blob: 172d2aa8101663ad3fb02cf0cf0f59e505b10d3c [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 Etuaho8d5571a2018-04-23 12:29:31 +03001297 if (context->getExtensions().webglCompatibility)
1298 {
1299 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1300 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
1301 {
1302 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1303 return false;
1304 }
1305 }
1306
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001307 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1308
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001309 if (mask & GL_COLOR_BUFFER_BIT)
1310 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001311 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001312 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001313
He Yunchao66a41a22016-12-15 16:45:05 +08001314 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001315 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001316 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001317
Geoff Langa15472a2015-08-11 11:48:03 -04001318 for (size_t drawbufferIdx = 0;
1319 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001320 {
Geoff Langa15472a2015-08-11 11:48:03 -04001321 const FramebufferAttachment *attachment =
1322 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1323 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001324 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001325 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001326
Geoff Langb2f3d052013-08-13 12:49:27 -04001327 // The GL ES 3.0.2 spec (pg 193) states that:
1328 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001329 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1330 // as well
1331 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1332 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001333 // Changes with EXT_color_buffer_float:
1334 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001335 GLenum readComponentType = readFormat.info->componentType;
1336 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001337 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001338 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001339 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001340 drawComponentType == GL_SIGNED_NORMALIZED);
1341
1342 if (extensions.colorBufferFloat)
1343 {
1344 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1345 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1346
1347 if (readFixedOrFloat != drawFixedOrFloat)
1348 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001349 context->handleError(InvalidOperation()
1350 << "If the read buffer contains fixed-point or "
1351 "floating-point values, the draw buffer must "
1352 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001353 return false;
1354 }
1355 }
1356 else if (readFixedPoint != drawFixedPoint)
1357 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001358 context->handleError(InvalidOperation()
1359 << "If the read buffer contains fixed-point values, "
1360 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001361 return false;
1362 }
1363
1364 if (readComponentType == GL_UNSIGNED_INT &&
1365 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001366 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001367 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001368 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001369 }
1370
Jamie Madill6163c752015-12-07 16:32:59 -05001371 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001372 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001373 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001374 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001375 }
1376
Jamie Madilla3944d42016-07-22 22:13:26 -04001377 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001378 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001379 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001380 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001381 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001382 }
Geoff Lange4915782017-04-12 15:19:07 -04001383
1384 if (context->getExtensions().webglCompatibility &&
1385 *readColorBuffer == *attachment)
1386 {
1387 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001388 InvalidOperation()
1389 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001390 return false;
1391 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001392 }
1393 }
1394
Jamie Madilla3944d42016-07-22 22:13:26 -04001395 if ((readFormat.info->componentType == GL_INT ||
1396 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1397 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001398 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001399 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001400 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001401 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001402 }
He Yunchao66a41a22016-12-15 16:45:05 +08001403 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1404 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1405 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1406 // situation is an application error that would lead to a crash in ANGLE.
1407 else if (drawFramebuffer->hasEnabledDrawBuffer())
1408 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001409 context->handleError(
1410 InvalidOperation()
1411 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001412 return false;
1413 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001414 }
1415
He Yunchaoced53ae2016-11-29 15:00:51 +08001416 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001417 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1418 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001419 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001420 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001421 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001422 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001423 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001424 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001425 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001426
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001427 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001428 {
Kenneth Russell69382852017-07-21 16:38:44 -04001429 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001430 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001431 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001432 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001433 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001434
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001435 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001436 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001437 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001438 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001439 }
Geoff Lange4915782017-04-12 15:19:07 -04001440
1441 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1442 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001443 context->handleError(
1444 InvalidOperation()
1445 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001446 return false;
1447 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001448 }
He Yunchao66a41a22016-12-15 16:45:05 +08001449 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1450 else if (drawBuffer)
1451 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001452 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1453 "depth/stencil attachment of a "
1454 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001455 return false;
1456 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001457 }
1458 }
1459
Martin Radeva3ed4572017-07-27 18:29:37 +03001460 // ANGLE_multiview, Revision 1:
1461 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1462 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1463 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1464 {
1465 context->handleError(InvalidFramebufferOperation()
1466 << "Attempt to read from a multi-view framebuffer.");
1467 return false;
1468 }
1469 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1470 {
1471 context->handleError(InvalidFramebufferOperation()
1472 << "Attempt to write to a multi-view framebuffer.");
1473 return false;
1474 }
1475
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001476 return true;
1477}
1478
Jamie Madill4928b7c2017-06-20 12:57:39 -04001479bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001480 GLint x,
1481 GLint y,
1482 GLsizei width,
1483 GLsizei height,
1484 GLenum format,
1485 GLenum type,
1486 GLsizei bufSize,
1487 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001488 GLsizei *columns,
1489 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001490 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001491{
1492 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001493 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001494 return false;
1495 }
1496
Brandon Jonesd1049182018-03-28 10:02:20 -07001497 GLsizei writeLength = 0;
1498 GLsizei writeColumns = 0;
1499 GLsizei writeRows = 0;
1500
1501 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1502 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001503 {
Geoff Langb1196682014-07-23 13:47:29 -04001504 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001505 }
1506
Brandon Jonesd1049182018-03-28 10:02:20 -07001507 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001508 {
Geoff Langb1196682014-07-23 13:47:29 -04001509 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001510 }
1511
Brandon Jonesd1049182018-03-28 10:02:20 -07001512 SetRobustLengthParam(length, writeLength);
1513 SetRobustLengthParam(columns, writeColumns);
1514 SetRobustLengthParam(rows, writeRows);
1515
Jamie Madillc29968b2016-01-20 11:17:23 -05001516 return true;
1517}
1518
1519bool ValidateReadnPixelsEXT(Context *context,
1520 GLint x,
1521 GLint y,
1522 GLsizei width,
1523 GLsizei height,
1524 GLenum format,
1525 GLenum type,
1526 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001527 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001528{
1529 if (bufSize < 0)
1530 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001531 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001532 return false;
1533 }
1534
Geoff Lang62fce5b2016-09-30 10:46:35 -04001535 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001536 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001537}
Jamie Madill26e91952014-03-05 15:01:27 -05001538
Jamie Madill4928b7c2017-06-20 12:57:39 -04001539bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001540 GLint x,
1541 GLint y,
1542 GLsizei width,
1543 GLsizei height,
1544 GLenum format,
1545 GLenum type,
1546 GLsizei bufSize,
1547 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001548 GLsizei *columns,
1549 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001550 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001551{
Brandon Jonesd1049182018-03-28 10:02:20 -07001552 GLsizei writeLength = 0;
1553 GLsizei writeColumns = 0;
1554 GLsizei writeRows = 0;
1555
Geoff Lang62fce5b2016-09-30 10:46:35 -04001556 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001557 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001558 return false;
1559 }
1560
Brandon Jonesd1049182018-03-28 10:02:20 -07001561 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1562 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001563 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001564 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001565 }
1566
Brandon Jonesd1049182018-03-28 10:02:20 -07001567 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001568 {
1569 return false;
1570 }
1571
Brandon Jonesd1049182018-03-28 10:02:20 -07001572 SetRobustLengthParam(length, writeLength);
1573 SetRobustLengthParam(columns, writeColumns);
1574 SetRobustLengthParam(rows, writeRows);
1575
Geoff Lang62fce5b2016-09-30 10:46:35 -04001576 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001577}
1578
Jamie Madillf0e04492017-08-26 15:28:42 -04001579bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001580{
1581 if (!context->getExtensions().occlusionQueryBoolean &&
1582 !context->getExtensions().disjointTimerQuery)
1583 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001584 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001585 return false;
1586 }
1587
Olli Etuaho41997e72016-03-10 13:38:39 +02001588 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001589}
1590
Jamie Madillf0e04492017-08-26 15:28:42 -04001591bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001592{
1593 if (!context->getExtensions().occlusionQueryBoolean &&
1594 !context->getExtensions().disjointTimerQuery)
1595 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001596 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001597 return false;
1598 }
1599
Olli Etuaho41997e72016-03-10 13:38:39 +02001600 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001601}
1602
Jamie Madillf0e04492017-08-26 15:28:42 -04001603bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1604{
1605 if (!context->getExtensions().occlusionQueryBoolean &&
1606 !context->getExtensions().disjointTimerQuery)
1607 {
1608 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1609 return false;
1610 }
1611
1612 return true;
1613}
1614
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001615bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001616{
1617 if (!ValidQueryType(context, target))
1618 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001619 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001620 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001621 }
1622
1623 if (id == 0)
1624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001625 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001626 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001627 }
1628
1629 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1630 // of zero, if the active query object name for <target> is non-zero (for the
1631 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1632 // the active query for either target is non-zero), if <id> is the name of an
1633 // existing query object whose type does not match <target>, or if <id> is the
1634 // active query object name for any query type, the error INVALID_OPERATION is
1635 // generated.
1636
1637 // Ensure no other queries are active
1638 // NOTE: If other queries than occlusion are supported, we will need to check
1639 // separately that:
1640 // a) The query ID passed is not the current active query for any target/type
1641 // b) There are no active queries for the requested target (and in the case
1642 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1643 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001644
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001645 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001647 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001648 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001649 }
1650
1651 Query *queryObject = context->getQuery(id, true, target);
1652
1653 // check that name was obtained with glGenQueries
1654 if (!queryObject)
1655 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001656 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001657 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001658 }
1659
1660 // check for type mismatch
1661 if (queryObject->getType() != target)
1662 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001663 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001664 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001665 }
1666
1667 return true;
1668}
1669
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001670bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1671{
1672 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001673 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001674 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001675 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001676 return false;
1677 }
1678
1679 return ValidateBeginQueryBase(context, target, id);
1680}
1681
1682bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001683{
1684 if (!ValidQueryType(context, target))
1685 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001686 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001687 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001688 }
1689
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001690 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001691
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001692 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001693 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001694 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001695 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001696 }
1697
Jamie Madill45c785d2014-05-13 14:09:34 -04001698 return true;
1699}
1700
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001701bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1702{
1703 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001704 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001705 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001706 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001707 return false;
1708 }
1709
1710 return ValidateEndQueryBase(context, target);
1711}
1712
1713bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1714{
1715 if (!context->getExtensions().disjointTimerQuery)
1716 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001717 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001718 return false;
1719 }
1720
1721 if (target != GL_TIMESTAMP_EXT)
1722 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001723 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001724 return false;
1725 }
1726
1727 Query *queryObject = context->getQuery(id, true, target);
1728 if (queryObject == nullptr)
1729 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001730 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001731 return false;
1732 }
1733
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001734 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001735 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001736 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001737 return false;
1738 }
1739
1740 return true;
1741}
1742
Geoff Lang2186c382016-10-14 10:54:54 -04001743bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001744{
Geoff Lang2186c382016-10-14 10:54:54 -04001745 if (numParams)
1746 {
1747 *numParams = 0;
1748 }
1749
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001750 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1751 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001752 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001753 return false;
1754 }
1755
1756 switch (pname)
1757 {
1758 case GL_CURRENT_QUERY_EXT:
1759 if (target == GL_TIMESTAMP_EXT)
1760 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001761 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001762 return false;
1763 }
1764 break;
1765 case GL_QUERY_COUNTER_BITS_EXT:
1766 if (!context->getExtensions().disjointTimerQuery ||
1767 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1768 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001769 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001770 return false;
1771 }
1772 break;
1773 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001774 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001775 return false;
1776 }
1777
Geoff Lang2186c382016-10-14 10:54:54 -04001778 if (numParams)
1779 {
1780 // All queries return only one value
1781 *numParams = 1;
1782 }
1783
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001784 return true;
1785}
1786
1787bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1788{
1789 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001790 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001791 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001792 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001793 return false;
1794 }
1795
Geoff Lang2186c382016-10-14 10:54:54 -04001796 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001797}
1798
Geoff Lang2186c382016-10-14 10:54:54 -04001799bool ValidateGetQueryivRobustANGLE(Context *context,
1800 GLenum target,
1801 GLenum pname,
1802 GLsizei bufSize,
1803 GLsizei *length,
1804 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001805{
Geoff Lang2186c382016-10-14 10:54:54 -04001806 if (!ValidateRobustEntryPoint(context, bufSize))
1807 {
1808 return false;
1809 }
1810
Brandon Jonesd1049182018-03-28 10:02:20 -07001811 GLsizei numParams = 0;
1812
1813 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001814 {
1815 return false;
1816 }
1817
Brandon Jonesd1049182018-03-28 10:02:20 -07001818 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001819 {
1820 return false;
1821 }
1822
Brandon Jonesd1049182018-03-28 10:02:20 -07001823 SetRobustLengthParam(length, numParams);
1824
Geoff Lang2186c382016-10-14 10:54:54 -04001825 return true;
1826}
1827
1828bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1829{
1830 if (numParams)
1831 {
1832 *numParams = 0;
1833 }
1834
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001835 Query *queryObject = context->getQuery(id, false, GL_NONE);
1836
1837 if (!queryObject)
1838 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001839 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001840 return false;
1841 }
1842
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001843 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001844 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001845 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001846 return false;
1847 }
1848
1849 switch (pname)
1850 {
1851 case GL_QUERY_RESULT_EXT:
1852 case GL_QUERY_RESULT_AVAILABLE_EXT:
1853 break;
1854
1855 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001856 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001857 return false;
1858 }
1859
Geoff Lang2186c382016-10-14 10:54:54 -04001860 if (numParams)
1861 {
1862 *numParams = 1;
1863 }
1864
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001865 return true;
1866}
1867
1868bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1869{
1870 if (!context->getExtensions().disjointTimerQuery)
1871 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001872 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001873 return false;
1874 }
Geoff Lang2186c382016-10-14 10:54:54 -04001875 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1876}
1877
1878bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1879 GLuint id,
1880 GLenum pname,
1881 GLsizei bufSize,
1882 GLsizei *length,
1883 GLint *params)
1884{
1885 if (!context->getExtensions().disjointTimerQuery)
1886 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001887 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001888 return false;
1889 }
1890
1891 if (!ValidateRobustEntryPoint(context, bufSize))
1892 {
1893 return false;
1894 }
1895
Brandon Jonesd1049182018-03-28 10:02:20 -07001896 GLsizei numParams = 0;
1897
1898 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001899 {
1900 return false;
1901 }
1902
Brandon Jonesd1049182018-03-28 10:02:20 -07001903 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001904 {
1905 return false;
1906 }
1907
Brandon Jonesd1049182018-03-28 10:02:20 -07001908 SetRobustLengthParam(length, numParams);
1909
Geoff Lang2186c382016-10-14 10:54:54 -04001910 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001911}
1912
1913bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1914{
1915 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001916 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001917 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001918 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001919 return false;
1920 }
Geoff Lang2186c382016-10-14 10:54:54 -04001921 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1922}
1923
1924bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1925 GLuint id,
1926 GLenum pname,
1927 GLsizei bufSize,
1928 GLsizei *length,
1929 GLuint *params)
1930{
1931 if (!context->getExtensions().disjointTimerQuery &&
1932 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1933 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001934 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001935 return false;
1936 }
1937
1938 if (!ValidateRobustEntryPoint(context, bufSize))
1939 {
1940 return false;
1941 }
1942
Brandon Jonesd1049182018-03-28 10:02:20 -07001943 GLsizei numParams = 0;
1944
1945 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001946 {
1947 return false;
1948 }
1949
Brandon Jonesd1049182018-03-28 10:02:20 -07001950 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001951 {
1952 return false;
1953 }
1954
Brandon Jonesd1049182018-03-28 10:02:20 -07001955 SetRobustLengthParam(length, numParams);
1956
Geoff Lang2186c382016-10-14 10:54:54 -04001957 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001958}
1959
1960bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1961{
1962 if (!context->getExtensions().disjointTimerQuery)
1963 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001964 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001965 return false;
1966 }
Geoff Lang2186c382016-10-14 10:54:54 -04001967 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1968}
1969
1970bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1971 GLuint id,
1972 GLenum pname,
1973 GLsizei bufSize,
1974 GLsizei *length,
1975 GLint64 *params)
1976{
1977 if (!context->getExtensions().disjointTimerQuery)
1978 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001979 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001980 return false;
1981 }
1982
1983 if (!ValidateRobustEntryPoint(context, bufSize))
1984 {
1985 return false;
1986 }
1987
Brandon Jonesd1049182018-03-28 10:02:20 -07001988 GLsizei numParams = 0;
1989
1990 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001991 {
1992 return false;
1993 }
1994
Brandon Jonesd1049182018-03-28 10:02:20 -07001995 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001996 {
1997 return false;
1998 }
1999
Brandon Jonesd1049182018-03-28 10:02:20 -07002000 SetRobustLengthParam(length, numParams);
2001
Geoff Lang2186c382016-10-14 10:54:54 -04002002 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002003}
2004
2005bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2006{
2007 if (!context->getExtensions().disjointTimerQuery)
2008 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002009 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002010 return false;
2011 }
Geoff Lang2186c382016-10-14 10:54:54 -04002012 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2013}
2014
2015bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2016 GLuint id,
2017 GLenum pname,
2018 GLsizei bufSize,
2019 GLsizei *length,
2020 GLuint64 *params)
2021{
2022 if (!context->getExtensions().disjointTimerQuery)
2023 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002024 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002025 return false;
2026 }
2027
2028 if (!ValidateRobustEntryPoint(context, bufSize))
2029 {
2030 return false;
2031 }
2032
Brandon Jonesd1049182018-03-28 10:02:20 -07002033 GLsizei numParams = 0;
2034
2035 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002036 {
2037 return false;
2038 }
2039
Brandon Jonesd1049182018-03-28 10:02:20 -07002040 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002041 {
2042 return false;
2043 }
2044
Brandon Jonesd1049182018-03-28 10:02:20 -07002045 SetRobustLengthParam(length, numParams);
2046
Geoff Lang2186c382016-10-14 10:54:54 -04002047 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002048}
2049
Jamie Madill5b772312018-03-08 20:28:32 -05002050bool ValidateUniformCommonBase(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002051 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002052 GLint location,
2053 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002054 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002055{
Jiajia Qin5451d532017-11-16 17:16:34 +08002056 // TODO(Jiajia): Add image uniform check in future.
2057 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002058 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002059 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002060 return false;
2061 }
2062
Jiajia Qin5451d532017-11-16 17:16:34 +08002063 if (!program)
2064 {
2065 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2066 return false;
2067 }
2068
2069 if (!program->isLinked())
2070 {
2071 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2072 return false;
2073 }
2074
2075 if (location == -1)
2076 {
2077 // Silently ignore the uniform command
2078 return false;
2079 }
2080
2081 const auto &uniformLocations = program->getUniformLocations();
2082 size_t castedLocation = static_cast<size_t>(location);
2083 if (castedLocation >= uniformLocations.size())
2084 {
2085 context->handleError(InvalidOperation() << "Invalid uniform location");
2086 return false;
2087 }
2088
2089 const auto &uniformLocation = uniformLocations[castedLocation];
2090 if (uniformLocation.ignored)
2091 {
2092 // Silently ignore the uniform command
2093 return false;
2094 }
2095
2096 if (!uniformLocation.used())
2097 {
2098 context->handleError(InvalidOperation());
2099 return false;
2100 }
2101
2102 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2103
2104 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2105 if (!uniform.isArray() && count > 1)
2106 {
2107 context->handleError(InvalidOperation());
2108 return false;
2109 }
2110
2111 *uniformOut = &uniform;
2112 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002113}
2114
Jamie Madill5b772312018-03-08 20:28:32 -05002115bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002116 GLenum uniformType,
2117 GLsizei count,
2118 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002119{
Jiajia Qin5451d532017-11-16 17:16:34 +08002120 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2121 // It is compatible with INT or BOOL.
2122 // Do these cheap tests first, for a little extra speed.
2123 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002124 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002125 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002126 }
2127
Jiajia Qin5451d532017-11-16 17:16:34 +08002128 if (IsSamplerType(uniformType))
2129 {
2130 // Check that the values are in range.
2131 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2132 for (GLsizei i = 0; i < count; ++i)
2133 {
2134 if (value[i] < 0 || value[i] >= max)
2135 {
2136 context->handleError(InvalidValue() << "sampler uniform value out of range");
2137 return false;
2138 }
2139 }
2140 return true;
2141 }
2142
2143 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2144 return false;
2145}
2146
Jamie Madill5b772312018-03-08 20:28:32 -05002147bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002148{
2149 // Check that the value type is compatible with uniform type.
2150 // Do the cheaper test first, for a little extra speed.
2151 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2152 {
2153 return true;
2154 }
2155
2156 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2157 return false;
2158}
2159
Jamie Madill5b772312018-03-08 20:28:32 -05002160bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002161{
2162 // Check that the value type is compatible with uniform type.
2163 if (valueType == uniformType)
2164 {
2165 return true;
2166 }
2167
2168 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2169 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002170}
2171
Jamie Madill5b772312018-03-08 20:28:32 -05002172bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002173{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002174 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002175 gl::Program *programObject = context->getGLState().getProgram();
2176 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2177 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002178}
2179
Jamie Madill5b772312018-03-08 20:28:32 -05002180bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002181{
2182 const LinkedUniform *uniform = nullptr;
2183 gl::Program *programObject = context->getGLState().getProgram();
2184 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2185 ValidateUniform1ivValue(context, uniform->type, count, value);
2186}
2187
Jamie Madill5b772312018-03-08 20:28:32 -05002188bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002189 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002190 GLint location,
2191 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002192 GLboolean transpose)
2193{
Geoff Lang92019432017-11-20 13:09:34 -05002194 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002195 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002196 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002197 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002198 }
2199
Jamie Madill62d31cb2015-09-11 13:25:51 -04002200 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002201 gl::Program *programObject = context->getGLState().getProgram();
2202 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2203 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002204}
2205
Jamie Madill5b772312018-03-08 20:28:32 -05002206bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002207{
2208 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2209 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002210 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002211 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002212 }
2213
Jamie Madill0af26e12015-03-05 19:54:33 -05002214 const Caps &caps = context->getCaps();
2215
Jamie Madill893ab082014-05-16 16:56:10 -04002216 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2217 {
2218 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2219
Jamie Madill0af26e12015-03-05 19:54:33 -05002220 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002221 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002222 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002223 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002224 }
2225 }
2226
2227 switch (pname)
2228 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002229 case GL_TEXTURE_BINDING_2D:
2230 case GL_TEXTURE_BINDING_CUBE_MAP:
2231 case GL_TEXTURE_BINDING_3D:
2232 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002233 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002234 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002235 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2236 if (!context->getExtensions().textureRectangle)
2237 {
2238 context->handleError(InvalidEnum()
2239 << "ANGLE_texture_rectangle extension not present");
2240 return false;
2241 }
2242 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002243 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2244 if (!context->getExtensions().eglStreamConsumerExternal &&
2245 !context->getExtensions().eglImageExternal)
2246 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002247 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2248 "nor GL_OES_EGL_image_external "
2249 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002250 return false;
2251 }
2252 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002253
He Yunchaoced53ae2016-11-29 15:00:51 +08002254 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2255 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002256 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002257 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2258 ASSERT(readFramebuffer);
2259
Jamie Madill427064d2018-04-13 16:20:34 -04002260 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002261 {
Geoff Langb1196682014-07-23 13:47:29 -04002262 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002263 }
2264
Jamie Madille98b1b52018-03-08 09:47:23 -05002265 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002266 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002267 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002268 return false;
2269 }
2270
Jamie Madille98b1b52018-03-08 09:47:23 -05002271 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002272 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002273 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002274 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002275 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002276 }
2277 }
2278 break;
2279
He Yunchaoced53ae2016-11-29 15:00:51 +08002280 default:
2281 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002282 }
2283
2284 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002285 if (*numParams == 0)
2286 {
2287 return false;
2288 }
2289
2290 return true;
2291}
2292
Brandon Jonesd1049182018-03-28 10:02:20 -07002293bool ValidateGetBooleanvRobustANGLE(Context *context,
2294 GLenum pname,
2295 GLsizei bufSize,
2296 GLsizei *length,
2297 GLboolean *params)
2298{
2299 GLenum nativeType;
2300 unsigned int numParams = 0;
2301
2302 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2303 {
2304 return false;
2305 }
2306
2307 SetRobustLengthParam(length, numParams);
2308
2309 return true;
2310}
2311
2312bool ValidateGetFloatvRobustANGLE(Context *context,
2313 GLenum pname,
2314 GLsizei bufSize,
2315 GLsizei *length,
2316 GLfloat *params)
2317{
2318 GLenum nativeType;
2319 unsigned int numParams = 0;
2320
2321 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2322 {
2323 return false;
2324 }
2325
2326 SetRobustLengthParam(length, numParams);
2327
2328 return true;
2329}
2330
2331bool ValidateGetIntegervRobustANGLE(Context *context,
2332 GLenum pname,
2333 GLsizei bufSize,
2334 GLsizei *length,
2335 GLint *data)
2336{
2337 GLenum nativeType;
2338 unsigned int numParams = 0;
2339
2340 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2341 {
2342 return false;
2343 }
2344
2345 SetRobustLengthParam(length, numParams);
2346
2347 return true;
2348}
2349
2350bool ValidateGetInteger64vRobustANGLE(Context *context,
2351 GLenum pname,
2352 GLsizei bufSize,
2353 GLsizei *length,
2354 GLint64 *data)
2355{
2356 GLenum nativeType;
2357 unsigned int numParams = 0;
2358
2359 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2360 {
2361 return false;
2362 }
2363
2364 if (nativeType == GL_INT_64_ANGLEX)
2365 {
2366 CastStateValues(context, nativeType, pname, numParams, data);
2367 return false;
2368 }
2369
2370 SetRobustLengthParam(length, numParams);
2371 return true;
2372}
2373
Jamie Madill5b772312018-03-08 20:28:32 -05002374bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002375 GLenum pname,
2376 GLsizei bufSize,
2377 GLenum *nativeType,
2378 unsigned int *numParams)
2379{
2380 if (!ValidateRobustEntryPoint(context, bufSize))
2381 {
2382 return false;
2383 }
2384
2385 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2386 {
2387 return false;
2388 }
2389
2390 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002391 {
2392 return false;
2393 }
2394
2395 return true;
2396}
2397
Jamie Madill5b772312018-03-08 20:28:32 -05002398bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002399 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002400 GLint level,
2401 GLenum internalformat,
2402 bool isSubImage,
2403 GLint xoffset,
2404 GLint yoffset,
2405 GLint zoffset,
2406 GLint x,
2407 GLint y,
2408 GLsizei width,
2409 GLsizei height,
2410 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002411 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002412{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002413 TextureType texType = TextureTargetToType(target);
2414
Brandon Jones6cad5662017-06-14 13:25:13 -07002415 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002416 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002417 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2418 return false;
2419 }
2420
2421 if (width < 0 || height < 0)
2422 {
2423 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002424 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002425 }
2426
He Yunchaoced53ae2016-11-29 15:00:51 +08002427 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2428 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002429 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002430 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002431 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002432 }
2433
2434 if (border != 0)
2435 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002436 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002437 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002438 }
2439
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002440 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002441 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002442 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002443 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002444 }
2445
Jamie Madille98b1b52018-03-08 09:47:23 -05002446 const gl::State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002447 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002448 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002449 {
Geoff Langb1196682014-07-23 13:47:29 -04002450 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002451 }
2452
Jamie Madille98b1b52018-03-08 09:47:23 -05002453 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002454 {
Geoff Langb1196682014-07-23 13:47:29 -04002455 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002456 }
2457
Martin Radev138064f2016-07-15 12:03:41 +03002458 if (readFramebuffer->getReadBufferState() == GL_NONE)
2459 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002460 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002461 return false;
2462 }
2463
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002464 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2465 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002466 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002467 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002468 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2469 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002470 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002471 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002472 return false;
2473 }
2474
Martin Radev04e2c3b2017-07-27 16:54:35 +03002475 // ANGLE_multiview spec, Revision 1:
2476 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2477 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2478 // is not NONE.
2479 if (source->getMultiviewLayout() != GL_NONE)
2480 {
2481 context->handleError(InvalidFramebufferOperation()
2482 << "The active read framebuffer object has multiview attachments.");
2483 return false;
2484 }
2485
Geoff Langaae65a42014-05-26 12:43:44 -04002486 const gl::Caps &caps = context->getCaps();
2487
Geoff Langaae65a42014-05-26 12:43:44 -04002488 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002489 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002490 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002491 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002492 maxDimension = caps.max2DTextureSize;
2493 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002494
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002495 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002496 maxDimension = caps.maxCubeMapTextureSize;
2497 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002498
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002499 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002500 maxDimension = caps.maxRectangleTextureSize;
2501 break;
2502
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002503 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002504 maxDimension = caps.max2DTextureSize;
2505 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002506
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002507 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002508 maxDimension = caps.max3DTextureSize;
2509 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002510
He Yunchaoced53ae2016-11-29 15:00:51 +08002511 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002512 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002513 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002514 }
2515
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002516 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002517 if (!texture)
2518 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002519 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002520 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002521 }
2522
Geoff Lang69cce582015-09-17 13:20:36 -04002523 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002524 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002525 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002526 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002527 }
2528
Geoff Langca271392017-04-05 12:30:00 -04002529 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002530 isSubImage ? *texture->getFormat(target, level).info
2531 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002532
Geoff Lang966c9402017-04-18 12:38:27 -04002533 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002534 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002535 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002536 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002537 }
2538
2539 if (isSubImage)
2540 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002541 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2542 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2543 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002544 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002545 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002546 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002547 }
2548 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002549 else
2550 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002551 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002552 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002553 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002554 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002555 }
2556
Geoff Langeb66a6e2016-10-31 13:06:12 -04002557 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002558 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002559 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002560 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002561 }
2562
2563 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002564 if (static_cast<int>(width) > maxLevelDimension ||
2565 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002566 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002567 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002568 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002569 }
2570 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002571
Jamie Madill0c8abca2016-07-22 20:21:26 -04002572 if (textureFormatOut)
2573 {
2574 *textureFormatOut = texture->getFormat(target, level);
2575 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002576
2577 // Detect texture copying feedback loops for WebGL.
2578 if (context->getExtensions().webglCompatibility)
2579 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002580 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002581 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002582 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002583 return false;
2584 }
2585 }
2586
Jamie Madill560a8d82014-05-21 13:06:20 -04002587 return true;
2588}
2589
Jamie Madill5b772312018-03-08 20:28:32 -05002590bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002591{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002592 const Extensions &extensions = context->getExtensions();
2593
Jamie Madill1aeb1312014-06-20 13:21:25 -04002594 switch (mode)
2595 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002596 case GL_POINTS:
2597 case GL_LINES:
2598 case GL_LINE_LOOP:
2599 case GL_LINE_STRIP:
2600 case GL_TRIANGLES:
2601 case GL_TRIANGLE_STRIP:
2602 case GL_TRIANGLE_FAN:
2603 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002604
2605 case GL_LINES_ADJACENCY_EXT:
2606 case GL_LINE_STRIP_ADJACENCY_EXT:
2607 case GL_TRIANGLES_ADJACENCY_EXT:
2608 case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
2609 if (!extensions.geometryShader)
2610 {
2611 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2612 return false;
2613 }
2614 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002615 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002616 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002617 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002618 }
2619
Jamie Madill250d33f2014-06-06 17:09:03 -04002620 if (count < 0)
2621 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002622 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002623 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002624 }
2625
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002626 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002627
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002628 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2629 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2630 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2631 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002632 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002633 // Check for mapped buffers
2634 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002635 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002636 {
2637 context->handleError(InvalidOperation());
2638 return false;
2639 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002640 }
2641
Jamie Madillcbcde722017-01-06 14:50:00 -05002642 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2643 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002644 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002645 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002646 {
Ken Russellb9f92502018-01-27 19:00:26 -08002647 ASSERT(framebuffer);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002648 const FramebufferAttachment *dsAttachment =
2649 framebuffer->getStencilOrDepthStencilAttachment();
Ken Russellb9f92502018-01-27 19:00:26 -08002650 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2651 ASSERT(stencilBits <= 8);
2652
Jinyoung Hur85769f02015-10-20 17:08:44 -04002653 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Ken Russellb9f92502018-01-27 19:00:26 -08002654 if (depthStencilState.stencilTest && stencilBits > 0)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002655 {
Ken Russellb9f92502018-01-27 19:00:26 -08002656 GLuint maxStencilValue = (1 << stencilBits) - 1;
2657
2658 bool differentRefs =
2659 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2660 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2661 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2662 (depthStencilState.stencilBackWritemask & maxStencilValue);
2663 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2664 (depthStencilState.stencilBackMask & maxStencilValue);
2665
2666 if (differentRefs || differentWritemasks || differentMasks)
Jamie Madillcbcde722017-01-06 14:50:00 -05002667 {
Ken Russellb9f92502018-01-27 19:00:26 -08002668 if (!extensions.webglCompatibility)
2669 {
2670 ERR() << "This ANGLE implementation does not support separate front/back "
2671 "stencil writemasks, reference values, or stencil mask values.";
2672 }
2673 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
2674 return false;
Jamie Madillcbcde722017-01-06 14:50:00 -05002675 }
Geoff Lang3a86ad32015-09-01 11:47:05 -04002676 }
Jamie Madillac528012014-06-20 13:21:23 -04002677 }
2678
Jamie Madill427064d2018-04-13 16:20:34 -04002679 if (!ValidateFramebufferComplete(context, framebuffer))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002680 {
Geoff Langb1196682014-07-23 13:47:29 -04002681 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002682 }
2683
Geoff Lang7dd2e102014-11-10 15:19:26 -05002684 gl::Program *program = state.getProgram();
2685 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002686 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002687 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002688 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002689 }
2690
Yunchao Hecddcb592017-11-13 15:27:35 +08002691 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2692 // vertex shader stage or fragment shader stage is a undefined behaviour.
2693 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2694 // produce undefined result.
Jiawei Shao385b3e02018-03-21 09:43:28 +08002695 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2696 !program->hasLinkedShaderStage(ShaderType::Fragment))
Yunchao Hecddcb592017-11-13 15:27:35 +08002697 {
2698 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2699 "vertex shader stage or fragment shader stage.");
2700 return false;
2701 }
2702
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002703 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002705 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002706 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002707 }
2708
Martin Radevffe754b2017-07-31 10:38:07 +03002709 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002710 {
Martin Radevda8e2572017-09-12 17:21:16 +03002711 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002712 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002713 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002714 {
2715 context->handleError(InvalidOperation() << "The number of views in the active program "
2716 "and draw framebuffer does not match.");
2717 return false;
2718 }
Martin Radev7e69f762017-07-27 14:54:13 +03002719
2720 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2721 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2722 framebufferNumViews > 1)
2723 {
2724 context->handleError(InvalidOperation()
2725 << "There is an active transform feedback object "
2726 "when the number of views in the active draw "
2727 "framebuffer is greater than 1.");
2728 return false;
2729 }
Martin Radevffe754b2017-07-31 10:38:07 +03002730
2731 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2732 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2733 {
2734 context->handleError(InvalidOperation() << "There is an active query for target "
2735 "GL_TIME_ELAPSED_EXT when the number of "
2736 "views in the active draw framebuffer is "
2737 "greater than 1.");
2738 return false;
2739 }
Martin Radev7cf61662017-07-26 17:10:53 +03002740 }
2741
Jiawei Shaofccebff2018-03-08 13:51:02 +08002742 // Do geometry shader specific validations
Jiawei Shao385b3e02018-03-21 09:43:28 +08002743 if (program->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shaofccebff2018-03-08 13:51:02 +08002744 {
2745 if (!IsCompatibleDrawModeWithGeometryShader(mode,
2746 program->getGeometryShaderInputPrimitiveType()))
2747 {
2748 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2749 IncompatibleDrawModeAgainstGeometryShader);
2750 return false;
2751 }
2752 }
2753
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002754 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002755 for (unsigned int uniformBlockIndex = 0;
2756 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002757 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002758 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
Lingfeng Yang038dd532018-03-29 17:31:52 -07002759 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002760 const OffsetBindingPointer<Buffer> &uniformBuffer =
2761 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002762
Geoff Lang5d124a62015-09-15 13:03:27 -04002763 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002764 {
2765 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002766 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002767 InvalidOperation()
2768 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002769 return false;
2770 }
2771
James Darpinian30b604d2018-03-12 17:26:57 -07002772 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
Jamie Madill62d31cb2015-09-11 13:25:51 -04002773 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002774 {
2775 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002776 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002777 InvalidOperation()
2778 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002779 return false;
2780 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002781
2782 if (extensions.webglCompatibility &&
2783 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2784 {
2785 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2786 UniformBufferBoundForTransformFeedback);
2787 return false;
2788 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002789 }
2790
Geoff Lange0cff192017-05-30 13:04:56 -04002791 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002792 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002793 {
James Darpiniane8a93c62018-01-04 18:02:24 -08002794 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2795 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2796 transformFeedbackObject->buffersBoundForOtherUse())
2797 {
2798 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferDoubleBound);
2799 return false;
2800 }
Geoff Lange0cff192017-05-30 13:04:56 -04002801 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002802 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2803 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002804 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002805 return false;
2806 }
Geoff Lange0cff192017-05-30 13:04:56 -04002807
Geoff Lang9ab5b822017-05-30 16:19:23 -04002808 // Detect that the vertex shader input types match the attribute types
2809 if (!ValidateVertexShaderAttributeTypeMatch(context))
2810 {
2811 return false;
2812 }
2813
Geoff Lange0cff192017-05-30 13:04:56 -04002814 // Detect that the color buffer types match the fragment shader output types
2815 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2816 {
2817 return false;
2818 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002819 }
2820
Jamie Madill9fdaa492018-02-16 10:52:11 -05002821 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002822}
2823
Jamie Madill5b772312018-03-08 20:28:32 -05002824bool ValidateDrawArraysCommon(Context *context,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002825 GLenum mode,
2826 GLint first,
2827 GLsizei count,
2828 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002829{
Jamie Madillfd716582014-06-06 17:09:04 -04002830 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002831 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002832 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002833 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002834 }
2835
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002836 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002837 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002838 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002839 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002840 {
James Darpinian30b604d2018-03-12 17:26:57 -07002841 if (curTransformFeedback->getPrimitiveMode() != mode)
2842 {
2843 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
2844 // that does not match the current transform feedback object's draw mode (if transform
2845 // feedback
2846 // is active), (3.0.2, section 2.14, pg 86)
2847 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2848 return false;
2849 }
2850
2851 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2852 {
2853 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2854 return false;
2855 }
Jamie Madillfd716582014-06-06 17:09:04 -04002856 }
2857
Jiajia Qind9671222016-11-29 16:30:31 +08002858 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002859 {
2860 return false;
2861 }
2862
Corentin Wallez71168a02016-12-19 15:11:18 -08002863 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002864 // - first < 0 has been checked as an error condition.
2865 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002866 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002867 ASSERT(first >= 0);
2868 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002869 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002870 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2871 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2872 {
2873 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2874 return false;
2875 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002876
Jamie Madill9fdaa492018-02-16 10:52:11 -05002877 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2878 {
2879 return false;
2880 }
Jamie Madillfd716582014-06-06 17:09:04 -04002881 }
2882
2883 return true;
2884}
2885
He Yunchaoced53ae2016-11-29 15:00:51 +08002886bool ValidateDrawArraysInstancedANGLE(Context *context,
2887 GLenum mode,
2888 GLint first,
2889 GLsizei count,
2890 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002891{
Geoff Lang63c5a592017-09-27 14:08:16 -04002892 if (!context->getExtensions().instancedArrays)
2893 {
2894 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2895 return false;
2896 }
2897
Corentin Wallez170efbf2017-05-02 13:45:01 -04002898 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002899 {
2900 return false;
2901 }
2902
Corentin Wallez0dc97812017-06-22 14:38:44 -04002903 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002904}
2905
Jamie Madill5b772312018-03-08 20:28:32 -05002906bool ValidateDrawElementsBase(Context *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002907{
Jamie Madill250d33f2014-06-06 17:09:03 -04002908 switch (type)
2909 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002910 case GL_UNSIGNED_BYTE:
2911 case GL_UNSIGNED_SHORT:
2912 break;
2913 case GL_UNSIGNED_INT:
2914 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2915 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002916 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002917 return false;
2918 }
2919 break;
2920 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002921 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002922 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002923 }
2924
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002925 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002926
2927 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002928 if (curTransformFeedback && curTransformFeedback->isActive() &&
2929 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002930 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002931 // It is an invalid operation to call DrawElements, DrawRangeElements or
2932 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002933 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002934 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002935 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002936 }
2937
Jiajia Qind9671222016-11-29 16:30:31 +08002938 return true;
2939}
2940
Jamie Madill5b772312018-03-08 20:28:32 -05002941bool ValidateDrawElementsCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002942 GLenum mode,
2943 GLsizei count,
2944 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002945 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002946 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002947{
2948 if (!ValidateDrawElementsBase(context, type))
2949 return false;
2950
2951 const State &state = context->getGLState();
2952
Corentin Wallez170efbf2017-05-02 13:45:01 -04002953 if (!ValidateDrawBase(context, mode, count))
2954 {
2955 return false;
2956 }
2957
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002958 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2959 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2960 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2961 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002962 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002963 // Check for mapped buffers
2964 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002965 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002966 {
2967 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2968 return false;
2969 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002970 }
2971
He Yunchaoced53ae2016-11-29 15:00:51 +08002972 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002973 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002974
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002975 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2976
2977 if (context->getExtensions().webglCompatibility)
2978 {
2979 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2980 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2981 {
2982 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2983 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2984 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002985 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002986 return false;
2987 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002988
2989 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2990 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2991 // error is generated.
2992 if (reinterpret_cast<intptr_t>(indices) < 0)
2993 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002994 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002995 return false;
2996 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002997 }
2998
2999 if (context->getExtensions().webglCompatibility ||
3000 !context->getGLState().areClientArraysEnabled())
3001 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003002 if (!elementArrayBuffer && count > 0)
3003 {
3004 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3005 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3006 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003007 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003008 return false;
3009 }
3010 }
3011
Jamie Madill9fdaa492018-02-16 10:52:11 -05003012 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003013 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003014 // This is an application error that would normally result in a crash, but we catch it and
3015 // return an error
3016 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3017 return false;
3018 }
3019
3020 if (count > 0 && elementArrayBuffer)
3021 {
3022 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3023 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3024 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3025 constexpr uint64_t kMaxTypeSize = 8;
3026 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3027 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3028 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3029
3030 uint64_t typeSize = typeBytes;
3031 uint64_t elementCount = static_cast<uint64_t>(count);
3032 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3033
3034 // Doing the multiplication here is overflow-safe
3035 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3036
3037 // The offset can be any value, check for overflows
3038 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3039 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003040 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003041 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3042 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003043 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003044
3045 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3046 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003047 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003048 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3049 return false;
3050 }
3051
3052 ASSERT(isPow2(typeSize) && typeSize > 0);
3053 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3054 {
3055 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003056 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003057 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003058
3059 if (context->getExtensions().webglCompatibility &&
3060 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3061 {
3062 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3063 ElementArrayBufferBoundForTransformFeedback);
3064 return false;
3065 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003066 }
3067
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003068 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003069 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003070 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
3071 // access is enabled.
3072 if (!ValidateDrawAttribs(context, primcount, 0, 1))
3073 {
3074 return false;
3075 }
3076 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003077 else if (count == 0)
3078 {
3079 // ValidateDrawAttribs also does some extra validation that is independent of the vertex
3080 // count.
3081 if (!ValidateDrawAttribs(context, 0, 0, 0))
3082 {
3083 return false;
3084 }
3085 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003086 else
3087 {
3088 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003089 const DrawCallParams &params = context->getParams<DrawCallParams>();
3090 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3091 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003092
3093 // If we use an index greater than our maximum supported index range, return an error.
3094 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3095 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003096 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003097 {
3098 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3099 return false;
3100 }
3101
Jamie Madill6f5444d2018-03-14 10:08:11 -04003102 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end),
3103 static_cast<GLint>(indexRange.vertexCount())))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003104 {
3105 return false;
3106 }
3107
3108 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003109 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003110 }
3111
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003112 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003113}
3114
Jamie Madill5b772312018-03-08 20:28:32 -05003115bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003116 GLenum mode,
3117 GLsizei count,
3118 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003119 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003120 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003121{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003122 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003123}
3124
Geoff Lang3edfe032015-09-04 16:38:24 -04003125bool ValidateDrawElementsInstancedANGLE(Context *context,
3126 GLenum mode,
3127 GLsizei count,
3128 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003129 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003130 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003131{
Geoff Lang63c5a592017-09-27 14:08:16 -04003132 if (!context->getExtensions().instancedArrays)
3133 {
3134 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3135 return false;
3136 }
3137
Corentin Wallez170efbf2017-05-02 13:45:01 -04003138 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003139 {
3140 return false;
3141 }
3142
Corentin Wallez0dc97812017-06-22 14:38:44 -04003143 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003144}
3145
He Yunchaoced53ae2016-11-29 15:00:51 +08003146bool ValidateFramebufferTextureBase(Context *context,
3147 GLenum target,
3148 GLenum attachment,
3149 GLuint texture,
3150 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003151{
Geoff Lange8afa902017-09-27 15:00:43 -04003152 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003153 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003154 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003155 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003156 }
3157
3158 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003159 {
3160 return false;
3161 }
3162
Jamie Madill55ec3b12014-07-03 10:38:57 -04003163 if (texture != 0)
3164 {
3165 gl::Texture *tex = context->getTexture(texture);
3166
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003167 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003168 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003169 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003170 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003171 }
3172
3173 if (level < 0)
3174 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003175 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003176 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003177 }
3178 }
3179
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003180 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003181 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003182
Jamie Madill84115c92015-04-23 15:00:07 -04003183 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003184 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003185 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003186 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003187 }
3188
3189 return true;
3190}
3191
Geoff Langb1196682014-07-23 13:47:29 -04003192bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003193{
3194 if (program == 0)
3195 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003196 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003197 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003198 }
3199
Dian Xiang769769a2015-09-09 15:20:08 -07003200 gl::Program *programObject = GetValidProgram(context, program);
3201 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003202 {
3203 return false;
3204 }
3205
Jamie Madill0063c512014-08-25 15:47:53 -04003206 if (!programObject || !programObject->isLinked())
3207 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003208 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003209 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003210 }
3211
Geoff Lang7dd2e102014-11-10 15:19:26 -05003212 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003213 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003214 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003215 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003216 }
3217
Jamie Madill0063c512014-08-25 15:47:53 -04003218 return true;
3219}
3220
Geoff Langf41d0ee2016-10-07 13:04:23 -04003221static bool ValidateSizedGetUniform(Context *context,
3222 GLuint program,
3223 GLint location,
3224 GLsizei bufSize,
3225 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003226{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003227 if (length)
3228 {
3229 *length = 0;
3230 }
3231
Jamie Madill78f41802014-08-25 15:47:55 -04003232 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003233 {
Jamie Madill78f41802014-08-25 15:47:55 -04003234 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003235 }
3236
Geoff Langf41d0ee2016-10-07 13:04:23 -04003237 if (bufSize < 0)
3238 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003239 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003240 return false;
3241 }
3242
Jamie Madilla502c742014-08-28 17:19:13 -04003243 gl::Program *programObject = context->getProgram(program);
3244 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003245
Jamie Madill78f41802014-08-25 15:47:55 -04003246 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003247 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003248 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003249 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003250 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003251 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003252 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003253 }
3254
Geoff Langf41d0ee2016-10-07 13:04:23 -04003255 if (length)
3256 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003257 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003258 }
3259
Jamie Madill0063c512014-08-25 15:47:53 -04003260 return true;
3261}
3262
He Yunchaoced53ae2016-11-29 15:00:51 +08003263bool ValidateGetnUniformfvEXT(Context *context,
3264 GLuint program,
3265 GLint location,
3266 GLsizei bufSize,
3267 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003268{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003269 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003270}
3271
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003272bool ValidateGetnUniformfvRobustANGLE(Context *context,
3273 GLuint program,
3274 GLint location,
3275 GLsizei bufSize,
3276 GLsizei *length,
3277 GLfloat *params)
3278{
3279 UNIMPLEMENTED();
3280 return false;
3281}
3282
He Yunchaoced53ae2016-11-29 15:00:51 +08003283bool ValidateGetnUniformivEXT(Context *context,
3284 GLuint program,
3285 GLint location,
3286 GLsizei bufSize,
3287 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003288{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003289 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3290}
3291
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003292bool ValidateGetnUniformivRobustANGLE(Context *context,
3293 GLuint program,
3294 GLint location,
3295 GLsizei bufSize,
3296 GLsizei *length,
3297 GLint *params)
3298{
3299 UNIMPLEMENTED();
3300 return false;
3301}
3302
3303bool ValidateGetnUniformuivRobustANGLE(Context *context,
3304 GLuint program,
3305 GLint location,
3306 GLsizei bufSize,
3307 GLsizei *length,
3308 GLuint *params)
3309{
3310 UNIMPLEMENTED();
3311 return false;
3312}
3313
Geoff Langf41d0ee2016-10-07 13:04:23 -04003314bool ValidateGetUniformfvRobustANGLE(Context *context,
3315 GLuint program,
3316 GLint location,
3317 GLsizei bufSize,
3318 GLsizei *length,
3319 GLfloat *params)
3320{
3321 if (!ValidateRobustEntryPoint(context, bufSize))
3322 {
3323 return false;
3324 }
3325
Brandon Jonesd1049182018-03-28 10:02:20 -07003326 GLsizei writeLength = 0;
3327
Geoff Langf41d0ee2016-10-07 13:04:23 -04003328 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003329 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3330 {
3331 return false;
3332 }
3333
3334 SetRobustLengthParam(length, writeLength);
3335
3336 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003337}
3338
3339bool ValidateGetUniformivRobustANGLE(Context *context,
3340 GLuint program,
3341 GLint location,
3342 GLsizei bufSize,
3343 GLsizei *length,
3344 GLint *params)
3345{
3346 if (!ValidateRobustEntryPoint(context, bufSize))
3347 {
3348 return false;
3349 }
3350
Brandon Jonesd1049182018-03-28 10:02:20 -07003351 GLsizei writeLength = 0;
3352
Geoff Langf41d0ee2016-10-07 13:04:23 -04003353 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003354 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3355 {
3356 return false;
3357 }
3358
3359 SetRobustLengthParam(length, writeLength);
3360
3361 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003362}
3363
3364bool ValidateGetUniformuivRobustANGLE(Context *context,
3365 GLuint program,
3366 GLint location,
3367 GLsizei bufSize,
3368 GLsizei *length,
3369 GLuint *params)
3370{
3371 if (!ValidateRobustEntryPoint(context, bufSize))
3372 {
3373 return false;
3374 }
3375
3376 if (context->getClientMajorVersion() < 3)
3377 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003378 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003379 return false;
3380 }
3381
Brandon Jonesd1049182018-03-28 10:02:20 -07003382 GLsizei writeLength = 0;
3383
Geoff Langf41d0ee2016-10-07 13:04:23 -04003384 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003385 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3386 {
3387 return false;
3388 }
3389
3390 SetRobustLengthParam(length, writeLength);
3391
3392 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003393}
3394
He Yunchaoced53ae2016-11-29 15:00:51 +08003395bool ValidateDiscardFramebufferBase(Context *context,
3396 GLenum target,
3397 GLsizei numAttachments,
3398 const GLenum *attachments,
3399 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003400{
3401 if (numAttachments < 0)
3402 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003403 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003404 return false;
3405 }
3406
3407 for (GLsizei i = 0; i < numAttachments; ++i)
3408 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003409 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003410 {
3411 if (defaultFramebuffer)
3412 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003413 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003414 return false;
3415 }
3416
3417 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3418 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003419 context->handleError(InvalidOperation() << "Requested color attachment is "
3420 "greater than the maximum supported "
3421 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003422 return false;
3423 }
3424 }
3425 else
3426 {
3427 switch (attachments[i])
3428 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003429 case GL_DEPTH_ATTACHMENT:
3430 case GL_STENCIL_ATTACHMENT:
3431 case GL_DEPTH_STENCIL_ATTACHMENT:
3432 if (defaultFramebuffer)
3433 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003434 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3435 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003436 return false;
3437 }
3438 break;
3439 case GL_COLOR:
3440 case GL_DEPTH:
3441 case GL_STENCIL:
3442 if (!defaultFramebuffer)
3443 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003444 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3445 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003446 return false;
3447 }
3448 break;
3449 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003450 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003451 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003452 }
3453 }
3454 }
3455
3456 return true;
3457}
3458
Austin Kinross6ee1e782015-05-29 17:05:37 -07003459bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3460{
Jamie Madill007530e2017-12-28 14:27:04 -05003461 if (!context->getExtensions().debugMarker)
3462 {
3463 // The debug marker calls should not set error state
3464 // However, it seems reasonable to set an error state if the extension is not enabled
3465 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3466 return false;
3467 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003468
Jamie Madill007530e2017-12-28 14:27:04 -05003469 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003470 if (length < 0)
3471 {
3472 return false;
3473 }
3474
3475 if (marker == nullptr)
3476 {
3477 return false;
3478 }
3479
3480 return true;
3481}
3482
3483bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3484{
Jamie Madill007530e2017-12-28 14:27:04 -05003485 if (!context->getExtensions().debugMarker)
3486 {
3487 // The debug marker calls should not set error state
3488 // However, it seems reasonable to set an error state if the extension is not enabled
3489 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3490 return false;
3491 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003492
Jamie Madill007530e2017-12-28 14:27:04 -05003493 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003494 if (length < 0)
3495 {
3496 return false;
3497 }
3498
3499 if (length > 0 && marker == nullptr)
3500 {
3501 return false;
3502 }
3503
3504 return true;
3505}
3506
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003507bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003508{
Geoff Langa8406172015-07-21 16:53:39 -04003509 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3510 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003511 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003512 return false;
3513 }
3514
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003515 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003516 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003517 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003518 if (!context->getExtensions().eglImage)
3519 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003520 context->handleError(InvalidEnum()
3521 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003522 }
3523 break;
3524
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003525 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003526 if (!context->getExtensions().eglImageExternal)
3527 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003528 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3529 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003530 }
Geoff Langa8406172015-07-21 16:53:39 -04003531 break;
3532
3533 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003534 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003535 return false;
3536 }
3537
Jamie Madill007530e2017-12-28 14:27:04 -05003538 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3539
Jamie Madill61e16b42017-06-19 11:13:23 -04003540 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003541 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003542 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003543 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003544 return false;
3545 }
3546
Jamie Madill007530e2017-12-28 14:27:04 -05003547 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003548 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003549 context->handleError(InvalidOperation()
3550 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003551 return false;
3552 }
3553
Geoff Langca271392017-04-05 12:30:00 -04003554 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003555 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003556 if (!textureCaps.texturable)
3557 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003558 context->handleError(InvalidOperation()
3559 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003560 return false;
3561 }
3562
Geoff Langdcab33b2015-07-21 13:03:16 -04003563 return true;
3564}
3565
3566bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003567 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003568 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003569{
Geoff Langa8406172015-07-21 16:53:39 -04003570 if (!context->getExtensions().eglImage)
3571 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003572 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003573 return false;
3574 }
3575
3576 switch (target)
3577 {
3578 case GL_RENDERBUFFER:
3579 break;
3580
3581 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003582 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003583 return false;
3584 }
3585
Jamie Madill007530e2017-12-28 14:27:04 -05003586 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3587
Jamie Madill61e16b42017-06-19 11:13:23 -04003588 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003589 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003590 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003591 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003592 return false;
3593 }
3594
Geoff Langca271392017-04-05 12:30:00 -04003595 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003596 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003597 if (!textureCaps.renderable)
3598 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003599 context->handleError(InvalidOperation()
3600 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003601 return false;
3602 }
3603
Geoff Langdcab33b2015-07-21 13:03:16 -04003604 return true;
3605}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003606
3607bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3608{
Geoff Lang36167ab2015-12-07 10:27:14 -05003609 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003610 {
3611 // The default VAO should always exist
3612 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003613 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003614 return false;
3615 }
3616
3617 return true;
3618}
3619
Geoff Langc5629752015-12-07 16:29:04 -05003620bool ValidateProgramBinaryBase(Context *context,
3621 GLuint program,
3622 GLenum binaryFormat,
3623 const void *binary,
3624 GLint length)
3625{
3626 Program *programObject = GetValidProgram(context, program);
3627 if (programObject == nullptr)
3628 {
3629 return false;
3630 }
3631
3632 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3633 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3634 programBinaryFormats.end())
3635 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003636 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003637 return false;
3638 }
3639
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003640 if (context->hasActiveTransformFeedback(program))
3641 {
3642 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003643 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3644 "is associated with an active transform "
3645 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003646 return false;
3647 }
3648
Geoff Langc5629752015-12-07 16:29:04 -05003649 return true;
3650}
3651
3652bool ValidateGetProgramBinaryBase(Context *context,
3653 GLuint program,
3654 GLsizei bufSize,
3655 GLsizei *length,
3656 GLenum *binaryFormat,
3657 void *binary)
3658{
3659 Program *programObject = GetValidProgram(context, program);
3660 if (programObject == nullptr)
3661 {
3662 return false;
3663 }
3664
3665 if (!programObject->isLinked())
3666 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003667 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003668 return false;
3669 }
3670
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003671 if (context->getCaps().programBinaryFormats.empty())
3672 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003673 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003674 return false;
3675 }
3676
Geoff Langc5629752015-12-07 16:29:04 -05003677 return true;
3678}
Jamie Madillc29968b2016-01-20 11:17:23 -05003679
Jamie Madill5b772312018-03-08 20:28:32 -05003680bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003681{
3682 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003683 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003684 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003685 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3686 return false;
3687 }
3688 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3689 {
3690 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003691 return false;
3692 }
3693
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003694 ASSERT(context->getGLState().getDrawFramebuffer());
3695 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003696 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3697
3698 // This should come first before the check for the default frame buffer
3699 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3700 // rather than INVALID_OPERATION
3701 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3702 {
3703 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3704
3705 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003706 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3707 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003708 {
3709 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003710 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3711 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3712 // 3.1 is still a bit ambiguous about the error, but future specs are
3713 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003714 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003715 return false;
3716 }
3717 else if (bufs[colorAttachment] >= maxColorAttachment)
3718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003719 context->handleError(InvalidOperation()
3720 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003721 return false;
3722 }
3723 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3724 frameBufferId != 0)
3725 {
3726 // INVALID_OPERATION-GL is bound to buffer and ith argument
3727 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003728 context->handleError(InvalidOperation()
3729 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003730 return false;
3731 }
3732 }
3733
3734 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3735 // and n is not 1 or bufs is bound to value other than BACK and NONE
3736 if (frameBufferId == 0)
3737 {
3738 if (n != 1)
3739 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003740 context->handleError(InvalidOperation()
3741 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003742 return false;
3743 }
3744
3745 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3746 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003747 context->handleError(
3748 InvalidOperation()
3749 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003750 return false;
3751 }
3752 }
3753
3754 return true;
3755}
3756
Geoff Lang496c02d2016-10-20 11:38:11 -07003757bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003758 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003759 GLenum pname,
3760 GLsizei *length,
3761 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003762{
Geoff Lang496c02d2016-10-20 11:38:11 -07003763 if (length)
3764 {
3765 *length = 0;
3766 }
3767
3768 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3769 {
3770 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003771 InvalidOperation()
3772 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003773 return false;
3774 }
3775
Corentin Walleze4477002017-12-01 14:39:58 -05003776 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003777 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003778 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003779 return false;
3780 }
3781
Geoff Lang496c02d2016-10-20 11:38:11 -07003782 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003783 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003784 case GL_BUFFER_MAP_POINTER:
3785 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003786
Geoff Lang496c02d2016-10-20 11:38:11 -07003787 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003788 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003789 return false;
3790 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003791
3792 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3793 // target bound to zero generate an INVALID_OPERATION error."
3794 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003795 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003796 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003797 context->handleError(InvalidOperation()
3798 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003799 return false;
3800 }
3801
Geoff Lang496c02d2016-10-20 11:38:11 -07003802 if (length)
3803 {
3804 *length = 1;
3805 }
3806
Olli Etuaho4f667482016-03-30 15:56:35 +03003807 return true;
3808}
3809
Corentin Wallez336129f2017-10-17 15:55:40 -04003810bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003811{
Corentin Walleze4477002017-12-01 14:39:58 -05003812 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003813 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003814 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003815 return false;
3816 }
3817
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003818 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003819
3820 if (buffer == nullptr || !buffer->isMapped())
3821 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003822 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003823 return false;
3824 }
3825
3826 return true;
3827}
3828
3829bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003830 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003831 GLintptr offset,
3832 GLsizeiptr length,
3833 GLbitfield access)
3834{
Corentin Walleze4477002017-12-01 14:39:58 -05003835 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003836 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003837 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003838 return false;
3839 }
3840
Brandon Jones6cad5662017-06-14 13:25:13 -07003841 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003842 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003843 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3844 return false;
3845 }
3846
3847 if (length < 0)
3848 {
3849 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003850 return false;
3851 }
3852
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003853 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003854
3855 if (!buffer)
3856 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003857 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003858 return false;
3859 }
3860
3861 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003862 CheckedNumeric<size_t> checkedOffset(offset);
3863 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003864
Jamie Madille2e406c2016-06-02 13:04:10 -04003865 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003866 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003867 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003868 return false;
3869 }
3870
3871 // Check for invalid bits in the mask
3872 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3873 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3874 GL_MAP_UNSYNCHRONIZED_BIT;
3875
3876 if (access & ~(allAccessBits))
3877 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003878 context->handleError(InvalidValue()
3879 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003880 return false;
3881 }
3882
3883 if (length == 0)
3884 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003885 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003886 return false;
3887 }
3888
3889 if (buffer->isMapped())
3890 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003891 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003892 return false;
3893 }
3894
3895 // Check for invalid bit combinations
3896 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3897 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003898 context->handleError(InvalidOperation()
3899 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003900 return false;
3901 }
3902
3903 GLbitfield writeOnlyBits =
3904 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3905
3906 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3907 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003908 context->handleError(InvalidOperation()
3909 << "Invalid access bits when mapping buffer for reading: 0x"
3910 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003911 return false;
3912 }
3913
3914 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3915 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003916 context->handleError(
3917 InvalidOperation()
3918 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003919 return false;
3920 }
Geoff Lang79f71042017-08-14 16:43:43 -04003921
3922 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003923}
3924
3925bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003926 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003927 GLintptr offset,
3928 GLsizeiptr length)
3929{
Brandon Jones6cad5662017-06-14 13:25:13 -07003930 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003931 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003932 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3933 return false;
3934 }
3935
3936 if (length < 0)
3937 {
3938 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003939 return false;
3940 }
3941
Corentin Walleze4477002017-12-01 14:39:58 -05003942 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003943 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003944 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003945 return false;
3946 }
3947
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003948 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003949
3950 if (buffer == nullptr)
3951 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003952 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003953 return false;
3954 }
3955
3956 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3957 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003958 context->handleError(InvalidOperation()
3959 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003960 return false;
3961 }
3962
3963 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003964 CheckedNumeric<size_t> checkedOffset(offset);
3965 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003966
Jamie Madille2e406c2016-06-02 13:04:10 -04003967 if (!checkedSize.IsValid() ||
3968 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003969 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003970 context->handleError(InvalidValue()
3971 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003972 return false;
3973 }
3974
3975 return true;
3976}
3977
Olli Etuaho41997e72016-03-10 13:38:39 +02003978bool ValidateGenOrDelete(Context *context, GLint n)
3979{
3980 if (n < 0)
3981 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003982 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003983 return false;
3984 }
3985 return true;
3986}
3987
Jamie Madill5b772312018-03-08 20:28:32 -05003988bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003989{
3990 if (!context->getExtensions().robustClientMemory)
3991 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003992 context->handleError(InvalidOperation()
3993 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003994 return false;
3995 }
3996
3997 if (bufSize < 0)
3998 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003999 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004000 return false;
4001 }
4002
4003 return true;
4004}
4005
Jamie Madill5b772312018-03-08 20:28:32 -05004006bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004007{
4008 if (bufSize < numParams)
4009 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004010 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4011 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004012 return false;
4013 }
4014
4015 return true;
4016}
4017
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004018bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004019 GLenum target,
4020 GLenum attachment,
4021 GLenum pname,
4022 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004023{
Geoff Lange8afa902017-09-27 15:00:43 -04004024 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004025 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004026 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004027 return false;
4028 }
4029
4030 int clientVersion = context->getClientMajorVersion();
4031
4032 switch (pname)
4033 {
4034 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4035 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4036 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4037 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4038 break;
4039
Martin Radeve5285d22017-07-14 16:23:53 +03004040 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4041 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4042 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4043 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4044 if (clientVersion < 3 || !context->getExtensions().multiview)
4045 {
4046 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4047 return false;
4048 }
4049 break;
4050
Geoff Langff5b2d52016-09-07 11:32:23 -04004051 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4052 if (clientVersion < 3 && !context->getExtensions().sRGB)
4053 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004054 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004055 return false;
4056 }
4057 break;
4058
4059 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4060 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4061 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4062 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4063 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4064 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4065 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4066 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4067 if (clientVersion < 3)
4068 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004069 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004070 return false;
4071 }
4072 break;
4073
4074 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004075 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004076 return false;
4077 }
4078
4079 // Determine if the attachment is a valid enum
4080 switch (attachment)
4081 {
4082 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004083 case GL_DEPTH:
4084 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004085 if (clientVersion < 3)
4086 {
Geoff Langfa125c92017-10-24 13:01:46 -04004087 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004088 return false;
4089 }
4090 break;
4091
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004092 case GL_DEPTH_STENCIL_ATTACHMENT:
4093 if (clientVersion < 3 && !context->isWebGL1())
4094 {
4095 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4096 return false;
4097 }
4098 break;
4099
Geoff Langfa125c92017-10-24 13:01:46 -04004100 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004101 case GL_DEPTH_ATTACHMENT:
4102 case GL_STENCIL_ATTACHMENT:
4103 break;
4104
4105 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004106 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4107 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004108 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4109 {
Geoff Langfa125c92017-10-24 13:01:46 -04004110 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004111 return false;
4112 }
4113 break;
4114 }
4115
4116 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4117 ASSERT(framebuffer);
4118
4119 if (framebuffer->id() == 0)
4120 {
4121 if (clientVersion < 3)
4122 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004123 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004124 return false;
4125 }
4126
4127 switch (attachment)
4128 {
4129 case GL_BACK:
4130 case GL_DEPTH:
4131 case GL_STENCIL:
4132 break;
4133
4134 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004135 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004136 return false;
4137 }
4138 }
4139 else
4140 {
4141 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4142 {
4143 // Valid attachment query
4144 }
4145 else
4146 {
4147 switch (attachment)
4148 {
4149 case GL_DEPTH_ATTACHMENT:
4150 case GL_STENCIL_ATTACHMENT:
4151 break;
4152
4153 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004154 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004155 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004156 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004157 return false;
4158 }
4159 break;
4160
4161 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004162 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004163 return false;
4164 }
4165 }
4166 }
4167
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004168 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004169 if (attachmentObject)
4170 {
4171 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4172 attachmentObject->type() == GL_TEXTURE ||
4173 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4174
4175 switch (pname)
4176 {
4177 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4178 if (attachmentObject->type() != GL_RENDERBUFFER &&
4179 attachmentObject->type() != GL_TEXTURE)
4180 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004181 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004182 return false;
4183 }
4184 break;
4185
4186 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4187 if (attachmentObject->type() != GL_TEXTURE)
4188 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004189 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004190 return false;
4191 }
4192 break;
4193
4194 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4195 if (attachmentObject->type() != GL_TEXTURE)
4196 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004197 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004198 return false;
4199 }
4200 break;
4201
4202 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4203 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4204 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004205 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004206 return false;
4207 }
4208 break;
4209
4210 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4211 if (attachmentObject->type() != GL_TEXTURE)
4212 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004213 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004214 return false;
4215 }
4216 break;
4217
4218 default:
4219 break;
4220 }
4221 }
4222 else
4223 {
4224 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4225 // is NONE, then querying any other pname will generate INVALID_ENUM.
4226
4227 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4228 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4229 // INVALID_OPERATION for all other pnames
4230
4231 switch (pname)
4232 {
4233 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4234 break;
4235
4236 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4237 if (clientVersion < 3)
4238 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004239 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004240 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004241 return false;
4242 }
4243 break;
4244
4245 default:
4246 if (clientVersion < 3)
4247 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004248 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004249 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004250 return false;
4251 }
4252 else
4253 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004254 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004255 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004256 return false;
4257 }
4258 }
4259 }
4260
Martin Radeve5285d22017-07-14 16:23:53 +03004261 if (numParams)
4262 {
4263 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4264 {
4265 // Only when the viewport offsets are queried we can have a varying number of output
4266 // parameters.
4267 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4268 *numParams = numViews * 2;
4269 }
4270 else
4271 {
4272 // For all other queries we can have only one output parameter.
4273 *numParams = 1;
4274 }
4275 }
4276
Geoff Langff5b2d52016-09-07 11:32:23 -04004277 return true;
4278}
4279
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004280bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004281 GLenum target,
4282 GLenum attachment,
4283 GLenum pname,
4284 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004285 GLsizei *length,
4286 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004287{
4288 if (!ValidateRobustEntryPoint(context, bufSize))
4289 {
4290 return false;
4291 }
4292
Brandon Jonesd1049182018-03-28 10:02:20 -07004293 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004294 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004295 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004296 {
4297 return false;
4298 }
4299
Brandon Jonesd1049182018-03-28 10:02:20 -07004300 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004301 {
4302 return false;
4303 }
4304
Brandon Jonesd1049182018-03-28 10:02:20 -07004305 SetRobustLengthParam(length, numParams);
4306
Geoff Langff5b2d52016-09-07 11:32:23 -04004307 return true;
4308}
4309
Jamie Madill5b772312018-03-08 20:28:32 -05004310bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004311 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004312 GLenum pname,
4313 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004314 GLsizei *length,
4315 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004316{
4317 if (!ValidateRobustEntryPoint(context, bufSize))
4318 {
4319 return false;
4320 }
4321
Brandon Jonesd1049182018-03-28 10:02:20 -07004322 GLsizei numParams = 0;
4323
4324 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004325 {
4326 return false;
4327 }
4328
Brandon Jonesd1049182018-03-28 10:02:20 -07004329 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004330 {
4331 return false;
4332 }
4333
Brandon Jonesd1049182018-03-28 10:02:20 -07004334 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004335 return true;
4336}
4337
Jamie Madill5b772312018-03-08 20:28:32 -05004338bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004339 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004340 GLenum pname,
4341 GLsizei bufSize,
4342 GLsizei *length,
4343 GLint64 *params)
4344{
Brandon Jonesd1049182018-03-28 10:02:20 -07004345 GLsizei numParams = 0;
4346
Geoff Langebebe1c2016-10-14 12:01:31 -04004347 if (!ValidateRobustEntryPoint(context, bufSize))
4348 {
4349 return false;
4350 }
4351
Brandon Jonesd1049182018-03-28 10:02:20 -07004352 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004353 {
4354 return false;
4355 }
4356
Brandon Jonesd1049182018-03-28 10:02:20 -07004357 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004358 {
4359 return false;
4360 }
4361
Brandon Jonesd1049182018-03-28 10:02:20 -07004362 SetRobustLengthParam(length, numParams);
4363
Geoff Langff5b2d52016-09-07 11:32:23 -04004364 return true;
4365}
4366
Jamie Madill5b772312018-03-08 20:28:32 -05004367bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004368{
4369 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004370 if (numParams)
4371 {
4372 *numParams = 1;
4373 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004374
4375 Program *programObject = GetValidProgram(context, program);
4376 if (!programObject)
4377 {
4378 return false;
4379 }
4380
4381 switch (pname)
4382 {
4383 case GL_DELETE_STATUS:
4384 case GL_LINK_STATUS:
4385 case GL_VALIDATE_STATUS:
4386 case GL_INFO_LOG_LENGTH:
4387 case GL_ATTACHED_SHADERS:
4388 case GL_ACTIVE_ATTRIBUTES:
4389 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4390 case GL_ACTIVE_UNIFORMS:
4391 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4392 break;
4393
4394 case GL_PROGRAM_BINARY_LENGTH:
4395 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004397 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4398 "requires GL_OES_get_program_binary or "
4399 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004400 return false;
4401 }
4402 break;
4403
4404 case GL_ACTIVE_UNIFORM_BLOCKS:
4405 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4406 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4407 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4408 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4409 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4410 if (context->getClientMajorVersion() < 3)
4411 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004412 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004413 return false;
4414 }
4415 break;
4416
Yunchao He61afff12017-03-14 15:34:03 +08004417 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004418 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004419 if (context->getClientVersion() < Version(3, 1))
4420 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004421 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004422 return false;
4423 }
4424 break;
4425
Jiawei Shao6ae51612018-02-23 14:03:25 +08004426 case GL_COMPUTE_WORK_GROUP_SIZE:
4427 if (context->getClientVersion() < Version(3, 1))
4428 {
4429 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4430 return false;
4431 }
4432
4433 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4434 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4435 // program which has not been linked successfully, or which does not contain objects to
4436 // form a compute shader.
4437 if (!programObject->isLinked())
4438 {
4439 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4440 return false;
4441 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004442 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004443 {
4444 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4445 return false;
4446 }
4447 break;
4448
Jiawei Shao447bfac2018-03-14 14:23:40 +08004449 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4450 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4451 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4452 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4453 if (!context->getExtensions().geometryShader)
4454 {
4455 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4456 return false;
4457 }
4458
4459 // [EXT_geometry_shader] Chapter 7.12
4460 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4461 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4462 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4463 // successfully, or which does not contain objects to form a geometry shader.
4464 if (!programObject->isLinked())
4465 {
4466 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4467 return false;
4468 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004469 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004470 {
4471 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4472 return false;
4473 }
4474 break;
4475
Geoff Langff5b2d52016-09-07 11:32:23 -04004476 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004477 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004478 return false;
4479 }
4480
4481 return true;
4482}
4483
4484bool ValidateGetProgramivRobustANGLE(Context *context,
4485 GLuint program,
4486 GLenum pname,
4487 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004488 GLsizei *length,
4489 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004490{
4491 if (!ValidateRobustEntryPoint(context, bufSize))
4492 {
4493 return false;
4494 }
4495
Brandon Jonesd1049182018-03-28 10:02:20 -07004496 GLsizei numParams = 0;
4497
4498 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004499 {
4500 return false;
4501 }
4502
Brandon Jonesd1049182018-03-28 10:02:20 -07004503 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004504 {
4505 return false;
4506 }
4507
Brandon Jonesd1049182018-03-28 10:02:20 -07004508 SetRobustLengthParam(length, numParams);
4509
Geoff Langff5b2d52016-09-07 11:32:23 -04004510 return true;
4511}
4512
Geoff Lang740d9022016-10-07 11:20:52 -04004513bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4514 GLenum target,
4515 GLenum pname,
4516 GLsizei bufSize,
4517 GLsizei *length,
4518 GLint *params)
4519{
4520 if (!ValidateRobustEntryPoint(context, bufSize))
4521 {
4522 return false;
4523 }
4524
Brandon Jonesd1049182018-03-28 10:02:20 -07004525 GLsizei numParams = 0;
4526
4527 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004528 {
4529 return false;
4530 }
4531
Brandon Jonesd1049182018-03-28 10:02:20 -07004532 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004533 {
4534 return false;
4535 }
4536
Brandon Jonesd1049182018-03-28 10:02:20 -07004537 SetRobustLengthParam(length, numParams);
4538
Geoff Lang740d9022016-10-07 11:20:52 -04004539 return true;
4540}
4541
Geoff Langd7d0ed32016-10-07 11:33:51 -04004542bool ValidateGetShaderivRobustANGLE(Context *context,
4543 GLuint shader,
4544 GLenum pname,
4545 GLsizei bufSize,
4546 GLsizei *length,
4547 GLint *params)
4548{
4549 if (!ValidateRobustEntryPoint(context, bufSize))
4550 {
4551 return false;
4552 }
4553
Brandon Jonesd1049182018-03-28 10:02:20 -07004554 GLsizei numParams = 0;
4555
4556 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004557 {
4558 return false;
4559 }
4560
Brandon Jonesd1049182018-03-28 10:02:20 -07004561 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004562 {
4563 return false;
4564 }
4565
Brandon Jonesd1049182018-03-28 10:02:20 -07004566 SetRobustLengthParam(length, numParams);
4567
Geoff Langd7d0ed32016-10-07 11:33:51 -04004568 return true;
4569}
4570
Geoff Langc1984ed2016-10-07 12:41:00 -04004571bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004572 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004573 GLenum pname,
4574 GLsizei bufSize,
4575 GLsizei *length,
4576 GLfloat *params)
4577{
4578 if (!ValidateRobustEntryPoint(context, bufSize))
4579 {
4580 return false;
4581 }
4582
Brandon Jonesd1049182018-03-28 10:02:20 -07004583 GLsizei numParams = 0;
4584
4585 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004586 {
4587 return false;
4588 }
4589
Brandon Jonesd1049182018-03-28 10:02:20 -07004590 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004591 {
4592 return false;
4593 }
4594
Brandon Jonesd1049182018-03-28 10:02:20 -07004595 SetRobustLengthParam(length, numParams);
4596
Geoff Langc1984ed2016-10-07 12:41:00 -04004597 return true;
4598}
4599
Geoff Langc1984ed2016-10-07 12:41:00 -04004600bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004601 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004602 GLenum pname,
4603 GLsizei bufSize,
4604 GLsizei *length,
4605 GLint *params)
4606{
Brandon Jonesd1049182018-03-28 10:02:20 -07004607
Geoff Langc1984ed2016-10-07 12:41:00 -04004608 if (!ValidateRobustEntryPoint(context, bufSize))
4609 {
4610 return false;
4611 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004612 GLsizei numParams = 0;
4613 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004614 {
4615 return false;
4616 }
4617
Brandon Jonesd1049182018-03-28 10:02:20 -07004618 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004619 {
4620 return false;
4621 }
4622
Brandon Jonesd1049182018-03-28 10:02:20 -07004623 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004624 return true;
4625}
4626
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004627bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4628 TextureType target,
4629 GLenum pname,
4630 GLsizei bufSize,
4631 GLsizei *length,
4632 GLint *params)
4633{
4634 UNIMPLEMENTED();
4635 return false;
4636}
4637
4638bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4639 TextureType target,
4640 GLenum pname,
4641 GLsizei bufSize,
4642 GLsizei *length,
4643 GLuint *params)
4644{
4645 UNIMPLEMENTED();
4646 return false;
4647}
4648
Geoff Langc1984ed2016-10-07 12:41:00 -04004649bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004650 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004651 GLenum pname,
4652 GLsizei bufSize,
4653 const GLfloat *params)
4654{
4655 if (!ValidateRobustEntryPoint(context, bufSize))
4656 {
4657 return false;
4658 }
4659
4660 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4661}
4662
Geoff Langc1984ed2016-10-07 12:41:00 -04004663bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004664 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004665 GLenum pname,
4666 GLsizei bufSize,
4667 const GLint *params)
4668{
4669 if (!ValidateRobustEntryPoint(context, bufSize))
4670 {
4671 return false;
4672 }
4673
4674 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4675}
4676
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004677bool ValidateTexParameterIivRobustANGLE(Context *context,
4678 TextureType target,
4679 GLenum pname,
4680 GLsizei bufSize,
4681 const GLint *params)
4682{
4683 UNIMPLEMENTED();
4684 return false;
4685}
4686
4687bool ValidateTexParameterIuivRobustANGLE(Context *context,
4688 TextureType target,
4689 GLenum pname,
4690 GLsizei bufSize,
4691 const GLuint *params)
4692{
4693 UNIMPLEMENTED();
4694 return false;
4695}
4696
Geoff Langc1984ed2016-10-07 12:41:00 -04004697bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4698 GLuint sampler,
4699 GLenum pname,
4700 GLuint bufSize,
4701 GLsizei *length,
4702 GLfloat *params)
4703{
4704 if (!ValidateRobustEntryPoint(context, bufSize))
4705 {
4706 return false;
4707 }
4708
Brandon Jonesd1049182018-03-28 10:02:20 -07004709 GLsizei numParams = 0;
4710
4711 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004712 {
4713 return false;
4714 }
4715
Brandon Jonesd1049182018-03-28 10:02:20 -07004716 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004717 {
4718 return false;
4719 }
4720
Brandon Jonesd1049182018-03-28 10:02:20 -07004721 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004722 return true;
4723}
4724
Geoff Langc1984ed2016-10-07 12:41:00 -04004725bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4726 GLuint sampler,
4727 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004728 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004729 GLsizei *length,
4730 GLint *params)
4731{
4732 if (!ValidateRobustEntryPoint(context, bufSize))
4733 {
4734 return false;
4735 }
4736
Brandon Jonesd1049182018-03-28 10:02:20 -07004737 GLsizei numParams = 0;
4738
4739 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004740 {
4741 return false;
4742 }
4743
Brandon Jonesd1049182018-03-28 10:02:20 -07004744 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004745 {
4746 return false;
4747 }
4748
Brandon Jonesd1049182018-03-28 10:02:20 -07004749 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004750 return true;
4751}
4752
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004753bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4754 GLuint sampler,
4755 GLenum pname,
4756 GLsizei bufSize,
4757 GLsizei *length,
4758 GLint *params)
4759{
4760 UNIMPLEMENTED();
4761 return false;
4762}
4763
4764bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4765 GLuint sampler,
4766 GLenum pname,
4767 GLsizei bufSize,
4768 GLsizei *length,
4769 GLuint *params)
4770{
4771 UNIMPLEMENTED();
4772 return false;
4773}
4774
Geoff Langc1984ed2016-10-07 12:41:00 -04004775bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4776 GLuint sampler,
4777 GLenum pname,
4778 GLsizei bufSize,
4779 const GLfloat *params)
4780{
4781 if (!ValidateRobustEntryPoint(context, bufSize))
4782 {
4783 return false;
4784 }
4785
4786 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4787}
4788
Geoff Langc1984ed2016-10-07 12:41:00 -04004789bool ValidateSamplerParameterivRobustANGLE(Context *context,
4790 GLuint sampler,
4791 GLenum pname,
4792 GLsizei bufSize,
4793 const GLint *params)
4794{
4795 if (!ValidateRobustEntryPoint(context, bufSize))
4796 {
4797 return false;
4798 }
4799
4800 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4801}
4802
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004803bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4804 GLuint sampler,
4805 GLenum pname,
4806 GLsizei bufSize,
4807 const GLint *param)
4808{
4809 UNIMPLEMENTED();
4810 return false;
4811}
4812
4813bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4814 GLuint sampler,
4815 GLenum pname,
4816 GLsizei bufSize,
4817 const GLuint *param)
4818{
4819 UNIMPLEMENTED();
4820 return false;
4821}
4822
Geoff Lang0b031062016-10-13 14:30:04 -04004823bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4824 GLuint index,
4825 GLenum pname,
4826 GLsizei bufSize,
4827 GLsizei *length,
4828 GLfloat *params)
4829{
4830 if (!ValidateRobustEntryPoint(context, bufSize))
4831 {
4832 return false;
4833 }
4834
Brandon Jonesd1049182018-03-28 10:02:20 -07004835 GLsizei writeLength = 0;
4836
4837 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004838 {
4839 return false;
4840 }
4841
Brandon Jonesd1049182018-03-28 10:02:20 -07004842 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004843 {
4844 return false;
4845 }
4846
Brandon Jonesd1049182018-03-28 10:02:20 -07004847 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004848 return true;
4849}
4850
Geoff Lang0b031062016-10-13 14:30:04 -04004851bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4852 GLuint index,
4853 GLenum pname,
4854 GLsizei bufSize,
4855 GLsizei *length,
4856 GLint *params)
4857{
4858 if (!ValidateRobustEntryPoint(context, bufSize))
4859 {
4860 return false;
4861 }
4862
Brandon Jonesd1049182018-03-28 10:02:20 -07004863 GLsizei writeLength = 0;
4864
4865 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004866 {
4867 return false;
4868 }
4869
Brandon Jonesd1049182018-03-28 10:02:20 -07004870 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004871 {
4872 return false;
4873 }
4874
Brandon Jonesd1049182018-03-28 10:02:20 -07004875 SetRobustLengthParam(length, writeLength);
4876
Geoff Lang0b031062016-10-13 14:30:04 -04004877 return true;
4878}
4879
Geoff Lang0b031062016-10-13 14:30:04 -04004880bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4881 GLuint index,
4882 GLenum pname,
4883 GLsizei bufSize,
4884 GLsizei *length,
4885 void **pointer)
4886{
4887 if (!ValidateRobustEntryPoint(context, bufSize))
4888 {
4889 return false;
4890 }
4891
Brandon Jonesd1049182018-03-28 10:02:20 -07004892 GLsizei writeLength = 0;
4893
4894 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004895 {
4896 return false;
4897 }
4898
Brandon Jonesd1049182018-03-28 10:02:20 -07004899 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004900 {
4901 return false;
4902 }
4903
Brandon Jonesd1049182018-03-28 10:02:20 -07004904 SetRobustLengthParam(length, writeLength);
4905
Geoff Lang0b031062016-10-13 14:30:04 -04004906 return true;
4907}
4908
Geoff Lang0b031062016-10-13 14:30:04 -04004909bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4910 GLuint index,
4911 GLenum pname,
4912 GLsizei bufSize,
4913 GLsizei *length,
4914 GLint *params)
4915{
4916 if (!ValidateRobustEntryPoint(context, bufSize))
4917 {
4918 return false;
4919 }
4920
Brandon Jonesd1049182018-03-28 10:02:20 -07004921 GLsizei writeLength = 0;
4922
4923 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004924 {
4925 return false;
4926 }
4927
Brandon Jonesd1049182018-03-28 10:02:20 -07004928 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004929 {
4930 return false;
4931 }
4932
Brandon Jonesd1049182018-03-28 10:02:20 -07004933 SetRobustLengthParam(length, writeLength);
4934
Geoff Lang0b031062016-10-13 14:30:04 -04004935 return true;
4936}
4937
Geoff Lang0b031062016-10-13 14:30:04 -04004938bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4939 GLuint index,
4940 GLenum pname,
4941 GLsizei bufSize,
4942 GLsizei *length,
4943 GLuint *params)
4944{
4945 if (!ValidateRobustEntryPoint(context, bufSize))
4946 {
4947 return false;
4948 }
4949
Brandon Jonesd1049182018-03-28 10:02:20 -07004950 GLsizei writeLength = 0;
4951
4952 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004953 {
4954 return false;
4955 }
4956
Brandon Jonesd1049182018-03-28 10:02:20 -07004957 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004958 {
4959 return false;
4960 }
4961
Brandon Jonesd1049182018-03-28 10:02:20 -07004962 SetRobustLengthParam(length, writeLength);
4963
Geoff Lang0b031062016-10-13 14:30:04 -04004964 return true;
4965}
4966
Geoff Lang6899b872016-10-14 11:30:13 -04004967bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4968 GLuint program,
4969 GLuint uniformBlockIndex,
4970 GLenum pname,
4971 GLsizei bufSize,
4972 GLsizei *length,
4973 GLint *params)
4974{
4975 if (!ValidateRobustEntryPoint(context, bufSize))
4976 {
4977 return false;
4978 }
4979
Brandon Jonesd1049182018-03-28 10:02:20 -07004980 GLsizei writeLength = 0;
4981
4982 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
4983 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004984 {
4985 return false;
4986 }
4987
Brandon Jonesd1049182018-03-28 10:02:20 -07004988 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004989 {
4990 return false;
4991 }
4992
Brandon Jonesd1049182018-03-28 10:02:20 -07004993 SetRobustLengthParam(length, writeLength);
4994
Geoff Lang6899b872016-10-14 11:30:13 -04004995 return true;
4996}
4997
Brandon Jones416aaf92018-04-10 08:10:16 -07004998bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07004999 GLenum target,
5000 GLenum internalformat,
5001 GLenum pname,
5002 GLsizei bufSize,
5003 GLsizei *length,
5004 GLint *params)
5005{
5006 if (!ValidateRobustEntryPoint(context, bufSize))
5007 {
5008 return false;
5009 }
5010
Brandon Jonesd1049182018-03-28 10:02:20 -07005011 GLsizei numParams = 0;
5012
5013 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5014 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005015 {
5016 return false;
5017 }
5018
Brandon Jonesd1049182018-03-28 10:02:20 -07005019 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005020 {
5021 return false;
5022 }
5023
Brandon Jonesd1049182018-03-28 10:02:20 -07005024 SetRobustLengthParam(length, numParams);
5025
Geoff Lang0a9661f2016-10-20 10:59:20 -07005026 return true;
5027}
5028
Jamie Madill5b772312018-03-08 20:28:32 -05005029bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005030 GLuint attribIndex,
5031 GLint size,
5032 GLenum type,
5033 GLboolean pureInteger)
5034{
5035 const Caps &caps = context->getCaps();
5036 if (attribIndex >= caps.maxVertexAttributes)
5037 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005038 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005039 return false;
5040 }
5041
5042 if (size < 1 || size > 4)
5043 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005044 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005045 return false;
Shao80957d92017-02-20 21:25:59 +08005046 }
5047
5048 switch (type)
5049 {
5050 case GL_BYTE:
5051 case GL_UNSIGNED_BYTE:
5052 case GL_SHORT:
5053 case GL_UNSIGNED_SHORT:
5054 break;
5055
5056 case GL_INT:
5057 case GL_UNSIGNED_INT:
5058 if (context->getClientMajorVersion() < 3)
5059 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005060 context->handleError(InvalidEnum()
5061 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005062 return false;
5063 }
5064 break;
5065
5066 case GL_FIXED:
5067 case GL_FLOAT:
5068 if (pureInteger)
5069 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005070 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005071 return false;
5072 }
5073 break;
5074
5075 case GL_HALF_FLOAT:
5076 if (context->getClientMajorVersion() < 3)
5077 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005078 context->handleError(InvalidEnum()
5079 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005080 return false;
5081 }
5082 if (pureInteger)
5083 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005084 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005085 return false;
5086 }
5087 break;
5088
5089 case GL_INT_2_10_10_10_REV:
5090 case GL_UNSIGNED_INT_2_10_10_10_REV:
5091 if (context->getClientMajorVersion() < 3)
5092 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005093 context->handleError(InvalidEnum()
5094 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005095 return false;
5096 }
5097 if (pureInteger)
5098 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005099 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005100 return false;
5101 }
5102 if (size != 4)
5103 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005104 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5105 "UNSIGNED_INT_2_10_10_10_REV and "
5106 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005107 return false;
5108 }
5109 break;
5110
5111 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005112 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005113 return false;
5114 }
5115
5116 return true;
5117}
5118
Geoff Lang76e65652017-03-27 14:58:02 -04005119// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5120// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5121// specified clear value and the type of a buffer that is being cleared generates an
5122// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005123bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005124 GLint drawbuffer,
5125 const GLenum *validComponentTypes,
5126 size_t validComponentTypeCount)
5127{
5128 const FramebufferAttachment *attachment =
5129 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5130 if (attachment)
5131 {
5132 GLenum componentType = attachment->getFormat().info->componentType;
5133 const GLenum *end = validComponentTypes + validComponentTypeCount;
5134 if (std::find(validComponentTypes, end, componentType) == end)
5135 {
5136 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005137 InvalidOperation()
5138 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005139 return false;
5140 }
5141 }
5142
5143 return true;
5144}
5145
Jamie Madill5b772312018-03-08 20:28:32 -05005146bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005147{
5148 if (!ValidateRobustEntryPoint(context, dataSize))
5149 {
5150 return false;
5151 }
5152
Corentin Wallez336129f2017-10-17 15:55:40 -04005153 gl::Buffer *pixelUnpackBuffer =
5154 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005155 if (pixelUnpackBuffer == nullptr)
5156 {
5157 if (dataSize < imageSize)
5158 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005159 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005160 }
5161 }
5162 return true;
5163}
5164
Jamie Madill5b772312018-03-08 20:28:32 -05005165bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005166 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005167 GLenum pname,
5168 bool pointerVersion,
5169 GLsizei *numParams)
5170{
5171 if (numParams)
5172 {
5173 *numParams = 0;
5174 }
5175
Corentin Walleze4477002017-12-01 14:39:58 -05005176 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005177 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005178 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005179 return false;
5180 }
5181
5182 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5183 if (!buffer)
5184 {
5185 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005186 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005187 return false;
5188 }
5189
5190 const Extensions &extensions = context->getExtensions();
5191
5192 switch (pname)
5193 {
5194 case GL_BUFFER_USAGE:
5195 case GL_BUFFER_SIZE:
5196 break;
5197
5198 case GL_BUFFER_ACCESS_OES:
5199 if (!extensions.mapBuffer)
5200 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005201 context->handleError(InvalidEnum()
5202 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005203 return false;
5204 }
5205 break;
5206
5207 case GL_BUFFER_MAPPED:
5208 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5209 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5210 !extensions.mapBufferRange)
5211 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005212 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5213 "GL_OES_mapbuffer or "
5214 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005215 return false;
5216 }
5217 break;
5218
5219 case GL_BUFFER_MAP_POINTER:
5220 if (!pointerVersion)
5221 {
5222 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005223 InvalidEnum()
5224 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005225 return false;
5226 }
5227 break;
5228
5229 case GL_BUFFER_ACCESS_FLAGS:
5230 case GL_BUFFER_MAP_OFFSET:
5231 case GL_BUFFER_MAP_LENGTH:
5232 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5233 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005234 context->handleError(InvalidEnum()
5235 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005236 return false;
5237 }
5238 break;
5239
5240 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005241 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005242 return false;
5243 }
5244
5245 // All buffer parameter queries return one value.
5246 if (numParams)
5247 {
5248 *numParams = 1;
5249 }
5250
5251 return true;
5252}
5253
5254bool ValidateGetRenderbufferParameterivBase(Context *context,
5255 GLenum target,
5256 GLenum pname,
5257 GLsizei *length)
5258{
5259 if (length)
5260 {
5261 *length = 0;
5262 }
5263
5264 if (target != GL_RENDERBUFFER)
5265 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005266 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005267 return false;
5268 }
5269
5270 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5271 if (renderbuffer == nullptr)
5272 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005273 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005274 return false;
5275 }
5276
5277 switch (pname)
5278 {
5279 case GL_RENDERBUFFER_WIDTH:
5280 case GL_RENDERBUFFER_HEIGHT:
5281 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5282 case GL_RENDERBUFFER_RED_SIZE:
5283 case GL_RENDERBUFFER_GREEN_SIZE:
5284 case GL_RENDERBUFFER_BLUE_SIZE:
5285 case GL_RENDERBUFFER_ALPHA_SIZE:
5286 case GL_RENDERBUFFER_DEPTH_SIZE:
5287 case GL_RENDERBUFFER_STENCIL_SIZE:
5288 break;
5289
5290 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5291 if (!context->getExtensions().framebufferMultisample)
5292 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005293 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005294 return false;
5295 }
5296 break;
5297
5298 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005299 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005300 return false;
5301 }
5302
5303 if (length)
5304 {
5305 *length = 1;
5306 }
5307 return true;
5308}
5309
5310bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5311{
5312 if (length)
5313 {
5314 *length = 0;
5315 }
5316
5317 if (GetValidShader(context, shader) == nullptr)
5318 {
5319 return false;
5320 }
5321
5322 switch (pname)
5323 {
5324 case GL_SHADER_TYPE:
5325 case GL_DELETE_STATUS:
5326 case GL_COMPILE_STATUS:
5327 case GL_INFO_LOG_LENGTH:
5328 case GL_SHADER_SOURCE_LENGTH:
5329 break;
5330
5331 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5332 if (!context->getExtensions().translatedShaderSource)
5333 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005334 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005335 return false;
5336 }
5337 break;
5338
5339 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005340 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005341 return false;
5342 }
5343
5344 if (length)
5345 {
5346 *length = 1;
5347 }
5348 return true;
5349}
5350
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005351bool ValidateGetTexParameterBase(Context *context,
5352 TextureType target,
5353 GLenum pname,
5354 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005355{
5356 if (length)
5357 {
5358 *length = 0;
5359 }
5360
5361 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5362 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005363 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005364 return false;
5365 }
5366
5367 if (context->getTargetTexture(target) == nullptr)
5368 {
5369 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005370 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005371 return false;
5372 }
5373
5374 switch (pname)
5375 {
5376 case GL_TEXTURE_MAG_FILTER:
5377 case GL_TEXTURE_MIN_FILTER:
5378 case GL_TEXTURE_WRAP_S:
5379 case GL_TEXTURE_WRAP_T:
5380 break;
5381
5382 case GL_TEXTURE_USAGE_ANGLE:
5383 if (!context->getExtensions().textureUsage)
5384 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005385 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005386 return false;
5387 }
5388 break;
5389
5390 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005391 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005392 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005393 return false;
5394 }
5395 break;
5396
5397 case GL_TEXTURE_IMMUTABLE_FORMAT:
5398 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5399 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005400 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005401 return false;
5402 }
5403 break;
5404
5405 case GL_TEXTURE_WRAP_R:
5406 case GL_TEXTURE_IMMUTABLE_LEVELS:
5407 case GL_TEXTURE_SWIZZLE_R:
5408 case GL_TEXTURE_SWIZZLE_G:
5409 case GL_TEXTURE_SWIZZLE_B:
5410 case GL_TEXTURE_SWIZZLE_A:
5411 case GL_TEXTURE_BASE_LEVEL:
5412 case GL_TEXTURE_MAX_LEVEL:
5413 case GL_TEXTURE_MIN_LOD:
5414 case GL_TEXTURE_MAX_LOD:
5415 case GL_TEXTURE_COMPARE_MODE:
5416 case GL_TEXTURE_COMPARE_FUNC:
5417 if (context->getClientMajorVersion() < 3)
5418 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005419 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005420 return false;
5421 }
5422 break;
5423
5424 case GL_TEXTURE_SRGB_DECODE_EXT:
5425 if (!context->getExtensions().textureSRGBDecode)
5426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005427 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005428 return false;
5429 }
5430 break;
5431
Yunchao Hebacaa712018-01-30 14:01:39 +08005432 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5433 if (context->getClientVersion() < Version(3, 1))
5434 {
5435 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5436 return false;
5437 }
5438 break;
5439
Jamie Madillbe849e42017-05-02 15:49:00 -04005440 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005441 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005442 return false;
5443 }
5444
5445 if (length)
5446 {
5447 *length = 1;
5448 }
5449 return true;
5450}
5451
5452bool ValidateGetVertexAttribBase(Context *context,
5453 GLuint index,
5454 GLenum pname,
5455 GLsizei *length,
5456 bool pointer,
5457 bool pureIntegerEntryPoint)
5458{
5459 if (length)
5460 {
5461 *length = 0;
5462 }
5463
5464 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5465 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005466 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005467 return false;
5468 }
5469
5470 if (index >= context->getCaps().maxVertexAttributes)
5471 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005472 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005473 return false;
5474 }
5475
5476 if (pointer)
5477 {
5478 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5479 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005480 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005481 return false;
5482 }
5483 }
5484 else
5485 {
5486 switch (pname)
5487 {
5488 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5489 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5490 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5491 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5492 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5493 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5494 case GL_CURRENT_VERTEX_ATTRIB:
5495 break;
5496
5497 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5498 static_assert(
5499 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5500 "ANGLE extension enums not equal to GL enums.");
5501 if (context->getClientMajorVersion() < 3 &&
5502 !context->getExtensions().instancedArrays)
5503 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005504 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5505 "requires OpenGL ES 3.0 or "
5506 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005507 return false;
5508 }
5509 break;
5510
5511 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5512 if (context->getClientMajorVersion() < 3)
5513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005514 context->handleError(
5515 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005516 return false;
5517 }
5518 break;
5519
5520 case GL_VERTEX_ATTRIB_BINDING:
5521 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5522 if (context->getClientVersion() < ES_3_1)
5523 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005524 context->handleError(InvalidEnum()
5525 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005526 return false;
5527 }
5528 break;
5529
5530 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005531 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005532 return false;
5533 }
5534 }
5535
5536 if (length)
5537 {
5538 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5539 {
5540 *length = 4;
5541 }
5542 else
5543 {
5544 *length = 1;
5545 }
5546 }
5547
5548 return true;
5549}
5550
Jamie Madill4928b7c2017-06-20 12:57:39 -04005551bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005552 GLint x,
5553 GLint y,
5554 GLsizei width,
5555 GLsizei height,
5556 GLenum format,
5557 GLenum type,
5558 GLsizei bufSize,
5559 GLsizei *length,
5560 GLsizei *columns,
5561 GLsizei *rows,
5562 void *pixels)
5563{
5564 if (length != nullptr)
5565 {
5566 *length = 0;
5567 }
5568 if (rows != nullptr)
5569 {
5570 *rows = 0;
5571 }
5572 if (columns != nullptr)
5573 {
5574 *columns = 0;
5575 }
5576
5577 if (width < 0 || height < 0)
5578 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005579 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005580 return false;
5581 }
5582
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005583 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005584
Jamie Madill427064d2018-04-13 16:20:34 -04005585 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005586 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005587 return false;
5588 }
5589
Jamie Madille98b1b52018-03-08 09:47:23 -05005590 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005591 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005592 return false;
5593 }
5594
Jamie Madill690c8eb2018-03-12 15:20:03 -04005595 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005596 ASSERT(framebuffer);
5597
5598 if (framebuffer->getReadBufferState() == GL_NONE)
5599 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005600 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005601 return false;
5602 }
5603
5604 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5605 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5606 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5607 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5608 // situation is an application error that would lead to a crash in ANGLE.
5609 if (readBuffer == nullptr)
5610 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005611 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005612 return false;
5613 }
5614
Martin Radev28031682017-07-28 14:47:56 +03005615 // ANGLE_multiview, Revision 1:
5616 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5617 // current read framebuffer is not NONE.
5618 if (readBuffer->getMultiviewLayout() != GL_NONE)
5619 {
5620 context->handleError(InvalidFramebufferOperation()
5621 << "Attempting to read from a multi-view framebuffer.");
5622 return false;
5623 }
5624
Geoff Lang280ba992017-04-18 16:30:58 -04005625 if (context->getExtensions().webglCompatibility)
5626 {
5627 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5628 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5629 // and type before validating the combination of format and type. However, the
5630 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5631 // verifies that GL_INVALID_OPERATION is generated.
5632 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5633 // dEQP/WebGL.
5634 if (!ValidReadPixelsFormatEnum(context, format))
5635 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005636 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005637 return false;
5638 }
5639
5640 if (!ValidReadPixelsTypeEnum(context, type))
5641 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005642 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005643 return false;
5644 }
5645 }
5646
Jamie Madill690c8eb2018-03-12 15:20:03 -04005647 GLenum currentFormat = GL_NONE;
5648 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5649
5650 GLenum currentType = GL_NONE;
5651 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5652
Jamie Madillbe849e42017-05-02 15:49:00 -04005653 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5654
5655 bool validFormatTypeCombination =
5656 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5657
5658 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5659 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005660 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005661 return false;
5662 }
5663
5664 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005665 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005666 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5667 {
5668 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005669 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005670 return false;
5671 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005672 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5673 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5674 {
5675 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5676 return false;
5677 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005678
5679 // .. the data would be packed to the buffer object such that the memory writes required
5680 // would exceed the data store size.
5681 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5682 const gl::Extents size(width, height, 1);
5683 const auto &pack = context->getGLState().getPackState();
5684
5685 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5686 if (endByteOrErr.isError())
5687 {
5688 context->handleError(endByteOrErr.getError());
5689 return false;
5690 }
5691
5692 size_t endByte = endByteOrErr.getResult();
5693 if (bufSize >= 0)
5694 {
5695 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5696 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005697 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005698 return false;
5699 }
5700 }
5701
5702 if (pixelPackBuffer != nullptr)
5703 {
5704 CheckedNumeric<size_t> checkedEndByte(endByte);
5705 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5706 checkedEndByte += checkedOffset;
5707
5708 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5709 {
5710 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005711 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005712 return false;
5713 }
5714 }
5715
5716 if (pixelPackBuffer == nullptr && length != nullptr)
5717 {
5718 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5719 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005720 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005721 return false;
5722 }
5723
5724 *length = static_cast<GLsizei>(endByte);
5725 }
5726
Geoff Langa953b522018-02-21 16:56:23 -05005727 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005728 angle::CheckedNumeric<int> clippedExtent(length);
5729 if (start < 0)
5730 {
5731 // "subtract" the area that is less than 0
5732 clippedExtent += start;
5733 }
5734
Geoff Langa953b522018-02-21 16:56:23 -05005735 angle::CheckedNumeric<int> readExtent = start;
5736 readExtent += length;
5737 if (!readExtent.IsValid())
5738 {
5739 return false;
5740 }
5741
5742 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005743 {
5744 // Subtract the region to the right of the read buffer
5745 clippedExtent -= (readExtent - bufferSize);
5746 }
5747
5748 if (!clippedExtent.IsValid())
5749 {
Geoff Langa953b522018-02-21 16:56:23 -05005750 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005751 }
5752
Geoff Langa953b522018-02-21 16:56:23 -05005753 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5754 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005755 };
5756
Geoff Langa953b522018-02-21 16:56:23 -05005757 GLsizei writtenColumns = 0;
5758 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5759 {
5760 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5761 return false;
5762 }
5763
5764 GLsizei writtenRows = 0;
5765 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5766 {
5767 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5768 return false;
5769 }
5770
Jamie Madillbe849e42017-05-02 15:49:00 -04005771 if (columns != nullptr)
5772 {
Geoff Langa953b522018-02-21 16:56:23 -05005773 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005774 }
5775
5776 if (rows != nullptr)
5777 {
Geoff Langa953b522018-02-21 16:56:23 -05005778 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005779 }
5780
5781 return true;
5782}
5783
5784template <typename ParamType>
5785bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005786 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005787 GLenum pname,
5788 GLsizei bufSize,
5789 const ParamType *params)
5790{
5791 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5792 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005793 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005794 return false;
5795 }
5796
5797 if (context->getTargetTexture(target) == nullptr)
5798 {
5799 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005800 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005801 return false;
5802 }
5803
5804 const GLsizei minBufSize = 1;
5805 if (bufSize >= 0 && bufSize < minBufSize)
5806 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005807 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005808 return false;
5809 }
5810
5811 switch (pname)
5812 {
5813 case GL_TEXTURE_WRAP_R:
5814 case GL_TEXTURE_SWIZZLE_R:
5815 case GL_TEXTURE_SWIZZLE_G:
5816 case GL_TEXTURE_SWIZZLE_B:
5817 case GL_TEXTURE_SWIZZLE_A:
5818 case GL_TEXTURE_BASE_LEVEL:
5819 case GL_TEXTURE_MAX_LEVEL:
5820 case GL_TEXTURE_COMPARE_MODE:
5821 case GL_TEXTURE_COMPARE_FUNC:
5822 case GL_TEXTURE_MIN_LOD:
5823 case GL_TEXTURE_MAX_LOD:
5824 if (context->getClientMajorVersion() < 3)
5825 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005826 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005827 return false;
5828 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005829 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005830 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005831 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5832 "available without "
5833 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005834 return false;
5835 }
5836 break;
5837
5838 default:
5839 break;
5840 }
5841
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005842 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005843 {
5844 switch (pname)
5845 {
5846 case GL_TEXTURE_MIN_FILTER:
5847 case GL_TEXTURE_MAG_FILTER:
5848 case GL_TEXTURE_WRAP_S:
5849 case GL_TEXTURE_WRAP_T:
5850 case GL_TEXTURE_WRAP_R:
5851 case GL_TEXTURE_MIN_LOD:
5852 case GL_TEXTURE_MAX_LOD:
5853 case GL_TEXTURE_COMPARE_MODE:
5854 case GL_TEXTURE_COMPARE_FUNC:
5855 context->handleError(InvalidEnum()
5856 << "Invalid parameter for 2D multisampled textures.");
5857 return false;
5858 }
5859 }
5860
Jamie Madillbe849e42017-05-02 15:49:00 -04005861 switch (pname)
5862 {
5863 case GL_TEXTURE_WRAP_S:
5864 case GL_TEXTURE_WRAP_T:
5865 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005866 {
5867 bool restrictedWrapModes =
5868 target == TextureType::External || target == TextureType::Rectangle;
5869 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005870 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005871 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005872 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005873 }
5874 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005875
5876 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005877 {
5878 bool restrictedMinFilter =
5879 target == TextureType::External || target == TextureType::Rectangle;
5880 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005881 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005882 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005883 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005884 }
5885 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005886
5887 case GL_TEXTURE_MAG_FILTER:
5888 if (!ValidateTextureMagFilterValue(context, params))
5889 {
5890 return false;
5891 }
5892 break;
5893
5894 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005895 if (!context->getExtensions().textureUsage)
5896 {
5897 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5898 return false;
5899 }
5900
Jamie Madillbe849e42017-05-02 15:49:00 -04005901 switch (ConvertToGLenum(params[0]))
5902 {
5903 case GL_NONE:
5904 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5905 break;
5906
5907 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005908 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005909 return false;
5910 }
5911 break;
5912
5913 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005914 {
5915 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5916 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04005917 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005918 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005919 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005920 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
5921 }
5922 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005923
5924 case GL_TEXTURE_MIN_LOD:
5925 case GL_TEXTURE_MAX_LOD:
5926 // any value is permissible
5927 break;
5928
5929 case GL_TEXTURE_COMPARE_MODE:
5930 if (!ValidateTextureCompareModeValue(context, params))
5931 {
5932 return false;
5933 }
5934 break;
5935
5936 case GL_TEXTURE_COMPARE_FUNC:
5937 if (!ValidateTextureCompareFuncValue(context, params))
5938 {
5939 return false;
5940 }
5941 break;
5942
5943 case GL_TEXTURE_SWIZZLE_R:
5944 case GL_TEXTURE_SWIZZLE_G:
5945 case GL_TEXTURE_SWIZZLE_B:
5946 case GL_TEXTURE_SWIZZLE_A:
5947 switch (ConvertToGLenum(params[0]))
5948 {
5949 case GL_RED:
5950 case GL_GREEN:
5951 case GL_BLUE:
5952 case GL_ALPHA:
5953 case GL_ZERO:
5954 case GL_ONE:
5955 break;
5956
5957 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005958 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005959 return false;
5960 }
5961 break;
5962
5963 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005964 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005965 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005966 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005967 return false;
5968 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005969 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005970 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005971 context->handleError(InvalidOperation()
5972 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005973 return false;
5974 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005975 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005976 {
5977 context->handleError(InvalidOperation()
5978 << "Base level must be 0 for multisampled textures.");
5979 return false;
5980 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005981 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005982 {
5983 context->handleError(InvalidOperation()
5984 << "Base level must be 0 for rectangle textures.");
5985 return false;
5986 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005987 break;
5988
5989 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005990 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005991 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005992 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005993 return false;
5994 }
5995 break;
5996
5997 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5998 if (context->getClientVersion() < Version(3, 1))
5999 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006000 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006001 return false;
6002 }
6003 switch (ConvertToGLenum(params[0]))
6004 {
6005 case GL_DEPTH_COMPONENT:
6006 case GL_STENCIL_INDEX:
6007 break;
6008
6009 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006010 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006011 return false;
6012 }
6013 break;
6014
6015 case GL_TEXTURE_SRGB_DECODE_EXT:
6016 if (!ValidateTextureSRGBDecodeValue(context, params))
6017 {
6018 return false;
6019 }
6020 break;
6021
6022 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006023 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006024 return false;
6025 }
6026
6027 return true;
6028}
6029
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006030template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6031template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006032
Jamie Madill5b772312018-03-08 20:28:32 -05006033bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006034{
6035 if (index >= MAX_VERTEX_ATTRIBS)
6036 {
6037 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6038 return false;
6039 }
6040
6041 return true;
6042}
6043
6044bool ValidateGetActiveUniformBlockivBase(Context *context,
6045 GLuint program,
6046 GLuint uniformBlockIndex,
6047 GLenum pname,
6048 GLsizei *length)
6049{
6050 if (length)
6051 {
6052 *length = 0;
6053 }
6054
6055 if (context->getClientMajorVersion() < 3)
6056 {
6057 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6058 return false;
6059 }
6060
6061 Program *programObject = GetValidProgram(context, program);
6062 if (!programObject)
6063 {
6064 return false;
6065 }
6066
6067 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6068 {
6069 context->handleError(InvalidValue()
6070 << "uniformBlockIndex exceeds active uniform block count.");
6071 return false;
6072 }
6073
6074 switch (pname)
6075 {
6076 case GL_UNIFORM_BLOCK_BINDING:
6077 case GL_UNIFORM_BLOCK_DATA_SIZE:
6078 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6079 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6080 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6081 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6082 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6083 break;
6084
6085 default:
6086 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6087 return false;
6088 }
6089
6090 if (length)
6091 {
6092 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6093 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006094 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006095 programObject->getUniformBlockByIndex(uniformBlockIndex);
6096 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6097 }
6098 else
6099 {
6100 *length = 1;
6101 }
6102 }
6103
6104 return true;
6105}
6106
Jamie Madill9696d072017-08-26 23:19:57 -04006107template <typename ParamType>
6108bool ValidateSamplerParameterBase(Context *context,
6109 GLuint sampler,
6110 GLenum pname,
6111 GLsizei bufSize,
6112 ParamType *params)
6113{
6114 if (context->getClientMajorVersion() < 3)
6115 {
6116 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6117 return false;
6118 }
6119
6120 if (!context->isSampler(sampler))
6121 {
6122 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6123 return false;
6124 }
6125
6126 const GLsizei minBufSize = 1;
6127 if (bufSize >= 0 && bufSize < minBufSize)
6128 {
6129 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6130 return false;
6131 }
6132
6133 switch (pname)
6134 {
6135 case GL_TEXTURE_WRAP_S:
6136 case GL_TEXTURE_WRAP_T:
6137 case GL_TEXTURE_WRAP_R:
6138 if (!ValidateTextureWrapModeValue(context, params, false))
6139 {
6140 return false;
6141 }
6142 break;
6143
6144 case GL_TEXTURE_MIN_FILTER:
6145 if (!ValidateTextureMinFilterValue(context, params, false))
6146 {
6147 return false;
6148 }
6149 break;
6150
6151 case GL_TEXTURE_MAG_FILTER:
6152 if (!ValidateTextureMagFilterValue(context, params))
6153 {
6154 return false;
6155 }
6156 break;
6157
6158 case GL_TEXTURE_MIN_LOD:
6159 case GL_TEXTURE_MAX_LOD:
6160 // any value is permissible
6161 break;
6162
6163 case GL_TEXTURE_COMPARE_MODE:
6164 if (!ValidateTextureCompareModeValue(context, params))
6165 {
6166 return false;
6167 }
6168 break;
6169
6170 case GL_TEXTURE_COMPARE_FUNC:
6171 if (!ValidateTextureCompareFuncValue(context, params))
6172 {
6173 return false;
6174 }
6175 break;
6176
6177 case GL_TEXTURE_SRGB_DECODE_EXT:
6178 if (!ValidateTextureSRGBDecodeValue(context, params))
6179 {
6180 return false;
6181 }
6182 break;
6183
Luc Ferron1b1a8642018-01-23 15:12:01 -05006184 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6185 {
6186 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6187 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6188 {
6189 return false;
6190 }
6191 }
6192 break;
6193
Jamie Madill9696d072017-08-26 23:19:57 -04006194 default:
6195 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6196 return false;
6197 }
6198
6199 return true;
6200}
6201
6202template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6203template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6204
6205bool ValidateGetSamplerParameterBase(Context *context,
6206 GLuint sampler,
6207 GLenum pname,
6208 GLsizei *length)
6209{
6210 if (length)
6211 {
6212 *length = 0;
6213 }
6214
6215 if (context->getClientMajorVersion() < 3)
6216 {
6217 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6218 return false;
6219 }
6220
6221 if (!context->isSampler(sampler))
6222 {
6223 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6224 return false;
6225 }
6226
6227 switch (pname)
6228 {
6229 case GL_TEXTURE_WRAP_S:
6230 case GL_TEXTURE_WRAP_T:
6231 case GL_TEXTURE_WRAP_R:
6232 case GL_TEXTURE_MIN_FILTER:
6233 case GL_TEXTURE_MAG_FILTER:
6234 case GL_TEXTURE_MIN_LOD:
6235 case GL_TEXTURE_MAX_LOD:
6236 case GL_TEXTURE_COMPARE_MODE:
6237 case GL_TEXTURE_COMPARE_FUNC:
6238 break;
6239
Luc Ferron1b1a8642018-01-23 15:12:01 -05006240 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6241 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6242 {
6243 return false;
6244 }
6245 break;
6246
Jamie Madill9696d072017-08-26 23:19:57 -04006247 case GL_TEXTURE_SRGB_DECODE_EXT:
6248 if (!context->getExtensions().textureSRGBDecode)
6249 {
6250 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6251 return false;
6252 }
6253 break;
6254
6255 default:
6256 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6257 return false;
6258 }
6259
6260 if (length)
6261 {
6262 *length = 1;
6263 }
6264 return true;
6265}
6266
6267bool ValidateGetInternalFormativBase(Context *context,
6268 GLenum target,
6269 GLenum internalformat,
6270 GLenum pname,
6271 GLsizei bufSize,
6272 GLsizei *numParams)
6273{
6274 if (numParams)
6275 {
6276 *numParams = 0;
6277 }
6278
6279 if (context->getClientMajorVersion() < 3)
6280 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006281 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006282 return false;
6283 }
6284
6285 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
6286 if (!formatCaps.renderable)
6287 {
6288 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6289 return false;
6290 }
6291
6292 switch (target)
6293 {
6294 case GL_RENDERBUFFER:
6295 break;
6296
6297 case GL_TEXTURE_2D_MULTISAMPLE:
6298 if (context->getClientVersion() < ES_3_1)
6299 {
6300 context->handleError(InvalidOperation()
6301 << "Texture target requires at least OpenGL ES 3.1.");
6302 return false;
6303 }
6304 break;
6305
6306 default:
6307 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6308 return false;
6309 }
6310
6311 if (bufSize < 0)
6312 {
6313 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6314 return false;
6315 }
6316
6317 GLsizei maxWriteParams = 0;
6318 switch (pname)
6319 {
6320 case GL_NUM_SAMPLE_COUNTS:
6321 maxWriteParams = 1;
6322 break;
6323
6324 case GL_SAMPLES:
6325 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6326 break;
6327
6328 default:
6329 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6330 return false;
6331 }
6332
6333 if (numParams)
6334 {
6335 // glGetInternalFormativ will not overflow bufSize
6336 *numParams = std::min(bufSize, maxWriteParams);
6337 }
6338
6339 return true;
6340}
6341
Jamie Madille98b1b52018-03-08 09:47:23 -05006342bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6343{
Jamie Madill427064d2018-04-13 16:20:34 -04006344 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006345 {
6346 context->handleError(InvalidOperation());
6347 return false;
6348 }
6349 return true;
6350}
6351
Lingfeng Yang038dd532018-03-29 17:31:52 -07006352bool ValidateMultitextureUnit(Context *context, GLenum texture)
6353{
6354 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6355 {
6356 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6357 return false;
6358 }
6359 return true;
6360}
6361
Jamie Madillc29968b2016-01-20 11:17:23 -05006362} // namespace gl