blob: 477d5604b11ebb7bc4c1e01ed10a165baddb1a8e [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"
Jamie Madill231c7f52017-04-26 13:45:37 -040022#include "libANGLE/formatutils.h"
jchen10a99ed552017-09-22 08:10:32 +080023#include "libANGLE/queryconversions.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040024#include "libANGLE/validationES2.h"
25#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040026
27#include "common/mathutil.h"
28#include "common/utilities.h"
29
Jamie Madille2e406c2016-06-02 13:04:10 -040030using namespace angle;
31
Geoff Lange8ebe7f2013-08-05 15:03:13 -040032namespace gl
33{
Jamie Madill1ca74672015-07-21 15:14:11 -040034namespace
35{
Luc Ferron9dbaeba2018-02-01 07:26:59 -050036bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
37{
38 // List of compressed format that require that the texture size is smaller than or a multiple of
39 // the compressed block size.
40 switch (internalFormat)
41 {
42 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
43 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
44 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
45 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
46 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
47 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
48 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
49 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
50 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
51 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
52 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
53 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
54 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
55 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
56 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
57 return true;
jchen10a99ed552017-09-22 08:10:32 +080058
Luc Ferron9dbaeba2018-02-01 07:26:59 -050059 default:
60 return false;
61 }
62}
63bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
64{
65 // Compressed sub textures have additional formats that requires exact size.
66 // ES 3.1, Section 8.7, Page 171
67 return CompressedTextureFormatRequiresExactSize(internalFormat) ||
68 IsETC2EACFormat(internalFormat);
69}
Corentin Wallez92db6942016-12-09 13:10:36 -050070bool ValidateDrawAttribs(ValidationContext *context,
71 GLint primcount,
72 GLint maxVertex,
73 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040074{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070075 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040076 const gl::Program *program = state.getProgram();
77
Corentin Wallez327411e2016-12-09 11:09:17 -050078 bool webglCompatibility = context->getExtensions().webglCompatibility;
79
Jamie Madill231c7f52017-04-26 13:45:37 -040080 const VertexArray *vao = state.getVertexArray();
81 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080082 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madilld078c682018-01-02 11:50:24 -050083 for (size_t attributeIndex : vao->getEnabledAttributesMask())
Jamie Madill1ca74672015-07-21 15:14:11 -040084 {
85 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallez672f7f32017-06-15 17:42:17 -040086
87 // No need to range check for disabled attribs.
88 if (!attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040089 {
Corentin Wallezfd456442016-12-21 17:57:00 -050090 continue;
91 }
Jamie Madill1ca74672015-07-21 15:14:11 -040092
Jamie Madill231c7f52017-04-26 13:45:37 -040093 // If we have no buffer, then we either get an error, or there are no more checks to be
94 // done.
Corentin Wallez672f7f32017-06-15 17:42:17 -040095 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
96 gl::Buffer *buffer = binding.getBuffer().get();
Corentin Wallezfd456442016-12-21 17:57:00 -050097 if (!buffer)
98 {
Geoff Langfeb8c682017-02-13 16:07:35 -050099 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -0500100 {
101 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -0500102 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
103 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
104 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
105 // error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700106 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
Corentin Wallezfd456442016-12-21 17:57:00 -0500107 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -0500108 }
Corentin Wallezfd456442016-12-21 17:57:00 -0500109 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -0400110 {
111 // This is an application error that would normally result in a crash,
112 // but we catch it and return an error
Brandon Jonesafa75152017-07-21 13:11:29 -0700113 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
Jamie Madill1ca74672015-07-21 15:14:11 -0400114 return false;
115 }
Corentin Wallezfd456442016-12-21 17:57:00 -0500116 continue;
117 }
118
Corentin Wallez672f7f32017-06-15 17:42:17 -0400119 // This needs to come after the check for client arrays as even unused attributes cannot use
120 // client-side arrays
121 if (!program->isAttribLocationActive(attributeIndex))
122 {
123 continue;
124 }
125
Corentin Wallezfd456442016-12-21 17:57:00 -0500126 // If we're drawing zero vertices, we have enough data.
127 if (vertexCount <= 0 || primcount <= 0)
128 {
129 continue;
130 }
131
132 GLint maxVertexElement = 0;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300133 GLuint divisor = binding.getDivisor();
134 if (divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500135 {
136 maxVertexElement = maxVertex;
137 }
138 else
139 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300140 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500141 }
142
143 // We do manual overflow checks here instead of using safe_math.h because it was
144 // a bottleneck. Thanks to some properties of GL we know inequalities that can
145 // help us make the overflow checks faster.
146
147 // The max possible attribSize is 16 for a vector of 4 32 bit values.
148 constexpr uint64_t kMaxAttribSize = 16;
149 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
150 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
151
152 // We know attribStride is given as a GLsizei which is typedefed to int.
153 // We also know an upper bound for attribSize.
154 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800155 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500156 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
157 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
158
159 // Computing the max offset using uint64_t without attrib.offset is overflow
160 // safe. Note: Last vertex element does not take the full stride!
161 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
162 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
163
164 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800165 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
166 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500167 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700168 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500169 return false;
170 }
171 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
172
173 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
174 // We can return INVALID_OPERATION if our vertex attribute does not have
175 // enough backing data.
176 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
177 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700178 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500179 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400180 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800181
182 if (webglCompatibility && buffer->isBoundForTransformFeedbackAndOtherUse())
183 {
184 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
185 VertexBufferBoundForTransformFeedback);
186 return false;
187 }
Jamie Madill1ca74672015-07-21 15:14:11 -0400188 }
189
190 return true;
191}
192
Geoff Lang280ba992017-04-18 16:30:58 -0400193bool ValidReadPixelsTypeEnum(ValidationContext *context, GLenum type)
194{
195 switch (type)
196 {
197 // Types referenced in Table 3.4 of the ES 2.0.25 spec
198 case GL_UNSIGNED_BYTE:
199 case GL_UNSIGNED_SHORT_4_4_4_4:
200 case GL_UNSIGNED_SHORT_5_5_5_1:
201 case GL_UNSIGNED_SHORT_5_6_5:
202 return context->getClientVersion() >= ES_2_0;
203
204 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
205 case GL_BYTE:
206 case GL_INT:
207 case GL_SHORT:
208 case GL_UNSIGNED_INT:
209 case GL_UNSIGNED_INT_10F_11F_11F_REV:
210 case GL_UNSIGNED_INT_24_8:
211 case GL_UNSIGNED_INT_2_10_10_10_REV:
212 case GL_UNSIGNED_INT_5_9_9_9_REV:
213 case GL_UNSIGNED_SHORT:
214 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
215 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
216 return context->getClientVersion() >= ES_3_0;
217
218 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400219 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
220 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400221
222 case GL_HALF_FLOAT:
223 return context->getClientVersion() >= ES_3_0 ||
224 context->getExtensions().textureHalfFloat;
225
226 case GL_HALF_FLOAT_OES:
227 return context->getExtensions().colorBufferHalfFloat;
228
229 default:
230 return false;
231 }
232}
233
234bool ValidReadPixelsFormatEnum(ValidationContext *context, GLenum format)
235{
236 switch (format)
237 {
238 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
239 case GL_RGBA:
240 case GL_RGB:
241 case GL_ALPHA:
242 return context->getClientVersion() >= ES_2_0;
243
244 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
245 case GL_RG:
246 case GL_RED:
247 case GL_RGBA_INTEGER:
248 case GL_RGB_INTEGER:
249 case GL_RG_INTEGER:
250 case GL_RED_INTEGER:
251 return context->getClientVersion() >= ES_3_0;
252
253 case GL_SRGB_ALPHA_EXT:
254 case GL_SRGB_EXT:
255 return context->getExtensions().sRGB;
256
257 case GL_BGRA_EXT:
258 return context->getExtensions().readFormatBGRA;
259
260 default:
261 return false;
262 }
263}
264
Geoff Langf607c602016-09-21 11:46:48 -0400265bool ValidReadPixelsFormatType(ValidationContext *context,
266 GLenum framebufferComponentType,
267 GLenum format,
268 GLenum type)
269{
270 switch (framebufferComponentType)
271 {
272 case GL_UNSIGNED_NORMALIZED:
273 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
274 // ReadPixels with BGRA even if the extension is not present
275 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
276 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
277 type == GL_UNSIGNED_BYTE);
278
279 case GL_SIGNED_NORMALIZED:
280 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
281
282 case GL_INT:
283 return (format == GL_RGBA_INTEGER && type == GL_INT);
284
285 case GL_UNSIGNED_INT:
286 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
287
288 case GL_FLOAT:
289 return (format == GL_RGBA && type == GL_FLOAT);
290
291 default:
292 UNREACHABLE();
293 return false;
294 }
295}
296
Geoff Langc1984ed2016-10-07 12:41:00 -0400297template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400298bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400299{
300 switch (ConvertToGLenum(params[0]))
301 {
302 case GL_CLAMP_TO_EDGE:
303 break;
304
305 case GL_REPEAT:
306 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400307 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400308 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400309 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700310 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400311 return false;
312 }
313 break;
314
315 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700316 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400317 return false;
318 }
319
320 return true;
321}
322
323template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400324bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400325{
326 switch (ConvertToGLenum(params[0]))
327 {
328 case GL_NEAREST:
329 case GL_LINEAR:
330 break;
331
332 case GL_NEAREST_MIPMAP_NEAREST:
333 case GL_LINEAR_MIPMAP_NEAREST:
334 case GL_NEAREST_MIPMAP_LINEAR:
335 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400336 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400337 {
338 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700339 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400340 return false;
341 }
342 break;
343
344 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700345 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400346 return false;
347 }
348
349 return true;
350}
351
352template <typename ParamType>
353bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
354{
355 switch (ConvertToGLenum(params[0]))
356 {
357 case GL_NEAREST:
358 case GL_LINEAR:
359 break;
360
361 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700362 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400363 return false;
364 }
365
366 return true;
367}
368
369template <typename ParamType>
370bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
371{
372 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
373 switch (ConvertToGLenum(params[0]))
374 {
375 case GL_NONE:
376 case GL_COMPARE_REF_TO_TEXTURE:
377 break;
378
379 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700380 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400381 return false;
382 }
383
384 return true;
385}
386
387template <typename ParamType>
388bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
389{
390 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
391 switch (ConvertToGLenum(params[0]))
392 {
393 case GL_LEQUAL:
394 case GL_GEQUAL:
395 case GL_LESS:
396 case GL_GREATER:
397 case GL_EQUAL:
398 case GL_NOTEQUAL:
399 case GL_ALWAYS:
400 case GL_NEVER:
401 break;
402
403 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700404 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400405 return false;
406 }
407
408 return true;
409}
410
411template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700412bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
413{
414 if (!context->getExtensions().textureSRGBDecode)
415 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700416 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700417 return false;
418 }
419
420 switch (ConvertToGLenum(params[0]))
421 {
422 case GL_DECODE_EXT:
423 case GL_SKIP_DECODE_EXT:
424 break;
425
426 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700427 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700428 return false;
429 }
430
431 return true;
432}
433
Luc Ferron1b1a8642018-01-23 15:12:01 -0500434bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
435{
436 if (!context->getExtensions().textureFilterAnisotropic)
437 {
438 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
439 return false;
440 }
441
442 return true;
443}
444
445bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
446{
447 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
448 {
449 return false;
450 }
451
452 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
453
454 if (paramValue < 1 || paramValue > largest)
455 {
456 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
457 return false;
458 }
459
460 return true;
461}
462
Geoff Lange0cff192017-05-30 13:04:56 -0400463bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
464{
465 const Program *program = context->getGLState().getProgram();
466 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
467
Brandon Jonesc405ae72017-12-06 14:15:03 -0800468 if (!ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
469 framebuffer->getDrawBufferTypeMask().to_ulong(),
470 program->getActiveOutputVariables().to_ulong(),
471 framebuffer->getDrawBufferMask().to_ulong()))
Geoff Lange0cff192017-05-30 13:04:56 -0400472 {
Brandon Jones76746f92017-11-22 11:44:41 -0800473 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
474 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400475 }
476
477 return true;
478}
479
Geoff Lang9ab5b822017-05-30 16:19:23 -0400480bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
481{
Jamie Madillcac94a92017-11-10 10:09:32 -0500482 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400483 const Program *program = context->getGLState().getProgram();
484 const VertexArray *vao = context->getGLState().getVertexArray();
485
Brandon Jonesc405ae72017-12-06 14:15:03 -0800486 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
487 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
488 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
489
490 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
491 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
492 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
493
494 if (!ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
495 program->getAttributesMask().to_ulong(), 0xFFFF))
Geoff Lang9ab5b822017-05-30 16:19:23 -0400496 {
Brandon Jonesc405ae72017-12-06 14:15:03 -0800497 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexShaderTypeMismatch);
498 return false;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400499 }
Geoff Lang9ab5b822017-05-30 16:19:23 -0400500 return true;
501}
502
Geoff Langf41a7152016-09-19 15:11:17 -0400503} // anonymous namespace
504
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500505bool IsETC2EACFormat(const GLenum format)
506{
507 // ES 3.1, Table 8.19
508 switch (format)
509 {
510 case GL_COMPRESSED_R11_EAC:
511 case GL_COMPRESSED_SIGNED_R11_EAC:
512 case GL_COMPRESSED_RG11_EAC:
513 case GL_COMPRESSED_SIGNED_RG11_EAC:
514 case GL_COMPRESSED_RGB8_ETC2:
515 case GL_COMPRESSED_SRGB8_ETC2:
516 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
517 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
518 case GL_COMPRESSED_RGBA8_ETC2_EAC:
519 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
520 return true;
521
522 default:
523 return false;
524 }
525}
526
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800527bool ValidTextureTarget(const ValidationContext *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400528{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800529 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400530 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800531 case TextureType::_2D:
532 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800533 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400534
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800535 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400536 return context->getExtensions().textureRectangle;
537
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800538 case TextureType::_3D:
539 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800540 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500541
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800542 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800543 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400544
He Yunchaoced53ae2016-11-29 15:00:51 +0800545 default:
546 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500547 }
Jamie Madill35d15012013-10-07 10:46:37 -0400548}
549
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800550bool ValidTexture2DTarget(const ValidationContext *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500551{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800552 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500553 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800554 case TextureType::_2D:
555 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500556 return true;
557
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800558 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400559 return context->getExtensions().textureRectangle;
560
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500561 default:
562 return false;
563 }
564}
565
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800566bool ValidTexture3DTarget(const ValidationContext *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500567{
568 switch (target)
569 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800570 case TextureType::_3D:
571 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300572 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500573
574 default:
575 return false;
576 }
577}
578
Ian Ewellbda75592016-04-18 17:25:54 -0400579// Most texture GL calls are not compatible with external textures, so we have a separate validation
580// function for use in the GL calls that do
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800581bool ValidTextureExternalTarget(const ValidationContext *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400582{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800583 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400584 (context->getExtensions().eglImageExternal ||
585 context->getExtensions().eglStreamConsumerExternal);
586}
587
Shannon Woods4dfed832014-03-17 20:03:39 -0400588// This function differs from ValidTextureTarget in that the target must be
589// usable as the destination of a 2D operation-- so a cube face is valid, but
590// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400591// Note: duplicate of IsInternalTextureTarget
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800592bool ValidTexture2DDestinationTarget(const ValidationContext *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400593{
594 switch (target)
595 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800596 case TextureTarget::_2D:
597 case TextureTarget::CubeMapNegativeX:
598 case TextureTarget::CubeMapNegativeY:
599 case TextureTarget::CubeMapNegativeZ:
600 case TextureTarget::CubeMapPositiveX:
601 case TextureTarget::CubeMapPositiveY:
602 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800603 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800604 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400605 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800606 default:
607 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500608 }
609}
610
Jamie Madillbe849e42017-05-02 15:49:00 -0400611bool ValidateDrawElementsInstancedBase(ValidationContext *context,
612 GLenum mode,
613 GLsizei count,
614 GLenum type,
615 const GLvoid *indices,
616 GLsizei primcount)
617{
618 if (primcount < 0)
619 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700620 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400621 return false;
622 }
623
624 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
625 {
626 return false;
627 }
628
Jamie Madill9fdaa492018-02-16 10:52:11 -0500629 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400630}
631
632bool ValidateDrawArraysInstancedBase(Context *context,
633 GLenum mode,
634 GLint first,
635 GLsizei count,
636 GLsizei primcount)
637{
638 if (primcount < 0)
639 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700640 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400641 return false;
642 }
643
644 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
645 {
646 return false;
647 }
648
Jamie Madill9fdaa492018-02-16 10:52:11 -0500649 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400650}
651
Corentin Wallez0dc97812017-06-22 14:38:44 -0400652bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400653{
654 // Verify there is at least one active attribute with a divisor of zero
655 const State &state = context->getGLState();
656
657 Program *program = state.getProgram();
658
659 const auto &attribs = state.getVertexArray()->getVertexAttributes();
660 const auto &bindings = state.getVertexArray()->getVertexBindings();
661 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
662 {
663 const VertexAttribute &attrib = attribs[attributeIndex];
664 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300665 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400666 {
667 return true;
668 }
669 }
670
Brandon Jonesafa75152017-07-21 13:11:29 -0700671 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400672 return false;
673}
674
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800675bool ValidTexture3DDestinationTarget(const ValidationContext *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500676{
677 switch (target)
678 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800679 case TextureType::_3D:
680 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800681 return true;
682 default:
683 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400684 }
685}
686
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800687bool ValidTexLevelDestinationTarget(const ValidationContext *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800688{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800689 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800690 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800691 case TextureType::_2D:
692 case TextureType::_2DArray:
693 case TextureType::_2DMultisample:
694 case TextureType::CubeMap:
695 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800696 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800697 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400698 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800699 default:
700 return false;
701 }
702}
703
Geoff Lange8afa902017-09-27 15:00:43 -0400704bool ValidFramebufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500705{
He Yunchaoced53ae2016-11-29 15:00:51 +0800706 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
707 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400708 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500709
710 switch (target)
711 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800712 case GL_FRAMEBUFFER:
713 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400714
He Yunchaoced53ae2016-11-29 15:00:51 +0800715 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800716 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400717 return (context->getExtensions().framebufferBlit ||
718 context->getClientMajorVersion() >= 3);
719
He Yunchaoced53ae2016-11-29 15:00:51 +0800720 default:
721 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500722 }
723}
724
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800725bool ValidMipLevel(const ValidationContext *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400726{
Jamie Madillc29968b2016-01-20 11:17:23 -0500727 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400728 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800729 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400730 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800731 case TextureType::_2D:
732 case TextureType::_2DArray:
733 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500734 maxDimension = caps.max2DTextureSize;
735 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800736 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800737 maxDimension = caps.maxCubeMapTextureSize;
738 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800739 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400740 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800741 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800742 maxDimension = caps.max3DTextureSize;
743 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800744 default:
745 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400746 }
747
Brandon Jones6cad5662017-06-14 13:25:13 -0700748 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400749}
750
Brandon Jones6cad5662017-06-14 13:25:13 -0700751bool ValidImageSizeParameters(ValidationContext *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800752 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700753 GLint level,
754 GLsizei width,
755 GLsizei height,
756 GLsizei depth,
757 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400758{
Brandon Jones6cad5662017-06-14 13:25:13 -0700759 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400760 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700761 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400762 return false;
763 }
Austin Kinross08528e12015-10-07 16:24:40 -0700764 // TexSubImage parameters can be NPOT without textureNPOT extension,
765 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500766 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500767 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500768 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400769 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400770 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700771 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400772 return false;
773 }
774
775 if (!ValidMipLevel(context, target, level))
776 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700777 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400778 return false;
779 }
780
781 return true;
782}
783
Geoff Lang966c9402017-04-18 12:38:27 -0400784bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
785{
786 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
787 (size % blockSize == 0);
788}
789
Jamie Madillc29968b2016-01-20 11:17:23 -0500790bool ValidCompressedImageSize(const ValidationContext *context,
791 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400792 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500793 GLsizei width,
794 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400795{
Geoff Langca271392017-04-05 12:30:00 -0400796 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400797 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400798 {
799 return false;
800 }
801
Geoff Lang966c9402017-04-18 12:38:27 -0400802 if (width < 0 || height < 0)
803 {
804 return false;
805 }
806
807 if (CompressedTextureFormatRequiresExactSize(internalFormat))
808 {
809 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
810 // block size for level 0 but WebGL disallows this.
811 bool smallerThanBlockSizeAllowed =
812 level > 0 || !context->getExtensions().webglCompatibility;
813
814 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
815 smallerThanBlockSizeAllowed) ||
816 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
817 smallerThanBlockSizeAllowed))
818 {
819 return false;
820 }
821 }
822
823 return true;
824}
825
826bool ValidCompressedSubImageSize(const ValidationContext *context,
827 GLenum internalFormat,
828 GLint xoffset,
829 GLint yoffset,
830 GLsizei width,
831 GLsizei height,
832 size_t textureWidth,
833 size_t textureHeight)
834{
835 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
836 if (!formatInfo.compressed)
837 {
838 return false;
839 }
840
Geoff Lang44ff5a72017-02-03 15:15:43 -0500841 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400842 {
843 return false;
844 }
845
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500846 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400847 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500848 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400849 yoffset % formatInfo.compressedBlockHeight != 0)
850 {
851 return false;
852 }
853
854 // Allowed to either have data that is a multiple of block size or is smaller than the block
855 // size but fills the entire mip
856 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
857 static_cast<size_t>(width) == textureWidth &&
858 static_cast<size_t>(height) == textureHeight;
859 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
860 (height % formatInfo.compressedBlockHeight) == 0;
861 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400862 {
863 return false;
864 }
865 }
866
Geoff Langd4f180b2013-09-24 13:57:44 -0400867 return true;
868}
869
Geoff Langff5b2d52016-09-07 11:32:23 -0400870bool ValidImageDataSize(ValidationContext *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800871 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400872 GLsizei width,
873 GLsizei height,
874 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400875 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400876 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400877 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400878 GLsizei imageSize)
879{
Corentin Wallez336129f2017-10-17 15:55:40 -0400880 gl::Buffer *pixelUnpackBuffer =
881 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400882 if (pixelUnpackBuffer == nullptr && imageSize < 0)
883 {
884 // Checks are not required
885 return true;
886 }
887
888 // ...the data would be unpacked from the buffer object such that the memory reads required
889 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400890 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
891 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400892 const gl::Extents size(width, height, depth);
893 const auto &unpack = context->getGLState().getUnpackState();
894
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800895 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Geoff Langff5b2d52016-09-07 11:32:23 -0400896 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
897 if (endByteOrErr.isError())
898 {
899 context->handleError(endByteOrErr.getError());
900 return false;
901 }
902
903 GLuint endByte = endByteOrErr.getResult();
904
905 if (pixelUnpackBuffer)
906 {
907 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
908 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
909 checkedEndByte += checkedOffset;
910
911 if (!checkedEndByte.IsValid() ||
912 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
913 {
914 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500915 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -0400916 return false;
917 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800918 if (context->getExtensions().webglCompatibility &&
919 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
920 {
921 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
922 PixelUnpackBufferBoundForTransformFeedback);
923 return false;
924 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400925 }
926 else
927 {
928 ASSERT(imageSize >= 0);
929 if (pixels == nullptr && imageSize != 0)
930 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500931 context->handleError(InvalidOperation()
932 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400933 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400934 }
935
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400936 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400937 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500938 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400939 return false;
940 }
941 }
942
943 return true;
944}
945
Geoff Lang37dde692014-01-31 16:34:54 -0500946bool ValidQueryType(const Context *context, GLenum queryType)
947{
He Yunchaoced53ae2016-11-29 15:00:51 +0800948 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
949 "GL extension enums not equal.");
950 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
951 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -0500952
953 switch (queryType)
954 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800955 case GL_ANY_SAMPLES_PASSED:
956 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400957 return context->getClientMajorVersion() >= 3 ||
958 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +0800959 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
960 return (context->getClientMajorVersion() >= 3);
961 case GL_TIME_ELAPSED_EXT:
962 return context->getExtensions().disjointTimerQuery;
963 case GL_COMMANDS_COMPLETED_CHROMIUM:
964 return context->getExtensions().syncQuery;
965 default:
966 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500967 }
968}
969
Geoff Lang2d62ab72017-03-23 16:54:40 -0400970bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
971 GLenum type,
972 GLboolean normalized,
973 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400974 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400975 bool pureInteger)
976{
977 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400978 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
979 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
980 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
981 // parameter exceeds 255.
982 constexpr GLsizei kMaxWebGLStride = 255;
983 if (stride > kMaxWebGLStride)
984 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500985 context->handleError(InvalidValue()
986 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -0400987 return false;
988 }
989
990 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
991 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
992 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
993 // or an INVALID_OPERATION error is generated.
994 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
995 size_t typeSize = GetVertexFormatTypeSize(internalType);
996
997 ASSERT(isPow2(typeSize) && typeSize > 0);
998 size_t sizeMask = (typeSize - 1);
999 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1000 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001001 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001002 return false;
1003 }
1004
1005 if ((stride & sizeMask) != 0)
1006 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001007 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001008 return false;
1009 }
1010
1011 return true;
1012}
1013
Jamie Madillef300b12016-10-07 15:12:09 -04001014Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001015{
He Yunchaoced53ae2016-11-29 15:00:51 +08001016 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1017 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1018 // or program object and INVALID_OPERATION if the provided name identifies an object
1019 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001020
Dian Xiang769769a2015-09-09 15:20:08 -07001021 Program *validProgram = context->getProgram(id);
1022
1023 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001024 {
Dian Xiang769769a2015-09-09 15:20:08 -07001025 if (context->getShader(id))
1026 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001027 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001028 }
1029 else
1030 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001031 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001032 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001033 }
Dian Xiang769769a2015-09-09 15:20:08 -07001034
1035 return validProgram;
1036}
1037
Jamie Madillef300b12016-10-07 15:12:09 -04001038Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001039{
1040 // See ValidProgram for spec details.
1041
1042 Shader *validShader = context->getShader(id);
1043
1044 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001045 {
Dian Xiang769769a2015-09-09 15:20:08 -07001046 if (context->getProgram(id))
1047 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001048 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001049 }
1050 else
1051 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001052 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001053 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001054 }
Dian Xiang769769a2015-09-09 15:20:08 -07001055
1056 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001057}
1058
Geoff Langb1196682014-07-23 13:47:29 -04001059bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001060{
Geoff Langfa125c92017-10-24 13:01:46 -04001061 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001062 {
Geoff Langfa125c92017-10-24 13:01:46 -04001063 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1064 {
1065 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1066 return false;
1067 }
Jamie Madillb4472272014-07-03 10:38:55 -04001068
Geoff Langfa125c92017-10-24 13:01:46 -04001069 // Color attachment 0 is validated below because it is always valid
1070 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001071 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001072 {
Geoff Langfa125c92017-10-24 13:01:46 -04001073 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001074 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001075 }
1076 }
1077 else
1078 {
1079 switch (attachment)
1080 {
Geoff Langfa125c92017-10-24 13:01:46 -04001081 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001082 case GL_DEPTH_ATTACHMENT:
1083 case GL_STENCIL_ATTACHMENT:
1084 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001085
He Yunchaoced53ae2016-11-29 15:00:51 +08001086 case GL_DEPTH_STENCIL_ATTACHMENT:
1087 if (!context->getExtensions().webglCompatibility &&
1088 context->getClientMajorVersion() < 3)
1089 {
Geoff Langfa125c92017-10-24 13:01:46 -04001090 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001091 return false;
1092 }
1093 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001094
He Yunchaoced53ae2016-11-29 15:00:51 +08001095 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001096 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001097 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001098 }
1099 }
1100
1101 return true;
1102}
1103
Jamie Madille8fb6402017-02-14 17:56:40 -05001104bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001105 GLenum target,
1106 GLsizei samples,
1107 GLenum internalformat,
1108 GLsizei width,
1109 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001110{
1111 switch (target)
1112 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001113 case GL_RENDERBUFFER:
1114 break;
1115 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001116 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001117 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001118 }
1119
1120 if (width < 0 || height < 0 || samples < 0)
1121 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001122 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001123 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001124 }
1125
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001126 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1127 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1128
1129 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001130 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001131 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001132 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001133 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001134 }
1135
1136 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1137 // 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 -08001138 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001139 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1140 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001141 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001142 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001143 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001144 }
1145
Geoff Langaae65a42014-05-26 12:43:44 -04001146 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001147 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001148 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001149 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001150 }
1151
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001152 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001153 if (handle == 0)
1154 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001155 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001156 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001157 }
1158
1159 return true;
1160}
1161
He Yunchaoced53ae2016-11-29 15:00:51 +08001162bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1163 GLenum target,
1164 GLenum attachment,
1165 GLenum renderbuffertarget,
1166 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001167{
Geoff Lange8afa902017-09-27 15:00:43 -04001168 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001169 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001170 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001171 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001172 }
1173
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001174 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001175
Jamie Madill84115c92015-04-23 15:00:07 -04001176 ASSERT(framebuffer);
1177 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001178 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001179 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001180 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001181 }
1182
Jamie Madillb4472272014-07-03 10:38:55 -04001183 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001184 {
Jamie Madillb4472272014-07-03 10:38:55 -04001185 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001186 }
1187
Jamie Madillab9d82c2014-01-21 16:38:14 -05001188 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1189 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1190 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1191 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1192 if (renderbuffer != 0)
1193 {
1194 if (!context->getRenderbuffer(renderbuffer))
1195 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001196 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001197 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001198 }
1199 }
1200
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001201 return true;
1202}
1203
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001204bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001205 GLint srcX0,
1206 GLint srcY0,
1207 GLint srcX1,
1208 GLint srcY1,
1209 GLint dstX0,
1210 GLint dstY0,
1211 GLint dstX1,
1212 GLint dstY1,
1213 GLbitfield mask,
1214 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001215{
1216 switch (filter)
1217 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001218 case GL_NEAREST:
1219 break;
1220 case GL_LINEAR:
1221 break;
1222 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001223 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001224 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001225 }
1226
1227 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1228 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001229 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001230 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001231 }
1232
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001233 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1234 // color buffer, leaving only nearest being unfiltered from above
1235 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1236 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001237 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001238 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001239 }
1240
Jamie Madill51f40ec2016-06-15 14:06:00 -04001241 const auto &glState = context->getGLState();
1242 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1243 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001244
1245 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001246 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001247 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001248 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001249 }
1250
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001251 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001252 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001253 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001254 return false;
1255 }
1256
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001257 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001258 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001259 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001260 return false;
1261 }
1262
Qin Jiajiaaef92162018-02-27 13:51:44 +08001263 if (readFramebuffer->id() == drawFramebuffer->id())
1264 {
1265 context->handleError(InvalidOperation());
1266 return false;
1267 }
1268
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001269 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001270 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001271 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001272 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001273 }
1274
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001275 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1276
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001277 if (mask & GL_COLOR_BUFFER_BIT)
1278 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001279 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001280 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001281
He Yunchao66a41a22016-12-15 16:45:05 +08001282 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001283 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001284 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001285
Geoff Langa15472a2015-08-11 11:48:03 -04001286 for (size_t drawbufferIdx = 0;
1287 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001288 {
Geoff Langa15472a2015-08-11 11:48:03 -04001289 const FramebufferAttachment *attachment =
1290 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1291 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001292 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001293 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001294
Geoff Langb2f3d052013-08-13 12:49:27 -04001295 // The GL ES 3.0.2 spec (pg 193) states that:
1296 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001297 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1298 // as well
1299 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1300 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001301 // Changes with EXT_color_buffer_float:
1302 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001303 GLenum readComponentType = readFormat.info->componentType;
1304 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001305 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001306 readComponentType == GL_SIGNED_NORMALIZED);
1307 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1308 drawComponentType == GL_SIGNED_NORMALIZED);
1309
1310 if (extensions.colorBufferFloat)
1311 {
1312 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1313 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1314
1315 if (readFixedOrFloat != drawFixedOrFloat)
1316 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001317 context->handleError(InvalidOperation()
1318 << "If the read buffer contains fixed-point or "
1319 "floating-point values, the draw buffer must "
1320 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001321 return false;
1322 }
1323 }
1324 else if (readFixedPoint != drawFixedPoint)
1325 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001326 context->handleError(InvalidOperation()
1327 << "If the read buffer contains fixed-point values, "
1328 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001329 return false;
1330 }
1331
1332 if (readComponentType == GL_UNSIGNED_INT &&
1333 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001334 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001335 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001336 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001337 }
1338
Jamie Madill6163c752015-12-07 16:32:59 -05001339 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001340 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001341 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001342 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001343 }
1344
Jamie Madilla3944d42016-07-22 22:13:26 -04001345 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001346 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001347 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001348 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001349 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001350 }
Geoff Lange4915782017-04-12 15:19:07 -04001351
1352 if (context->getExtensions().webglCompatibility &&
1353 *readColorBuffer == *attachment)
1354 {
1355 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001356 InvalidOperation()
1357 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001358 return false;
1359 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001360 }
1361 }
1362
Jamie Madilla3944d42016-07-22 22:13:26 -04001363 if ((readFormat.info->componentType == GL_INT ||
1364 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1365 filter == GL_LINEAR)
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 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001370 }
He Yunchao66a41a22016-12-15 16:45:05 +08001371 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1372 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1373 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1374 // situation is an application error that would lead to a crash in ANGLE.
1375 else if (drawFramebuffer->hasEnabledDrawBuffer())
1376 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001377 context->handleError(
1378 InvalidOperation()
1379 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001380 return false;
1381 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001382 }
1383
He Yunchaoced53ae2016-11-29 15:00:51 +08001384 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001385 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1386 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001387 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001388 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001389 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001390 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001391 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001392 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001393 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001394
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001395 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001396 {
Kenneth Russell69382852017-07-21 16:38:44 -04001397 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
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
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001403 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001404 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001405 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001406 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001407 }
Geoff Lange4915782017-04-12 15:19:07 -04001408
1409 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001411 context->handleError(
1412 InvalidOperation()
1413 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001414 return false;
1415 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001416 }
He Yunchao66a41a22016-12-15 16:45:05 +08001417 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1418 else if (drawBuffer)
1419 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001420 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1421 "depth/stencil attachment of a "
1422 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001423 return false;
1424 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001425 }
1426 }
1427
Martin Radeva3ed4572017-07-27 18:29:37 +03001428 // ANGLE_multiview, Revision 1:
1429 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1430 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1431 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1432 {
1433 context->handleError(InvalidFramebufferOperation()
1434 << "Attempt to read from a multi-view framebuffer.");
1435 return false;
1436 }
1437 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1438 {
1439 context->handleError(InvalidFramebufferOperation()
1440 << "Attempt to write to a multi-view framebuffer.");
1441 return false;
1442 }
1443
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001444 return true;
1445}
1446
Jamie Madill4928b7c2017-06-20 12:57:39 -04001447bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001448 GLint x,
1449 GLint y,
1450 GLsizei width,
1451 GLsizei height,
1452 GLenum format,
1453 GLenum type,
1454 GLsizei bufSize,
1455 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001456 GLsizei *columns,
1457 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001458 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001459{
1460 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001461 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001462 return false;
1463 }
1464
Geoff Lang62fce5b2016-09-30 10:46:35 -04001465 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001466 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001467 {
Geoff Langb1196682014-07-23 13:47:29 -04001468 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001469 }
1470
Geoff Lang62fce5b2016-09-30 10:46:35 -04001471 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001472 {
Geoff Langb1196682014-07-23 13:47:29 -04001473 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001474 }
1475
Jamie Madillc29968b2016-01-20 11:17:23 -05001476 return true;
1477}
1478
1479bool ValidateReadnPixelsEXT(Context *context,
1480 GLint x,
1481 GLint y,
1482 GLsizei width,
1483 GLsizei height,
1484 GLenum format,
1485 GLenum type,
1486 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001487 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001488{
1489 if (bufSize < 0)
1490 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001491 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001492 return false;
1493 }
1494
Geoff Lang62fce5b2016-09-30 10:46:35 -04001495 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001496 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001497}
Jamie Madill26e91952014-03-05 15:01:27 -05001498
Jamie Madill4928b7c2017-06-20 12:57:39 -04001499bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001500 GLint x,
1501 GLint y,
1502 GLsizei width,
1503 GLsizei height,
1504 GLenum format,
1505 GLenum type,
1506 GLsizei bufSize,
1507 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001508 GLsizei *columns,
1509 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001510 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001511{
1512 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001513 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001514 return false;
1515 }
1516
Geoff Lange93daba2017-03-30 13:54:40 -04001517 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1518 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001519 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001520 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001521 }
1522
Geoff Lang62fce5b2016-09-30 10:46:35 -04001523 if (!ValidateRobustBufferSize(context, bufSize, *length))
1524 {
1525 return false;
1526 }
1527
1528 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001529}
1530
Jamie Madillf0e04492017-08-26 15:28:42 -04001531bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001532{
1533 if (!context->getExtensions().occlusionQueryBoolean &&
1534 !context->getExtensions().disjointTimerQuery)
1535 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001536 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001537 return false;
1538 }
1539
Olli Etuaho41997e72016-03-10 13:38:39 +02001540 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001541}
1542
Jamie Madillf0e04492017-08-26 15:28:42 -04001543bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001544{
1545 if (!context->getExtensions().occlusionQueryBoolean &&
1546 !context->getExtensions().disjointTimerQuery)
1547 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001548 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001549 return false;
1550 }
1551
Olli Etuaho41997e72016-03-10 13:38:39 +02001552 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001553}
1554
Jamie Madillf0e04492017-08-26 15:28:42 -04001555bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1556{
1557 if (!context->getExtensions().occlusionQueryBoolean &&
1558 !context->getExtensions().disjointTimerQuery)
1559 {
1560 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1561 return false;
1562 }
1563
1564 return true;
1565}
1566
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001567bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001568{
1569 if (!ValidQueryType(context, target))
1570 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001571 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001572 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001573 }
1574
1575 if (id == 0)
1576 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001577 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001578 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001579 }
1580
1581 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1582 // of zero, if the active query object name for <target> is non-zero (for the
1583 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1584 // the active query for either target is non-zero), if <id> is the name of an
1585 // existing query object whose type does not match <target>, or if <id> is the
1586 // active query object name for any query type, the error INVALID_OPERATION is
1587 // generated.
1588
1589 // Ensure no other queries are active
1590 // NOTE: If other queries than occlusion are supported, we will need to check
1591 // separately that:
1592 // a) The query ID passed is not the current active query for any target/type
1593 // b) There are no active queries for the requested target (and in the case
1594 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1595 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001596
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001597 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001598 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001599 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001600 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001601 }
1602
1603 Query *queryObject = context->getQuery(id, true, target);
1604
1605 // check that name was obtained with glGenQueries
1606 if (!queryObject)
1607 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001608 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001609 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001610 }
1611
1612 // check for type mismatch
1613 if (queryObject->getType() != target)
1614 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001615 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001616 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001617 }
1618
1619 return true;
1620}
1621
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001622bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1623{
1624 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001625 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001626 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001627 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001628 return false;
1629 }
1630
1631 return ValidateBeginQueryBase(context, target, id);
1632}
1633
1634bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001635{
1636 if (!ValidQueryType(context, target))
1637 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001638 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001639 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001640 }
1641
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001642 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001643
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001644 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001645 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001646 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001647 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001648 }
1649
Jamie Madill45c785d2014-05-13 14:09:34 -04001650 return true;
1651}
1652
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001653bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1654{
1655 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001656 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001657 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001658 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001659 return false;
1660 }
1661
1662 return ValidateEndQueryBase(context, target);
1663}
1664
1665bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1666{
1667 if (!context->getExtensions().disjointTimerQuery)
1668 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001669 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001670 return false;
1671 }
1672
1673 if (target != GL_TIMESTAMP_EXT)
1674 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001675 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001676 return false;
1677 }
1678
1679 Query *queryObject = context->getQuery(id, true, target);
1680 if (queryObject == nullptr)
1681 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001682 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001683 return false;
1684 }
1685
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001686 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001687 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001688 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001689 return false;
1690 }
1691
1692 return true;
1693}
1694
Geoff Lang2186c382016-10-14 10:54:54 -04001695bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001696{
Geoff Lang2186c382016-10-14 10:54:54 -04001697 if (numParams)
1698 {
1699 *numParams = 0;
1700 }
1701
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001702 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1703 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001704 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001705 return false;
1706 }
1707
1708 switch (pname)
1709 {
1710 case GL_CURRENT_QUERY_EXT:
1711 if (target == GL_TIMESTAMP_EXT)
1712 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001713 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001714 return false;
1715 }
1716 break;
1717 case GL_QUERY_COUNTER_BITS_EXT:
1718 if (!context->getExtensions().disjointTimerQuery ||
1719 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1720 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001721 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001722 return false;
1723 }
1724 break;
1725 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001726 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001727 return false;
1728 }
1729
Geoff Lang2186c382016-10-14 10:54:54 -04001730 if (numParams)
1731 {
1732 // All queries return only one value
1733 *numParams = 1;
1734 }
1735
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001736 return true;
1737}
1738
1739bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1740{
1741 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001742 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001743 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001744 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001745 return false;
1746 }
1747
Geoff Lang2186c382016-10-14 10:54:54 -04001748 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001749}
1750
Geoff Lang2186c382016-10-14 10:54:54 -04001751bool ValidateGetQueryivRobustANGLE(Context *context,
1752 GLenum target,
1753 GLenum pname,
1754 GLsizei bufSize,
1755 GLsizei *length,
1756 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001757{
Geoff Lang2186c382016-10-14 10:54:54 -04001758 if (!ValidateRobustEntryPoint(context, bufSize))
1759 {
1760 return false;
1761 }
1762
1763 if (!ValidateGetQueryivBase(context, target, pname, length))
1764 {
1765 return false;
1766 }
1767
1768 if (!ValidateRobustBufferSize(context, bufSize, *length))
1769 {
1770 return false;
1771 }
1772
1773 return true;
1774}
1775
1776bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1777{
1778 if (numParams)
1779 {
1780 *numParams = 0;
1781 }
1782
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001783 Query *queryObject = context->getQuery(id, false, GL_NONE);
1784
1785 if (!queryObject)
1786 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001787 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001788 return false;
1789 }
1790
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001791 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001792 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001793 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001794 return false;
1795 }
1796
1797 switch (pname)
1798 {
1799 case GL_QUERY_RESULT_EXT:
1800 case GL_QUERY_RESULT_AVAILABLE_EXT:
1801 break;
1802
1803 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001804 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001805 return false;
1806 }
1807
Geoff Lang2186c382016-10-14 10:54:54 -04001808 if (numParams)
1809 {
1810 *numParams = 1;
1811 }
1812
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001813 return true;
1814}
1815
1816bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1817{
1818 if (!context->getExtensions().disjointTimerQuery)
1819 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001820 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001821 return false;
1822 }
Geoff Lang2186c382016-10-14 10:54:54 -04001823 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1824}
1825
1826bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1827 GLuint id,
1828 GLenum pname,
1829 GLsizei bufSize,
1830 GLsizei *length,
1831 GLint *params)
1832{
1833 if (!context->getExtensions().disjointTimerQuery)
1834 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001835 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001836 return false;
1837 }
1838
1839 if (!ValidateRobustEntryPoint(context, bufSize))
1840 {
1841 return false;
1842 }
1843
1844 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1845 {
1846 return false;
1847 }
1848
1849 if (!ValidateRobustBufferSize(context, bufSize, *length))
1850 {
1851 return false;
1852 }
1853
1854 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001855}
1856
1857bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1858{
1859 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001860 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001861 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001862 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001863 return false;
1864 }
Geoff Lang2186c382016-10-14 10:54:54 -04001865 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1866}
1867
1868bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1869 GLuint id,
1870 GLenum pname,
1871 GLsizei bufSize,
1872 GLsizei *length,
1873 GLuint *params)
1874{
1875 if (!context->getExtensions().disjointTimerQuery &&
1876 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1877 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001878 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001879 return false;
1880 }
1881
1882 if (!ValidateRobustEntryPoint(context, bufSize))
1883 {
1884 return false;
1885 }
1886
1887 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1888 {
1889 return false;
1890 }
1891
1892 if (!ValidateRobustBufferSize(context, bufSize, *length))
1893 {
1894 return false;
1895 }
1896
1897 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001898}
1899
1900bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1901{
1902 if (!context->getExtensions().disjointTimerQuery)
1903 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001904 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001905 return false;
1906 }
Geoff Lang2186c382016-10-14 10:54:54 -04001907 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1908}
1909
1910bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1911 GLuint id,
1912 GLenum pname,
1913 GLsizei bufSize,
1914 GLsizei *length,
1915 GLint64 *params)
1916{
1917 if (!context->getExtensions().disjointTimerQuery)
1918 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001919 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001920 return false;
1921 }
1922
1923 if (!ValidateRobustEntryPoint(context, bufSize))
1924 {
1925 return false;
1926 }
1927
1928 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1929 {
1930 return false;
1931 }
1932
1933 if (!ValidateRobustBufferSize(context, bufSize, *length))
1934 {
1935 return false;
1936 }
1937
1938 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001939}
1940
1941bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1942{
1943 if (!context->getExtensions().disjointTimerQuery)
1944 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001945 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001946 return false;
1947 }
Geoff Lang2186c382016-10-14 10:54:54 -04001948 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1949}
1950
1951bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1952 GLuint id,
1953 GLenum pname,
1954 GLsizei bufSize,
1955 GLsizei *length,
1956 GLuint64 *params)
1957{
1958 if (!context->getExtensions().disjointTimerQuery)
1959 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001960 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001961 return false;
1962 }
1963
1964 if (!ValidateRobustEntryPoint(context, bufSize))
1965 {
1966 return false;
1967 }
1968
1969 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1970 {
1971 return false;
1972 }
1973
1974 if (!ValidateRobustBufferSize(context, bufSize, *length))
1975 {
1976 return false;
1977 }
1978
1979 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001980}
1981
Jiajia Qin5451d532017-11-16 17:16:34 +08001982bool ValidateUniformCommonBase(ValidationContext *context,
1983 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05001984 GLint location,
1985 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08001986 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05001987{
Jiajia Qin5451d532017-11-16 17:16:34 +08001988 // TODO(Jiajia): Add image uniform check in future.
1989 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05001990 {
Jiajia Qin5451d532017-11-16 17:16:34 +08001991 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05001992 return false;
1993 }
1994
Jiajia Qin5451d532017-11-16 17:16:34 +08001995 if (!program)
1996 {
1997 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
1998 return false;
1999 }
2000
2001 if (!program->isLinked())
2002 {
2003 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2004 return false;
2005 }
2006
2007 if (location == -1)
2008 {
2009 // Silently ignore the uniform command
2010 return false;
2011 }
2012
2013 const auto &uniformLocations = program->getUniformLocations();
2014 size_t castedLocation = static_cast<size_t>(location);
2015 if (castedLocation >= uniformLocations.size())
2016 {
2017 context->handleError(InvalidOperation() << "Invalid uniform location");
2018 return false;
2019 }
2020
2021 const auto &uniformLocation = uniformLocations[castedLocation];
2022 if (uniformLocation.ignored)
2023 {
2024 // Silently ignore the uniform command
2025 return false;
2026 }
2027
2028 if (!uniformLocation.used())
2029 {
2030 context->handleError(InvalidOperation());
2031 return false;
2032 }
2033
2034 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2035
2036 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2037 if (!uniform.isArray() && count > 1)
2038 {
2039 context->handleError(InvalidOperation());
2040 return false;
2041 }
2042
2043 *uniformOut = &uniform;
2044 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002045}
2046
Jiajia Qin5451d532017-11-16 17:16:34 +08002047bool ValidateUniform1ivValue(ValidationContext *context,
2048 GLenum uniformType,
2049 GLsizei count,
2050 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002051{
Jiajia Qin5451d532017-11-16 17:16:34 +08002052 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2053 // It is compatible with INT or BOOL.
2054 // Do these cheap tests first, for a little extra speed.
2055 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002056 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002057 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002058 }
2059
Jiajia Qin5451d532017-11-16 17:16:34 +08002060 if (IsSamplerType(uniformType))
2061 {
2062 // Check that the values are in range.
2063 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2064 for (GLsizei i = 0; i < count; ++i)
2065 {
2066 if (value[i] < 0 || value[i] >= max)
2067 {
2068 context->handleError(InvalidValue() << "sampler uniform value out of range");
2069 return false;
2070 }
2071 }
2072 return true;
2073 }
2074
2075 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2076 return false;
2077}
2078
2079bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2080{
2081 // Check that the value type is compatible with uniform type.
2082 // Do the cheaper test first, for a little extra speed.
2083 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2084 {
2085 return true;
2086 }
2087
2088 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2089 return false;
2090}
2091
2092bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2093{
2094 // Check that the value type is compatible with uniform type.
2095 if (valueType == uniformType)
2096 {
2097 return true;
2098 }
2099
2100 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2101 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002102}
2103
Jamie Madillc1d770e2017-04-13 17:31:24 -04002104bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002105{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002106 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002107 gl::Program *programObject = context->getGLState().getProgram();
2108 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2109 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002110}
2111
Jamie Madillbe849e42017-05-02 15:49:00 -04002112bool ValidateUniform1iv(ValidationContext *context,
2113 GLint location,
2114 GLsizei count,
2115 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002116{
2117 const LinkedUniform *uniform = nullptr;
2118 gl::Program *programObject = context->getGLState().getProgram();
2119 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2120 ValidateUniform1ivValue(context, uniform->type, count, value);
2121}
2122
Jamie Madillc1d770e2017-04-13 17:31:24 -04002123bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002124 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002125 GLint location,
2126 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002127 GLboolean transpose)
2128{
Geoff Lang92019432017-11-20 13:09:34 -05002129 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002130 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002131 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002132 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002133 }
2134
Jamie Madill62d31cb2015-09-11 13:25:51 -04002135 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002136 gl::Program *programObject = context->getGLState().getProgram();
2137 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2138 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002139}
2140
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002141bool ValidateStateQuery(ValidationContext *context,
2142 GLenum pname,
2143 GLenum *nativeType,
2144 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002145{
2146 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2147 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002148 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002149 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002150 }
2151
Jamie Madill0af26e12015-03-05 19:54:33 -05002152 const Caps &caps = context->getCaps();
2153
Jamie Madill893ab082014-05-16 16:56:10 -04002154 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2155 {
2156 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2157
Jamie Madill0af26e12015-03-05 19:54:33 -05002158 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002159 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002160 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002161 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002162 }
2163 }
2164
2165 switch (pname)
2166 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002167 case GL_TEXTURE_BINDING_2D:
2168 case GL_TEXTURE_BINDING_CUBE_MAP:
2169 case GL_TEXTURE_BINDING_3D:
2170 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002171 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002172 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002173 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2174 if (!context->getExtensions().textureRectangle)
2175 {
2176 context->handleError(InvalidEnum()
2177 << "ANGLE_texture_rectangle extension not present");
2178 return false;
2179 }
2180 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002181 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2182 if (!context->getExtensions().eglStreamConsumerExternal &&
2183 !context->getExtensions().eglImageExternal)
2184 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002185 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2186 "nor GL_OES_EGL_image_external "
2187 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002188 return false;
2189 }
2190 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002191
He Yunchaoced53ae2016-11-29 15:00:51 +08002192 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2193 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002194 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002195 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2196 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002197 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002198 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002199 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002200 }
2201
Jamie Madill51f40ec2016-06-15 14:06:00 -04002202 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2203 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002204
2205 if (framebuffer->getReadBufferState() == GL_NONE)
2206 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002207 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002208 return false;
2209 }
2210
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002211 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002212 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002213 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002214 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002215 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002216 }
2217 }
2218 break;
2219
He Yunchaoced53ae2016-11-29 15:00:51 +08002220 default:
2221 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002222 }
2223
2224 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002225 if (*numParams == 0)
2226 {
2227 return false;
2228 }
2229
2230 return true;
2231}
2232
2233bool ValidateRobustStateQuery(ValidationContext *context,
2234 GLenum pname,
2235 GLsizei bufSize,
2236 GLenum *nativeType,
2237 unsigned int *numParams)
2238{
2239 if (!ValidateRobustEntryPoint(context, bufSize))
2240 {
2241 return false;
2242 }
2243
2244 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2245 {
2246 return false;
2247 }
2248
2249 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002250 {
2251 return false;
2252 }
2253
2254 return true;
2255}
2256
Jamie Madillc29968b2016-01-20 11:17:23 -05002257bool ValidateCopyTexImageParametersBase(ValidationContext *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002258 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002259 GLint level,
2260 GLenum internalformat,
2261 bool isSubImage,
2262 GLint xoffset,
2263 GLint yoffset,
2264 GLint zoffset,
2265 GLint x,
2266 GLint y,
2267 GLsizei width,
2268 GLsizei height,
2269 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002270 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002271{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002272 TextureType texType = TextureTargetToType(target);
2273
Brandon Jones6cad5662017-06-14 13:25:13 -07002274 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002275 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002276 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2277 return false;
2278 }
2279
2280 if (width < 0 || height < 0)
2281 {
2282 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002283 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002284 }
2285
He Yunchaoced53ae2016-11-29 15:00:51 +08002286 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2287 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002288 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002289 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002290 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002291 }
2292
2293 if (border != 0)
2294 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002295 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002296 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002297 }
2298
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002299 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002300 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002301 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002302 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002303 }
2304
Jamie Madill51f40ec2016-06-15 14:06:00 -04002305 const auto &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002306 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002307 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002308 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002309 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002310 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002311 }
2312
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002313 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002314 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002315 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002316 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002317 }
2318
Martin Radev138064f2016-07-15 12:03:41 +03002319 if (readFramebuffer->getReadBufferState() == GL_NONE)
2320 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002321 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002322 return false;
2323 }
2324
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002325 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2326 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002327 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002328 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002329 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2330 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002331 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002332 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002333 return false;
2334 }
2335
Martin Radev04e2c3b2017-07-27 16:54:35 +03002336 // ANGLE_multiview spec, Revision 1:
2337 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2338 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2339 // is not NONE.
2340 if (source->getMultiviewLayout() != GL_NONE)
2341 {
2342 context->handleError(InvalidFramebufferOperation()
2343 << "The active read framebuffer object has multiview attachments.");
2344 return false;
2345 }
2346
Geoff Langaae65a42014-05-26 12:43:44 -04002347 const gl::Caps &caps = context->getCaps();
2348
Geoff Langaae65a42014-05-26 12:43:44 -04002349 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002350 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002351 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002352 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002353 maxDimension = caps.max2DTextureSize;
2354 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002355
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002356 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002357 maxDimension = caps.maxCubeMapTextureSize;
2358 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002359
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002360 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002361 maxDimension = caps.maxRectangleTextureSize;
2362 break;
2363
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002364 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002365 maxDimension = caps.max2DTextureSize;
2366 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002367
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002368 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002369 maxDimension = caps.max3DTextureSize;
2370 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002371
He Yunchaoced53ae2016-11-29 15:00:51 +08002372 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002373 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002374 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002375 }
2376
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002377 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002378 if (!texture)
2379 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002380 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002381 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002382 }
2383
Geoff Lang69cce582015-09-17 13:20:36 -04002384 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002385 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002386 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002387 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002388 }
2389
Geoff Langca271392017-04-05 12:30:00 -04002390 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002391 isSubImage ? *texture->getFormat(target, level).info
2392 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002393
Geoff Lang966c9402017-04-18 12:38:27 -04002394 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002395 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002396 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002397 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002398 }
2399
2400 if (isSubImage)
2401 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002402 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2403 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2404 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002406 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002407 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002408 }
2409 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002410 else
2411 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002412 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002413 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002414 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002415 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002416 }
2417
Geoff Langeb66a6e2016-10-31 13:06:12 -04002418 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002419 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002420 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002421 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002422 }
2423
2424 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002425 if (static_cast<int>(width) > maxLevelDimension ||
2426 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002427 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002428 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002429 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002430 }
2431 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002432
Jamie Madill0c8abca2016-07-22 20:21:26 -04002433 if (textureFormatOut)
2434 {
2435 *textureFormatOut = texture->getFormat(target, level);
2436 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002437
2438 // Detect texture copying feedback loops for WebGL.
2439 if (context->getExtensions().webglCompatibility)
2440 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002441 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002442 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002443 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002444 return false;
2445 }
2446 }
2447
Jamie Madill560a8d82014-05-21 13:06:20 -04002448 return true;
2449}
2450
Jiajia Qind9671222016-11-29 16:30:31 +08002451bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002452{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002453 switch (mode)
2454 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002455 case GL_POINTS:
2456 case GL_LINES:
2457 case GL_LINE_LOOP:
2458 case GL_LINE_STRIP:
2459 case GL_TRIANGLES:
2460 case GL_TRIANGLE_STRIP:
2461 case GL_TRIANGLE_FAN:
2462 break;
2463 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002464 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002465 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002466 }
2467
Jamie Madill250d33f2014-06-06 17:09:03 -04002468 if (count < 0)
2469 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002470 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002471 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002472 }
2473
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002474 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002475
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002476 const Extensions &extensions = context->getExtensions();
2477
2478 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2479 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2480 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2481 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002482 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002483 // Check for mapped buffers
2484 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002485 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002486 {
2487 context->handleError(InvalidOperation());
2488 return false;
2489 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002490 }
2491
Jamie Madillcbcde722017-01-06 14:50:00 -05002492 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2493 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002494 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002495 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002496 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002497 const FramebufferAttachment *dsAttachment =
2498 framebuffer->getStencilOrDepthStencilAttachment();
2499 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002500 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002501 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002502
2503 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2504 bool differentWritemasks =
2505 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2506 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2507 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2508 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2509
2510 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002511 {
Martin Radevffe754b2017-07-31 10:38:07 +03002512 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002513 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002514 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2515 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002516 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002517 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002518 return false;
2519 }
Jamie Madillac528012014-06-20 13:21:23 -04002520 }
2521
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002522 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002523 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002524 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002525 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002526 }
2527
Geoff Lang7dd2e102014-11-10 15:19:26 -05002528 gl::Program *program = state.getProgram();
2529 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002530 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002531 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002532 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002533 }
2534
Yunchao Hecddcb592017-11-13 15:27:35 +08002535 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2536 // vertex shader stage or fragment shader stage is a undefined behaviour.
2537 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2538 // produce undefined result.
Yunchao Heece12532017-11-21 15:50:21 +08002539 if (!program->hasLinkedVertexShader() || !program->hasLinkedFragmentShader())
Yunchao Hecddcb592017-11-13 15:27:35 +08002540 {
2541 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2542 "vertex shader stage or fragment shader stage.");
2543 return false;
2544 }
2545
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002546 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002547 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002548 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002549 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002550 }
2551
Martin Radevffe754b2017-07-31 10:38:07 +03002552 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002553 {
Martin Radevda8e2572017-09-12 17:21:16 +03002554 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002555 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002556 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002557 {
2558 context->handleError(InvalidOperation() << "The number of views in the active program "
2559 "and draw framebuffer does not match.");
2560 return false;
2561 }
Martin Radev7e69f762017-07-27 14:54:13 +03002562
2563 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2564 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2565 framebufferNumViews > 1)
2566 {
2567 context->handleError(InvalidOperation()
2568 << "There is an active transform feedback object "
2569 "when the number of views in the active draw "
2570 "framebuffer is greater than 1.");
2571 return false;
2572 }
Martin Radevffe754b2017-07-31 10:38:07 +03002573
2574 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2575 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2576 {
2577 context->handleError(InvalidOperation() << "There is an active query for target "
2578 "GL_TIME_ELAPSED_EXT when the number of "
2579 "views in the active draw framebuffer is "
2580 "greater than 1.");
2581 return false;
2582 }
Martin Radev7cf61662017-07-26 17:10:53 +03002583 }
2584
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002585 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002586 for (unsigned int uniformBlockIndex = 0;
2587 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002588 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002589 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002590 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002591 const OffsetBindingPointer<Buffer> &uniformBuffer =
2592 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002593
Geoff Lang5d124a62015-09-15 13:03:27 -04002594 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002595 {
2596 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002597 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002598 InvalidOperation()
2599 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002600 return false;
2601 }
2602
Geoff Lang5d124a62015-09-15 13:03:27 -04002603 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002604 if (uniformBufferSize == 0)
2605 {
2606 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002607 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002608 }
2609
Jamie Madill62d31cb2015-09-11 13:25:51 -04002610 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002611 {
2612 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002613 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002614 InvalidOperation()
2615 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002616 return false;
2617 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002618
2619 if (extensions.webglCompatibility &&
2620 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2621 {
2622 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2623 UniformBufferBoundForTransformFeedback);
2624 return false;
2625 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002626 }
2627
Geoff Lange0cff192017-05-30 13:04:56 -04002628 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002629 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002630 {
James Darpiniane8a93c62018-01-04 18:02:24 -08002631 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2632 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2633 transformFeedbackObject->buffersBoundForOtherUse())
2634 {
2635 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferDoubleBound);
2636 return false;
2637 }
Geoff Lange0cff192017-05-30 13:04:56 -04002638 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002639 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2640 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002641 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002642 return false;
2643 }
Geoff Lange0cff192017-05-30 13:04:56 -04002644
Geoff Lang9ab5b822017-05-30 16:19:23 -04002645 // Detect that the vertex shader input types match the attribute types
2646 if (!ValidateVertexShaderAttributeTypeMatch(context))
2647 {
2648 return false;
2649 }
2650
Geoff Lange0cff192017-05-30 13:04:56 -04002651 // Detect that the color buffer types match the fragment shader output types
2652 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2653 {
2654 return false;
2655 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002656 }
2657
Jamie Madill9fdaa492018-02-16 10:52:11 -05002658 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002659}
2660
Jamie Madillc1d770e2017-04-13 17:31:24 -04002661bool ValidateDrawArraysCommon(ValidationContext *context,
2662 GLenum mode,
2663 GLint first,
2664 GLsizei count,
2665 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002666{
Jamie Madillfd716582014-06-06 17:09:04 -04002667 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002668 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002669 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002670 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002671 }
2672
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002673 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002674 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002675 if (curTransformFeedback && curTransformFeedback->isActive() &&
2676 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002677 {
2678 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002679 // that does not match the current transform feedback object's draw mode (if transform
2680 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002681 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002682 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002683 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002684 }
2685
Jiajia Qind9671222016-11-29 16:30:31 +08002686 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002687 {
2688 return false;
2689 }
2690
Corentin Wallez71168a02016-12-19 15:11:18 -08002691 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002692 // - first < 0 has been checked as an error condition.
2693 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002694 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002695 ASSERT(first >= 0);
2696 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002697 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002698 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2699 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2700 {
2701 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2702 return false;
2703 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002704
Jamie Madill9fdaa492018-02-16 10:52:11 -05002705 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2706 {
2707 return false;
2708 }
Jamie Madillfd716582014-06-06 17:09:04 -04002709 }
2710
2711 return true;
2712}
2713
He Yunchaoced53ae2016-11-29 15:00:51 +08002714bool ValidateDrawArraysInstancedANGLE(Context *context,
2715 GLenum mode,
2716 GLint first,
2717 GLsizei count,
2718 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002719{
Geoff Lang63c5a592017-09-27 14:08:16 -04002720 if (!context->getExtensions().instancedArrays)
2721 {
2722 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2723 return false;
2724 }
2725
Corentin Wallez170efbf2017-05-02 13:45:01 -04002726 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002727 {
2728 return false;
2729 }
2730
Corentin Wallez0dc97812017-06-22 14:38:44 -04002731 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002732}
2733
Jiajia Qind9671222016-11-29 16:30:31 +08002734bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002735{
Jamie Madill250d33f2014-06-06 17:09:03 -04002736 switch (type)
2737 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002738 case GL_UNSIGNED_BYTE:
2739 case GL_UNSIGNED_SHORT:
2740 break;
2741 case GL_UNSIGNED_INT:
2742 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2743 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002744 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002745 return false;
2746 }
2747 break;
2748 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002749 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002750 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002751 }
2752
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002753 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002754
2755 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002756 if (curTransformFeedback && curTransformFeedback->isActive() &&
2757 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002758 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002759 // It is an invalid operation to call DrawElements, DrawRangeElements or
2760 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002761 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002762 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002763 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002764 }
2765
Jiajia Qind9671222016-11-29 16:30:31 +08002766 return true;
2767}
2768
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002769bool ValidateDrawElementsCommon(ValidationContext *context,
2770 GLenum mode,
2771 GLsizei count,
2772 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002773 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002774 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002775{
2776 if (!ValidateDrawElementsBase(context, type))
2777 return false;
2778
2779 const State &state = context->getGLState();
2780
Corentin Wallez170efbf2017-05-02 13:45:01 -04002781 if (!ValidateDrawBase(context, mode, count))
2782 {
2783 return false;
2784 }
2785
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002786 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2787 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2788 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2789 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002790 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002791 // Check for mapped buffers
2792 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002793 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002794 {
2795 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2796 return false;
2797 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002798 }
2799
He Yunchaoced53ae2016-11-29 15:00:51 +08002800 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002801 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002802
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002803 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2804
2805 if (context->getExtensions().webglCompatibility)
2806 {
2807 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2808 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2809 {
2810 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2811 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2812 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002813 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002814 return false;
2815 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002816
2817 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2818 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2819 // error is generated.
2820 if (reinterpret_cast<intptr_t>(indices) < 0)
2821 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002822 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002823 return false;
2824 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002825 }
2826
2827 if (context->getExtensions().webglCompatibility ||
2828 !context->getGLState().areClientArraysEnabled())
2829 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002830 if (!elementArrayBuffer && count > 0)
2831 {
2832 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2833 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2834 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002835 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002836 return false;
2837 }
2838 }
2839
Jamie Madill9fdaa492018-02-16 10:52:11 -05002840 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04002841 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002842 // This is an application error that would normally result in a crash, but we catch it and
2843 // return an error
2844 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
2845 return false;
2846 }
2847
2848 if (count > 0 && elementArrayBuffer)
2849 {
2850 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2851 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2852 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2853 constexpr uint64_t kMaxTypeSize = 8;
2854 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2855 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2856 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
2857
2858 uint64_t typeSize = typeBytes;
2859 uint64_t elementCount = static_cast<uint64_t>(count);
2860 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2861
2862 // Doing the multiplication here is overflow-safe
2863 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2864
2865 // The offset can be any value, check for overflows
2866 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2867 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04002868 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002869 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2870 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002871 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05002872
2873 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2874 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002875 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002876 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
2877 return false;
2878 }
2879
2880 ASSERT(isPow2(typeSize) && typeSize > 0);
2881 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
2882 {
2883 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04002884 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002885 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002886
2887 if (context->getExtensions().webglCompatibility &&
2888 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
2889 {
2890 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2891 ElementArrayBufferBoundForTransformFeedback);
2892 return false;
2893 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002894 }
2895
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002896 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002897 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002898 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2899 // access is enabled.
2900 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2901 {
2902 return false;
2903 }
2904 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05002905 else if (count == 0)
2906 {
2907 // ValidateDrawAttribs also does some extra validation that is independent of the vertex
2908 // count.
2909 if (!ValidateDrawAttribs(context, 0, 0, 0))
2910 {
2911 return false;
2912 }
2913 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002914 else
2915 {
2916 // Use the parameter buffer to retrieve and cache the index range.
2917 const auto &params = context->getParams<HasIndexRange>();
2918 const auto &indexRangeOpt = params.getIndexRange();
2919 if (!indexRangeOpt.valid())
2920 {
2921 // Unexpected error.
2922 return false;
2923 }
2924
2925 // If we use an index greater than our maximum supported index range, return an error.
2926 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2927 // return an error if possible here.
2928 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2929 {
2930 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2931 return false;
2932 }
2933
2934 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2935 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2936 {
2937 return false;
2938 }
2939
2940 // No op if there are no real indices in the index data (all are primitive restart).
2941 return (indexRangeOpt.value().vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002942 }
2943
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002944 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002945}
2946
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002947bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2948 GLenum mode,
2949 GLsizei count,
2950 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002951 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002952 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002953{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002954 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002955}
2956
Geoff Lang3edfe032015-09-04 16:38:24 -04002957bool ValidateDrawElementsInstancedANGLE(Context *context,
2958 GLenum mode,
2959 GLsizei count,
2960 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002961 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002962 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002963{
Geoff Lang63c5a592017-09-27 14:08:16 -04002964 if (!context->getExtensions().instancedArrays)
2965 {
2966 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2967 return false;
2968 }
2969
Corentin Wallez170efbf2017-05-02 13:45:01 -04002970 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002971 {
2972 return false;
2973 }
2974
Corentin Wallez0dc97812017-06-22 14:38:44 -04002975 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002976}
2977
He Yunchaoced53ae2016-11-29 15:00:51 +08002978bool ValidateFramebufferTextureBase(Context *context,
2979 GLenum target,
2980 GLenum attachment,
2981 GLuint texture,
2982 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002983{
Geoff Lange8afa902017-09-27 15:00:43 -04002984 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002985 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002986 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002987 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002988 }
2989
2990 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002991 {
2992 return false;
2993 }
2994
Jamie Madill55ec3b12014-07-03 10:38:57 -04002995 if (texture != 0)
2996 {
2997 gl::Texture *tex = context->getTexture(texture);
2998
Luc Ferronadcf0ae2018-01-24 08:27:37 -05002999 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003000 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003001 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003002 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003003 }
3004
3005 if (level < 0)
3006 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003007 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003008 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003009 }
3010 }
3011
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003012 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003013 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003014
Jamie Madill84115c92015-04-23 15:00:07 -04003015 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003016 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003017 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003018 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003019 }
3020
3021 return true;
3022}
3023
Geoff Langb1196682014-07-23 13:47:29 -04003024bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003025{
3026 if (program == 0)
3027 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003028 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003029 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003030 }
3031
Dian Xiang769769a2015-09-09 15:20:08 -07003032 gl::Program *programObject = GetValidProgram(context, program);
3033 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003034 {
3035 return false;
3036 }
3037
Jamie Madill0063c512014-08-25 15:47:53 -04003038 if (!programObject || !programObject->isLinked())
3039 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003040 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003041 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003042 }
3043
Geoff Lang7dd2e102014-11-10 15:19:26 -05003044 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003045 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003046 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003047 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003048 }
3049
Jamie Madill0063c512014-08-25 15:47:53 -04003050 return true;
3051}
3052
Geoff Langf41d0ee2016-10-07 13:04:23 -04003053static bool ValidateSizedGetUniform(Context *context,
3054 GLuint program,
3055 GLint location,
3056 GLsizei bufSize,
3057 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003058{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003059 if (length)
3060 {
3061 *length = 0;
3062 }
3063
Jamie Madill78f41802014-08-25 15:47:55 -04003064 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003065 {
Jamie Madill78f41802014-08-25 15:47:55 -04003066 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003067 }
3068
Geoff Langf41d0ee2016-10-07 13:04:23 -04003069 if (bufSize < 0)
3070 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003071 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003072 return false;
3073 }
3074
Jamie Madilla502c742014-08-28 17:19:13 -04003075 gl::Program *programObject = context->getProgram(program);
3076 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003077
Jamie Madill78f41802014-08-25 15:47:55 -04003078 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003079 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003080 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003081 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003082 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003083 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003084 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003085 }
3086
Geoff Langf41d0ee2016-10-07 13:04:23 -04003087 if (length)
3088 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003089 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003090 }
3091
Jamie Madill0063c512014-08-25 15:47:53 -04003092 return true;
3093}
3094
He Yunchaoced53ae2016-11-29 15:00:51 +08003095bool ValidateGetnUniformfvEXT(Context *context,
3096 GLuint program,
3097 GLint location,
3098 GLsizei bufSize,
3099 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003100{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003101 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003102}
3103
He Yunchaoced53ae2016-11-29 15:00:51 +08003104bool ValidateGetnUniformivEXT(Context *context,
3105 GLuint program,
3106 GLint location,
3107 GLsizei bufSize,
3108 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003109{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003110 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3111}
3112
3113bool ValidateGetUniformfvRobustANGLE(Context *context,
3114 GLuint program,
3115 GLint location,
3116 GLsizei bufSize,
3117 GLsizei *length,
3118 GLfloat *params)
3119{
3120 if (!ValidateRobustEntryPoint(context, bufSize))
3121 {
3122 return false;
3123 }
3124
3125 // bufSize is validated in ValidateSizedGetUniform
3126 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3127}
3128
3129bool ValidateGetUniformivRobustANGLE(Context *context,
3130 GLuint program,
3131 GLint location,
3132 GLsizei bufSize,
3133 GLsizei *length,
3134 GLint *params)
3135{
3136 if (!ValidateRobustEntryPoint(context, bufSize))
3137 {
3138 return false;
3139 }
3140
3141 // bufSize is validated in ValidateSizedGetUniform
3142 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3143}
3144
3145bool ValidateGetUniformuivRobustANGLE(Context *context,
3146 GLuint program,
3147 GLint location,
3148 GLsizei bufSize,
3149 GLsizei *length,
3150 GLuint *params)
3151{
3152 if (!ValidateRobustEntryPoint(context, bufSize))
3153 {
3154 return false;
3155 }
3156
3157 if (context->getClientMajorVersion() < 3)
3158 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003159 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003160 return false;
3161 }
3162
3163 // bufSize is validated in ValidateSizedGetUniform
3164 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003165}
3166
He Yunchaoced53ae2016-11-29 15:00:51 +08003167bool ValidateDiscardFramebufferBase(Context *context,
3168 GLenum target,
3169 GLsizei numAttachments,
3170 const GLenum *attachments,
3171 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003172{
3173 if (numAttachments < 0)
3174 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003175 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003176 return false;
3177 }
3178
3179 for (GLsizei i = 0; i < numAttachments; ++i)
3180 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003181 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003182 {
3183 if (defaultFramebuffer)
3184 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003185 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003186 return false;
3187 }
3188
3189 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3190 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003191 context->handleError(InvalidOperation() << "Requested color attachment is "
3192 "greater than the maximum supported "
3193 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003194 return false;
3195 }
3196 }
3197 else
3198 {
3199 switch (attachments[i])
3200 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003201 case GL_DEPTH_ATTACHMENT:
3202 case GL_STENCIL_ATTACHMENT:
3203 case GL_DEPTH_STENCIL_ATTACHMENT:
3204 if (defaultFramebuffer)
3205 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003206 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3207 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003208 return false;
3209 }
3210 break;
3211 case GL_COLOR:
3212 case GL_DEPTH:
3213 case GL_STENCIL:
3214 if (!defaultFramebuffer)
3215 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003216 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3217 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003218 return false;
3219 }
3220 break;
3221 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003222 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003223 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003224 }
3225 }
3226 }
3227
3228 return true;
3229}
3230
Austin Kinross6ee1e782015-05-29 17:05:37 -07003231bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3232{
Jamie Madill007530e2017-12-28 14:27:04 -05003233 if (!context->getExtensions().debugMarker)
3234 {
3235 // The debug marker calls should not set error state
3236 // However, it seems reasonable to set an error state if the extension is not enabled
3237 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3238 return false;
3239 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003240
Jamie Madill007530e2017-12-28 14:27:04 -05003241 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003242 if (length < 0)
3243 {
3244 return false;
3245 }
3246
3247 if (marker == nullptr)
3248 {
3249 return false;
3250 }
3251
3252 return true;
3253}
3254
3255bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3256{
Jamie Madill007530e2017-12-28 14:27:04 -05003257 if (!context->getExtensions().debugMarker)
3258 {
3259 // The debug marker calls should not set error state
3260 // However, it seems reasonable to set an error state if the extension is not enabled
3261 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3262 return false;
3263 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003264
Jamie Madill007530e2017-12-28 14:27:04 -05003265 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003266 if (length < 0)
3267 {
3268 return false;
3269 }
3270
3271 if (length > 0 && marker == nullptr)
3272 {
3273 return false;
3274 }
3275
3276 return true;
3277}
3278
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003279bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003280{
Geoff Langa8406172015-07-21 16:53:39 -04003281 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3282 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003283 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003284 return false;
3285 }
3286
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003287 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003288 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003289 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003290 if (!context->getExtensions().eglImage)
3291 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003292 context->handleError(InvalidEnum()
3293 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003294 }
3295 break;
3296
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003297 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003298 if (!context->getExtensions().eglImageExternal)
3299 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003300 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3301 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003302 }
Geoff Langa8406172015-07-21 16:53:39 -04003303 break;
3304
3305 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003306 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003307 return false;
3308 }
3309
Jamie Madill007530e2017-12-28 14:27:04 -05003310 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3311
Jamie Madill61e16b42017-06-19 11:13:23 -04003312 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003313 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003314 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003315 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003316 return false;
3317 }
3318
Jamie Madill007530e2017-12-28 14:27:04 -05003319 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003320 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003321 context->handleError(InvalidOperation()
3322 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003323 return false;
3324 }
3325
Geoff Langca271392017-04-05 12:30:00 -04003326 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003327 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003328 if (!textureCaps.texturable)
3329 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003330 context->handleError(InvalidOperation()
3331 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003332 return false;
3333 }
3334
Geoff Langdcab33b2015-07-21 13:03:16 -04003335 return true;
3336}
3337
3338bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003339 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003340 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003341{
Geoff Langa8406172015-07-21 16:53:39 -04003342 if (!context->getExtensions().eglImage)
3343 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003344 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003345 return false;
3346 }
3347
3348 switch (target)
3349 {
3350 case GL_RENDERBUFFER:
3351 break;
3352
3353 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003354 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003355 return false;
3356 }
3357
Jamie Madill007530e2017-12-28 14:27:04 -05003358 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3359
Jamie Madill61e16b42017-06-19 11:13:23 -04003360 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003361 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003362 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003363 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003364 return false;
3365 }
3366
Geoff Langca271392017-04-05 12:30:00 -04003367 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003368 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003369 if (!textureCaps.renderable)
3370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003371 context->handleError(InvalidOperation()
3372 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003373 return false;
3374 }
3375
Geoff Langdcab33b2015-07-21 13:03:16 -04003376 return true;
3377}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003378
3379bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3380{
Geoff Lang36167ab2015-12-07 10:27:14 -05003381 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003382 {
3383 // The default VAO should always exist
3384 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003385 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003386 return false;
3387 }
3388
3389 return true;
3390}
3391
Geoff Langc5629752015-12-07 16:29:04 -05003392bool ValidateProgramBinaryBase(Context *context,
3393 GLuint program,
3394 GLenum binaryFormat,
3395 const void *binary,
3396 GLint length)
3397{
3398 Program *programObject = GetValidProgram(context, program);
3399 if (programObject == nullptr)
3400 {
3401 return false;
3402 }
3403
3404 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3405 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3406 programBinaryFormats.end())
3407 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003408 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003409 return false;
3410 }
3411
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003412 if (context->hasActiveTransformFeedback(program))
3413 {
3414 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003415 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3416 "is associated with an active transform "
3417 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003418 return false;
3419 }
3420
Geoff Langc5629752015-12-07 16:29:04 -05003421 return true;
3422}
3423
3424bool ValidateGetProgramBinaryBase(Context *context,
3425 GLuint program,
3426 GLsizei bufSize,
3427 GLsizei *length,
3428 GLenum *binaryFormat,
3429 void *binary)
3430{
3431 Program *programObject = GetValidProgram(context, program);
3432 if (programObject == nullptr)
3433 {
3434 return false;
3435 }
3436
3437 if (!programObject->isLinked())
3438 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003439 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003440 return false;
3441 }
3442
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003443 if (context->getCaps().programBinaryFormats.empty())
3444 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003445 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003446 return false;
3447 }
3448
Geoff Langc5629752015-12-07 16:29:04 -05003449 return true;
3450}
Jamie Madillc29968b2016-01-20 11:17:23 -05003451
Jamie Madillc29968b2016-01-20 11:17:23 -05003452bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3453{
3454 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003455 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003456 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003457 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3458 return false;
3459 }
3460 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3461 {
3462 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003463 return false;
3464 }
3465
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003466 ASSERT(context->getGLState().getDrawFramebuffer());
3467 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003468 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3469
3470 // This should come first before the check for the default frame buffer
3471 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3472 // rather than INVALID_OPERATION
3473 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3474 {
3475 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3476
3477 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003478 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3479 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003480 {
3481 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003482 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3483 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3484 // 3.1 is still a bit ambiguous about the error, but future specs are
3485 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003486 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003487 return false;
3488 }
3489 else if (bufs[colorAttachment] >= maxColorAttachment)
3490 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003491 context->handleError(InvalidOperation()
3492 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003493 return false;
3494 }
3495 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3496 frameBufferId != 0)
3497 {
3498 // INVALID_OPERATION-GL is bound to buffer and ith argument
3499 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003500 context->handleError(InvalidOperation()
3501 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003502 return false;
3503 }
3504 }
3505
3506 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3507 // and n is not 1 or bufs is bound to value other than BACK and NONE
3508 if (frameBufferId == 0)
3509 {
3510 if (n != 1)
3511 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003512 context->handleError(InvalidOperation()
3513 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003514 return false;
3515 }
3516
3517 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3518 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003519 context->handleError(
3520 InvalidOperation()
3521 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003522 return false;
3523 }
3524 }
3525
3526 return true;
3527}
3528
Geoff Lang496c02d2016-10-20 11:38:11 -07003529bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003530 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003531 GLenum pname,
3532 GLsizei *length,
3533 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003534{
Geoff Lang496c02d2016-10-20 11:38:11 -07003535 if (length)
3536 {
3537 *length = 0;
3538 }
3539
3540 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3541 {
3542 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003543 InvalidOperation()
3544 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003545 return false;
3546 }
3547
Corentin Walleze4477002017-12-01 14:39:58 -05003548 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003549 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003550 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003551 return false;
3552 }
3553
Geoff Lang496c02d2016-10-20 11:38:11 -07003554 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003555 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003556 case GL_BUFFER_MAP_POINTER:
3557 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003558
Geoff Lang496c02d2016-10-20 11:38:11 -07003559 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003560 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003561 return false;
3562 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003563
3564 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3565 // target bound to zero generate an INVALID_OPERATION error."
3566 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003567 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003568 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003569 context->handleError(InvalidOperation()
3570 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003571 return false;
3572 }
3573
Geoff Lang496c02d2016-10-20 11:38:11 -07003574 if (length)
3575 {
3576 *length = 1;
3577 }
3578
Olli Etuaho4f667482016-03-30 15:56:35 +03003579 return true;
3580}
3581
Corentin Wallez336129f2017-10-17 15:55:40 -04003582bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003583{
Corentin Walleze4477002017-12-01 14:39:58 -05003584 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003585 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003586 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003587 return false;
3588 }
3589
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003590 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003591
3592 if (buffer == nullptr || !buffer->isMapped())
3593 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003594 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003595 return false;
3596 }
3597
3598 return true;
3599}
3600
3601bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003602 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003603 GLintptr offset,
3604 GLsizeiptr length,
3605 GLbitfield access)
3606{
Corentin Walleze4477002017-12-01 14:39:58 -05003607 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003608 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003609 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003610 return false;
3611 }
3612
Brandon Jones6cad5662017-06-14 13:25:13 -07003613 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003614 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003615 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3616 return false;
3617 }
3618
3619 if (length < 0)
3620 {
3621 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003622 return false;
3623 }
3624
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003625 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003626
3627 if (!buffer)
3628 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003629 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003630 return false;
3631 }
3632
3633 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003634 CheckedNumeric<size_t> checkedOffset(offset);
3635 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003636
Jamie Madille2e406c2016-06-02 13:04:10 -04003637 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003638 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003639 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003640 return false;
3641 }
3642
3643 // Check for invalid bits in the mask
3644 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3645 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3646 GL_MAP_UNSYNCHRONIZED_BIT;
3647
3648 if (access & ~(allAccessBits))
3649 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003650 context->handleError(InvalidValue()
3651 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003652 return false;
3653 }
3654
3655 if (length == 0)
3656 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003657 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003658 return false;
3659 }
3660
3661 if (buffer->isMapped())
3662 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003663 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003664 return false;
3665 }
3666
3667 // Check for invalid bit combinations
3668 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3669 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003670 context->handleError(InvalidOperation()
3671 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003672 return false;
3673 }
3674
3675 GLbitfield writeOnlyBits =
3676 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3677
3678 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3679 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003680 context->handleError(InvalidOperation()
3681 << "Invalid access bits when mapping buffer for reading: 0x"
3682 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003683 return false;
3684 }
3685
3686 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3687 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003688 context->handleError(
3689 InvalidOperation()
3690 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003691 return false;
3692 }
Geoff Lang79f71042017-08-14 16:43:43 -04003693
3694 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003695}
3696
3697bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003698 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003699 GLintptr offset,
3700 GLsizeiptr length)
3701{
Brandon Jones6cad5662017-06-14 13:25:13 -07003702 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003703 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003704 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3705 return false;
3706 }
3707
3708 if (length < 0)
3709 {
3710 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003711 return false;
3712 }
3713
Corentin Walleze4477002017-12-01 14:39:58 -05003714 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003715 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003716 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003717 return false;
3718 }
3719
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003720 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003721
3722 if (buffer == nullptr)
3723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003724 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003725 return false;
3726 }
3727
3728 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3729 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003730 context->handleError(InvalidOperation()
3731 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003732 return false;
3733 }
3734
3735 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003736 CheckedNumeric<size_t> checkedOffset(offset);
3737 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003738
Jamie Madille2e406c2016-06-02 13:04:10 -04003739 if (!checkedSize.IsValid() ||
3740 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003741 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003742 context->handleError(InvalidValue()
3743 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003744 return false;
3745 }
3746
3747 return true;
3748}
3749
Olli Etuaho41997e72016-03-10 13:38:39 +02003750bool ValidateGenOrDelete(Context *context, GLint n)
3751{
3752 if (n < 0)
3753 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003754 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003755 return false;
3756 }
3757 return true;
3758}
3759
Geoff Langff5b2d52016-09-07 11:32:23 -04003760bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3761{
3762 if (!context->getExtensions().robustClientMemory)
3763 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003764 context->handleError(InvalidOperation()
3765 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003766 return false;
3767 }
3768
3769 if (bufSize < 0)
3770 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003771 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003772 return false;
3773 }
3774
3775 return true;
3776}
3777
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003778bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3779{
3780 if (bufSize < numParams)
3781 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003782 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3783 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003784 return false;
3785 }
3786
3787 return true;
3788}
3789
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003790bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04003791 GLenum target,
3792 GLenum attachment,
3793 GLenum pname,
3794 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003795{
Geoff Lange8afa902017-09-27 15:00:43 -04003796 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003797 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003798 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003799 return false;
3800 }
3801
3802 int clientVersion = context->getClientMajorVersion();
3803
3804 switch (pname)
3805 {
3806 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3807 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3808 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3809 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3810 break;
3811
Martin Radeve5285d22017-07-14 16:23:53 +03003812 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3813 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3814 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3815 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3816 if (clientVersion < 3 || !context->getExtensions().multiview)
3817 {
3818 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3819 return false;
3820 }
3821 break;
3822
Geoff Langff5b2d52016-09-07 11:32:23 -04003823 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3824 if (clientVersion < 3 && !context->getExtensions().sRGB)
3825 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003826 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003827 return false;
3828 }
3829 break;
3830
3831 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3832 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3833 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3834 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3835 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3836 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3837 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3838 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3839 if (clientVersion < 3)
3840 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003841 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003842 return false;
3843 }
3844 break;
3845
3846 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003847 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003848 return false;
3849 }
3850
3851 // Determine if the attachment is a valid enum
3852 switch (attachment)
3853 {
3854 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04003855 case GL_DEPTH:
3856 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04003857 if (clientVersion < 3)
3858 {
Geoff Langfa125c92017-10-24 13:01:46 -04003859 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003860 return false;
3861 }
3862 break;
3863
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003864 case GL_DEPTH_STENCIL_ATTACHMENT:
3865 if (clientVersion < 3 && !context->isWebGL1())
3866 {
3867 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3868 return false;
3869 }
3870 break;
3871
Geoff Langfa125c92017-10-24 13:01:46 -04003872 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003873 case GL_DEPTH_ATTACHMENT:
3874 case GL_STENCIL_ATTACHMENT:
3875 break;
3876
3877 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003878 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3879 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003880 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3881 {
Geoff Langfa125c92017-10-24 13:01:46 -04003882 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003883 return false;
3884 }
3885 break;
3886 }
3887
3888 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3889 ASSERT(framebuffer);
3890
3891 if (framebuffer->id() == 0)
3892 {
3893 if (clientVersion < 3)
3894 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003895 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003896 return false;
3897 }
3898
3899 switch (attachment)
3900 {
3901 case GL_BACK:
3902 case GL_DEPTH:
3903 case GL_STENCIL:
3904 break;
3905
3906 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003907 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003908 return false;
3909 }
3910 }
3911 else
3912 {
3913 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3914 {
3915 // Valid attachment query
3916 }
3917 else
3918 {
3919 switch (attachment)
3920 {
3921 case GL_DEPTH_ATTACHMENT:
3922 case GL_STENCIL_ATTACHMENT:
3923 break;
3924
3925 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003926 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04003927 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003928 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003929 return false;
3930 }
3931 break;
3932
3933 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003934 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003935 return false;
3936 }
3937 }
3938 }
3939
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003940 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003941 if (attachmentObject)
3942 {
3943 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3944 attachmentObject->type() == GL_TEXTURE ||
3945 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3946
3947 switch (pname)
3948 {
3949 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3950 if (attachmentObject->type() != GL_RENDERBUFFER &&
3951 attachmentObject->type() != GL_TEXTURE)
3952 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003953 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003954 return false;
3955 }
3956 break;
3957
3958 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3959 if (attachmentObject->type() != GL_TEXTURE)
3960 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003961 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003962 return false;
3963 }
3964 break;
3965
3966 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3967 if (attachmentObject->type() != GL_TEXTURE)
3968 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003969 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003970 return false;
3971 }
3972 break;
3973
3974 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3975 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3976 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003977 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003978 return false;
3979 }
3980 break;
3981
3982 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3983 if (attachmentObject->type() != GL_TEXTURE)
3984 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003985 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003986 return false;
3987 }
3988 break;
3989
3990 default:
3991 break;
3992 }
3993 }
3994 else
3995 {
3996 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3997 // is NONE, then querying any other pname will generate INVALID_ENUM.
3998
3999 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4000 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4001 // INVALID_OPERATION for all other pnames
4002
4003 switch (pname)
4004 {
4005 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4006 break;
4007
4008 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4009 if (clientVersion < 3)
4010 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004011 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004012 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004013 return false;
4014 }
4015 break;
4016
4017 default:
4018 if (clientVersion < 3)
4019 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004020 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004021 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004022 return false;
4023 }
4024 else
4025 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004026 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004027 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004028 return false;
4029 }
4030 }
4031 }
4032
Martin Radeve5285d22017-07-14 16:23:53 +03004033 if (numParams)
4034 {
4035 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4036 {
4037 // Only when the viewport offsets are queried we can have a varying number of output
4038 // parameters.
4039 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4040 *numParams = numViews * 2;
4041 }
4042 else
4043 {
4044 // For all other queries we can have only one output parameter.
4045 *numParams = 1;
4046 }
4047 }
4048
Geoff Langff5b2d52016-09-07 11:32:23 -04004049 return true;
4050}
4051
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004052bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004053 GLenum target,
4054 GLenum attachment,
4055 GLenum pname,
4056 GLsizei bufSize,
4057 GLsizei *numParams)
4058{
4059 if (!ValidateRobustEntryPoint(context, bufSize))
4060 {
4061 return false;
4062 }
4063
Jamie Madillbe849e42017-05-02 15:49:00 -04004064 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4065 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004066 {
4067 return false;
4068 }
4069
4070 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4071 {
4072 return false;
4073 }
4074
4075 return true;
4076}
4077
Geoff Langff5b2d52016-09-07 11:32:23 -04004078bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004079 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004080 GLenum pname,
4081 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004082 GLsizei *length,
4083 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004084{
4085 if (!ValidateRobustEntryPoint(context, bufSize))
4086 {
4087 return false;
4088 }
4089
Geoff Langebebe1c2016-10-14 12:01:31 -04004090 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004091 {
4092 return false;
4093 }
4094
Geoff Langebebe1c2016-10-14 12:01:31 -04004095 if (!ValidateRobustBufferSize(context, bufSize, *length))
4096 {
4097 return false;
4098 }
4099
4100 return true;
4101}
4102
Geoff Langebebe1c2016-10-14 12:01:31 -04004103bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004104 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004105 GLenum pname,
4106 GLsizei bufSize,
4107 GLsizei *length,
4108 GLint64 *params)
4109{
4110 if (!ValidateRobustEntryPoint(context, bufSize))
4111 {
4112 return false;
4113 }
4114
4115 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4116 {
4117 return false;
4118 }
4119
4120 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004121 {
4122 return false;
4123 }
4124
4125 return true;
4126}
4127
Jamie Madillbe849e42017-05-02 15:49:00 -04004128bool ValidateGetProgramivBase(ValidationContext *context,
4129 GLuint program,
4130 GLenum pname,
4131 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004132{
4133 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004134 if (numParams)
4135 {
4136 *numParams = 1;
4137 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004138
4139 Program *programObject = GetValidProgram(context, program);
4140 if (!programObject)
4141 {
4142 return false;
4143 }
4144
4145 switch (pname)
4146 {
4147 case GL_DELETE_STATUS:
4148 case GL_LINK_STATUS:
4149 case GL_VALIDATE_STATUS:
4150 case GL_INFO_LOG_LENGTH:
4151 case GL_ATTACHED_SHADERS:
4152 case GL_ACTIVE_ATTRIBUTES:
4153 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4154 case GL_ACTIVE_UNIFORMS:
4155 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4156 break;
4157
4158 case GL_PROGRAM_BINARY_LENGTH:
4159 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4160 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004161 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4162 "requires GL_OES_get_program_binary or "
4163 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004164 return false;
4165 }
4166 break;
4167
4168 case GL_ACTIVE_UNIFORM_BLOCKS:
4169 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4170 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4171 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4172 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4173 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4174 if (context->getClientMajorVersion() < 3)
4175 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004176 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004177 return false;
4178 }
4179 break;
4180
Yunchao He61afff12017-03-14 15:34:03 +08004181 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004182 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004183 if (context->getClientVersion() < Version(3, 1))
4184 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004185 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004186 return false;
4187 }
4188 break;
4189
Jiawei Shao6ae51612018-02-23 14:03:25 +08004190 case GL_COMPUTE_WORK_GROUP_SIZE:
4191 if (context->getClientVersion() < Version(3, 1))
4192 {
4193 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4194 return false;
4195 }
4196
4197 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4198 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4199 // program which has not been linked successfully, or which does not contain objects to
4200 // form a compute shader.
4201 if (!programObject->isLinked())
4202 {
4203 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4204 return false;
4205 }
4206 if (!programObject->hasLinkedComputeShader())
4207 {
4208 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4209 return false;
4210 }
4211 break;
4212
Geoff Langff5b2d52016-09-07 11:32:23 -04004213 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004214 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004215 return false;
4216 }
4217
4218 return true;
4219}
4220
4221bool ValidateGetProgramivRobustANGLE(Context *context,
4222 GLuint program,
4223 GLenum pname,
4224 GLsizei bufSize,
4225 GLsizei *numParams)
4226{
4227 if (!ValidateRobustEntryPoint(context, bufSize))
4228 {
4229 return false;
4230 }
4231
Jamie Madillbe849e42017-05-02 15:49:00 -04004232 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004233 {
4234 return false;
4235 }
4236
4237 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4238 {
4239 return false;
4240 }
4241
4242 return true;
4243}
4244
Geoff Lang740d9022016-10-07 11:20:52 -04004245bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4246 GLenum target,
4247 GLenum pname,
4248 GLsizei bufSize,
4249 GLsizei *length,
4250 GLint *params)
4251{
4252 if (!ValidateRobustEntryPoint(context, bufSize))
4253 {
4254 return false;
4255 }
4256
4257 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4258 {
4259 return false;
4260 }
4261
4262 if (!ValidateRobustBufferSize(context, bufSize, *length))
4263 {
4264 return false;
4265 }
4266
4267 return true;
4268}
4269
Geoff Langd7d0ed32016-10-07 11:33:51 -04004270bool ValidateGetShaderivRobustANGLE(Context *context,
4271 GLuint shader,
4272 GLenum pname,
4273 GLsizei bufSize,
4274 GLsizei *length,
4275 GLint *params)
4276{
4277 if (!ValidateRobustEntryPoint(context, bufSize))
4278 {
4279 return false;
4280 }
4281
4282 if (!ValidateGetShaderivBase(context, shader, pname, length))
4283 {
4284 return false;
4285 }
4286
4287 if (!ValidateRobustBufferSize(context, bufSize, *length))
4288 {
4289 return false;
4290 }
4291
4292 return true;
4293}
4294
Geoff Langc1984ed2016-10-07 12:41:00 -04004295bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004296 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004297 GLenum pname,
4298 GLsizei bufSize,
4299 GLsizei *length,
4300 GLfloat *params)
4301{
4302 if (!ValidateRobustEntryPoint(context, bufSize))
4303 {
4304 return false;
4305 }
4306
4307 if (!ValidateGetTexParameterBase(context, target, pname, length))
4308 {
4309 return false;
4310 }
4311
4312 if (!ValidateRobustBufferSize(context, bufSize, *length))
4313 {
4314 return false;
4315 }
4316
4317 return true;
4318}
4319
Geoff Langc1984ed2016-10-07 12:41:00 -04004320bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004321 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004322 GLenum pname,
4323 GLsizei bufSize,
4324 GLsizei *length,
4325 GLint *params)
4326{
4327 if (!ValidateRobustEntryPoint(context, bufSize))
4328 {
4329 return false;
4330 }
4331
4332 if (!ValidateGetTexParameterBase(context, target, pname, length))
4333 {
4334 return false;
4335 }
4336
4337 if (!ValidateRobustBufferSize(context, bufSize, *length))
4338 {
4339 return false;
4340 }
4341
4342 return true;
4343}
4344
Geoff Langc1984ed2016-10-07 12:41:00 -04004345bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004346 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004347 GLenum pname,
4348 GLsizei bufSize,
4349 const GLfloat *params)
4350{
4351 if (!ValidateRobustEntryPoint(context, bufSize))
4352 {
4353 return false;
4354 }
4355
4356 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4357}
4358
Geoff Langc1984ed2016-10-07 12:41:00 -04004359bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004360 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004361 GLenum pname,
4362 GLsizei bufSize,
4363 const GLint *params)
4364{
4365 if (!ValidateRobustEntryPoint(context, bufSize))
4366 {
4367 return false;
4368 }
4369
4370 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4371}
4372
Geoff Langc1984ed2016-10-07 12:41:00 -04004373bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4374 GLuint sampler,
4375 GLenum pname,
4376 GLuint bufSize,
4377 GLsizei *length,
4378 GLfloat *params)
4379{
4380 if (!ValidateRobustEntryPoint(context, bufSize))
4381 {
4382 return false;
4383 }
4384
4385 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4386 {
4387 return false;
4388 }
4389
4390 if (!ValidateRobustBufferSize(context, bufSize, *length))
4391 {
4392 return false;
4393 }
4394
4395 return true;
4396}
4397
Geoff Langc1984ed2016-10-07 12:41:00 -04004398bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4399 GLuint sampler,
4400 GLenum pname,
4401 GLuint bufSize,
4402 GLsizei *length,
4403 GLint *params)
4404{
4405 if (!ValidateRobustEntryPoint(context, bufSize))
4406 {
4407 return false;
4408 }
4409
4410 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4411 {
4412 return false;
4413 }
4414
4415 if (!ValidateRobustBufferSize(context, bufSize, *length))
4416 {
4417 return false;
4418 }
4419
4420 return true;
4421}
4422
Geoff Langc1984ed2016-10-07 12:41:00 -04004423bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4424 GLuint sampler,
4425 GLenum pname,
4426 GLsizei bufSize,
4427 const GLfloat *params)
4428{
4429 if (!ValidateRobustEntryPoint(context, bufSize))
4430 {
4431 return false;
4432 }
4433
4434 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4435}
4436
Geoff Langc1984ed2016-10-07 12:41:00 -04004437bool ValidateSamplerParameterivRobustANGLE(Context *context,
4438 GLuint sampler,
4439 GLenum pname,
4440 GLsizei bufSize,
4441 const GLint *params)
4442{
4443 if (!ValidateRobustEntryPoint(context, bufSize))
4444 {
4445 return false;
4446 }
4447
4448 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4449}
4450
Geoff Lang0b031062016-10-13 14:30:04 -04004451bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4452 GLuint index,
4453 GLenum pname,
4454 GLsizei bufSize,
4455 GLsizei *length,
4456 GLfloat *params)
4457{
4458 if (!ValidateRobustEntryPoint(context, bufSize))
4459 {
4460 return false;
4461 }
4462
4463 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4464 {
4465 return false;
4466 }
4467
4468 if (!ValidateRobustBufferSize(context, bufSize, *length))
4469 {
4470 return false;
4471 }
4472
4473 return true;
4474}
4475
Geoff Lang0b031062016-10-13 14:30:04 -04004476bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4477 GLuint index,
4478 GLenum pname,
4479 GLsizei bufSize,
4480 GLsizei *length,
4481 GLint *params)
4482{
4483 if (!ValidateRobustEntryPoint(context, bufSize))
4484 {
4485 return false;
4486 }
4487
4488 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4489 {
4490 return false;
4491 }
4492
4493 if (!ValidateRobustBufferSize(context, bufSize, *length))
4494 {
4495 return false;
4496 }
4497
4498 return true;
4499}
4500
Geoff Lang0b031062016-10-13 14:30:04 -04004501bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4502 GLuint index,
4503 GLenum pname,
4504 GLsizei bufSize,
4505 GLsizei *length,
4506 void **pointer)
4507{
4508 if (!ValidateRobustEntryPoint(context, bufSize))
4509 {
4510 return false;
4511 }
4512
4513 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4514 {
4515 return false;
4516 }
4517
4518 if (!ValidateRobustBufferSize(context, bufSize, *length))
4519 {
4520 return false;
4521 }
4522
4523 return true;
4524}
4525
Geoff Lang0b031062016-10-13 14:30:04 -04004526bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4527 GLuint index,
4528 GLenum pname,
4529 GLsizei bufSize,
4530 GLsizei *length,
4531 GLint *params)
4532{
4533 if (!ValidateRobustEntryPoint(context, bufSize))
4534 {
4535 return false;
4536 }
4537
4538 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4539 {
4540 return false;
4541 }
4542
4543 if (!ValidateRobustBufferSize(context, bufSize, *length))
4544 {
4545 return false;
4546 }
4547
4548 return true;
4549}
4550
Geoff Lang0b031062016-10-13 14:30:04 -04004551bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4552 GLuint index,
4553 GLenum pname,
4554 GLsizei bufSize,
4555 GLsizei *length,
4556 GLuint *params)
4557{
4558 if (!ValidateRobustEntryPoint(context, bufSize))
4559 {
4560 return false;
4561 }
4562
4563 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4564 {
4565 return false;
4566 }
4567
4568 if (!ValidateRobustBufferSize(context, bufSize, *length))
4569 {
4570 return false;
4571 }
4572
4573 return true;
4574}
4575
Geoff Lang6899b872016-10-14 11:30:13 -04004576bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4577 GLuint program,
4578 GLuint uniformBlockIndex,
4579 GLenum pname,
4580 GLsizei bufSize,
4581 GLsizei *length,
4582 GLint *params)
4583{
4584 if (!ValidateRobustEntryPoint(context, bufSize))
4585 {
4586 return false;
4587 }
4588
4589 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4590 {
4591 return false;
4592 }
4593
4594 if (!ValidateRobustBufferSize(context, bufSize, *length))
4595 {
4596 return false;
4597 }
4598
4599 return true;
4600}
4601
Geoff Lang0a9661f2016-10-20 10:59:20 -07004602bool ValidateGetInternalFormativRobustANGLE(Context *context,
4603 GLenum target,
4604 GLenum internalformat,
4605 GLenum pname,
4606 GLsizei bufSize,
4607 GLsizei *length,
4608 GLint *params)
4609{
4610 if (!ValidateRobustEntryPoint(context, bufSize))
4611 {
4612 return false;
4613 }
4614
4615 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4616 {
4617 return false;
4618 }
4619
4620 if (!ValidateRobustBufferSize(context, bufSize, *length))
4621 {
4622 return false;
4623 }
4624
4625 return true;
4626}
4627
Shao80957d92017-02-20 21:25:59 +08004628bool ValidateVertexFormatBase(ValidationContext *context,
4629 GLuint attribIndex,
4630 GLint size,
4631 GLenum type,
4632 GLboolean pureInteger)
4633{
4634 const Caps &caps = context->getCaps();
4635 if (attribIndex >= caps.maxVertexAttributes)
4636 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004637 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004638 return false;
4639 }
4640
4641 if (size < 1 || size > 4)
4642 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004643 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004644 return false;
Shao80957d92017-02-20 21:25:59 +08004645 }
4646
4647 switch (type)
4648 {
4649 case GL_BYTE:
4650 case GL_UNSIGNED_BYTE:
4651 case GL_SHORT:
4652 case GL_UNSIGNED_SHORT:
4653 break;
4654
4655 case GL_INT:
4656 case GL_UNSIGNED_INT:
4657 if (context->getClientMajorVersion() < 3)
4658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004659 context->handleError(InvalidEnum()
4660 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004661 return false;
4662 }
4663 break;
4664
4665 case GL_FIXED:
4666 case GL_FLOAT:
4667 if (pureInteger)
4668 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004669 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004670 return false;
4671 }
4672 break;
4673
4674 case GL_HALF_FLOAT:
4675 if (context->getClientMajorVersion() < 3)
4676 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004677 context->handleError(InvalidEnum()
4678 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004679 return false;
4680 }
4681 if (pureInteger)
4682 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004683 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004684 return false;
4685 }
4686 break;
4687
4688 case GL_INT_2_10_10_10_REV:
4689 case GL_UNSIGNED_INT_2_10_10_10_REV:
4690 if (context->getClientMajorVersion() < 3)
4691 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004692 context->handleError(InvalidEnum()
4693 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004694 return false;
4695 }
4696 if (pureInteger)
4697 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004698 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004699 return false;
4700 }
4701 if (size != 4)
4702 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004703 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4704 "UNSIGNED_INT_2_10_10_10_REV and "
4705 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004706 return false;
4707 }
4708 break;
4709
4710 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004711 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004712 return false;
4713 }
4714
4715 return true;
4716}
4717
Geoff Lang76e65652017-03-27 14:58:02 -04004718// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4719// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4720// specified clear value and the type of a buffer that is being cleared generates an
4721// INVALID_OPERATION error instead of producing undefined results
4722bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4723 GLint drawbuffer,
4724 const GLenum *validComponentTypes,
4725 size_t validComponentTypeCount)
4726{
4727 const FramebufferAttachment *attachment =
4728 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4729 if (attachment)
4730 {
4731 GLenum componentType = attachment->getFormat().info->componentType;
4732 const GLenum *end = validComponentTypes + validComponentTypeCount;
4733 if (std::find(validComponentTypes, end, componentType) == end)
4734 {
4735 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004736 InvalidOperation()
4737 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004738 return false;
4739 }
4740 }
4741
4742 return true;
4743}
4744
Corentin Wallezb2931602017-04-11 15:58:57 -04004745bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4746 GLsizei imageSize,
4747 GLsizei dataSize)
4748{
4749 if (!ValidateRobustEntryPoint(context, dataSize))
4750 {
4751 return false;
4752 }
4753
Corentin Wallez336129f2017-10-17 15:55:40 -04004754 gl::Buffer *pixelUnpackBuffer =
4755 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004756 if (pixelUnpackBuffer == nullptr)
4757 {
4758 if (dataSize < imageSize)
4759 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004760 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004761 }
4762 }
4763 return true;
4764}
4765
Jamie Madillbe849e42017-05-02 15:49:00 -04004766bool ValidateGetBufferParameterBase(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004767 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004768 GLenum pname,
4769 bool pointerVersion,
4770 GLsizei *numParams)
4771{
4772 if (numParams)
4773 {
4774 *numParams = 0;
4775 }
4776
Corentin Walleze4477002017-12-01 14:39:58 -05004777 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004778 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004779 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004780 return false;
4781 }
4782
4783 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4784 if (!buffer)
4785 {
4786 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004787 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004788 return false;
4789 }
4790
4791 const Extensions &extensions = context->getExtensions();
4792
4793 switch (pname)
4794 {
4795 case GL_BUFFER_USAGE:
4796 case GL_BUFFER_SIZE:
4797 break;
4798
4799 case GL_BUFFER_ACCESS_OES:
4800 if (!extensions.mapBuffer)
4801 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004802 context->handleError(InvalidEnum()
4803 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004804 return false;
4805 }
4806 break;
4807
4808 case GL_BUFFER_MAPPED:
4809 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4810 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4811 !extensions.mapBufferRange)
4812 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004813 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4814 "GL_OES_mapbuffer or "
4815 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004816 return false;
4817 }
4818 break;
4819
4820 case GL_BUFFER_MAP_POINTER:
4821 if (!pointerVersion)
4822 {
4823 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004824 InvalidEnum()
4825 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004826 return false;
4827 }
4828 break;
4829
4830 case GL_BUFFER_ACCESS_FLAGS:
4831 case GL_BUFFER_MAP_OFFSET:
4832 case GL_BUFFER_MAP_LENGTH:
4833 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4834 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004835 context->handleError(InvalidEnum()
4836 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004837 return false;
4838 }
4839 break;
4840
4841 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004842 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004843 return false;
4844 }
4845
4846 // All buffer parameter queries return one value.
4847 if (numParams)
4848 {
4849 *numParams = 1;
4850 }
4851
4852 return true;
4853}
4854
4855bool ValidateGetRenderbufferParameterivBase(Context *context,
4856 GLenum target,
4857 GLenum pname,
4858 GLsizei *length)
4859{
4860 if (length)
4861 {
4862 *length = 0;
4863 }
4864
4865 if (target != GL_RENDERBUFFER)
4866 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004867 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004868 return false;
4869 }
4870
4871 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4872 if (renderbuffer == nullptr)
4873 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004874 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004875 return false;
4876 }
4877
4878 switch (pname)
4879 {
4880 case GL_RENDERBUFFER_WIDTH:
4881 case GL_RENDERBUFFER_HEIGHT:
4882 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4883 case GL_RENDERBUFFER_RED_SIZE:
4884 case GL_RENDERBUFFER_GREEN_SIZE:
4885 case GL_RENDERBUFFER_BLUE_SIZE:
4886 case GL_RENDERBUFFER_ALPHA_SIZE:
4887 case GL_RENDERBUFFER_DEPTH_SIZE:
4888 case GL_RENDERBUFFER_STENCIL_SIZE:
4889 break;
4890
4891 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4892 if (!context->getExtensions().framebufferMultisample)
4893 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004894 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004895 return false;
4896 }
4897 break;
4898
4899 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004900 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004901 return false;
4902 }
4903
4904 if (length)
4905 {
4906 *length = 1;
4907 }
4908 return true;
4909}
4910
4911bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4912{
4913 if (length)
4914 {
4915 *length = 0;
4916 }
4917
4918 if (GetValidShader(context, shader) == nullptr)
4919 {
4920 return false;
4921 }
4922
4923 switch (pname)
4924 {
4925 case GL_SHADER_TYPE:
4926 case GL_DELETE_STATUS:
4927 case GL_COMPILE_STATUS:
4928 case GL_INFO_LOG_LENGTH:
4929 case GL_SHADER_SOURCE_LENGTH:
4930 break;
4931
4932 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4933 if (!context->getExtensions().translatedShaderSource)
4934 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004935 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004936 return false;
4937 }
4938 break;
4939
4940 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004941 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004942 return false;
4943 }
4944
4945 if (length)
4946 {
4947 *length = 1;
4948 }
4949 return true;
4950}
4951
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004952bool ValidateGetTexParameterBase(Context *context,
4953 TextureType target,
4954 GLenum pname,
4955 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04004956{
4957 if (length)
4958 {
4959 *length = 0;
4960 }
4961
4962 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4963 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004964 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004965 return false;
4966 }
4967
4968 if (context->getTargetTexture(target) == nullptr)
4969 {
4970 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004971 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004972 return false;
4973 }
4974
4975 switch (pname)
4976 {
4977 case GL_TEXTURE_MAG_FILTER:
4978 case GL_TEXTURE_MIN_FILTER:
4979 case GL_TEXTURE_WRAP_S:
4980 case GL_TEXTURE_WRAP_T:
4981 break;
4982
4983 case GL_TEXTURE_USAGE_ANGLE:
4984 if (!context->getExtensions().textureUsage)
4985 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004986 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004987 return false;
4988 }
4989 break;
4990
4991 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05004992 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04004993 {
Jamie Madillbe849e42017-05-02 15:49:00 -04004994 return false;
4995 }
4996 break;
4997
4998 case GL_TEXTURE_IMMUTABLE_FORMAT:
4999 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5000 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005001 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005002 return false;
5003 }
5004 break;
5005
5006 case GL_TEXTURE_WRAP_R:
5007 case GL_TEXTURE_IMMUTABLE_LEVELS:
5008 case GL_TEXTURE_SWIZZLE_R:
5009 case GL_TEXTURE_SWIZZLE_G:
5010 case GL_TEXTURE_SWIZZLE_B:
5011 case GL_TEXTURE_SWIZZLE_A:
5012 case GL_TEXTURE_BASE_LEVEL:
5013 case GL_TEXTURE_MAX_LEVEL:
5014 case GL_TEXTURE_MIN_LOD:
5015 case GL_TEXTURE_MAX_LOD:
5016 case GL_TEXTURE_COMPARE_MODE:
5017 case GL_TEXTURE_COMPARE_FUNC:
5018 if (context->getClientMajorVersion() < 3)
5019 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005020 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005021 return false;
5022 }
5023 break;
5024
5025 case GL_TEXTURE_SRGB_DECODE_EXT:
5026 if (!context->getExtensions().textureSRGBDecode)
5027 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005028 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005029 return false;
5030 }
5031 break;
5032
Yunchao Hebacaa712018-01-30 14:01:39 +08005033 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5034 if (context->getClientVersion() < Version(3, 1))
5035 {
5036 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5037 return false;
5038 }
5039 break;
5040
Jamie Madillbe849e42017-05-02 15:49:00 -04005041 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005042 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005043 return false;
5044 }
5045
5046 if (length)
5047 {
5048 *length = 1;
5049 }
5050 return true;
5051}
5052
5053bool ValidateGetVertexAttribBase(Context *context,
5054 GLuint index,
5055 GLenum pname,
5056 GLsizei *length,
5057 bool pointer,
5058 bool pureIntegerEntryPoint)
5059{
5060 if (length)
5061 {
5062 *length = 0;
5063 }
5064
5065 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5066 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005067 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005068 return false;
5069 }
5070
5071 if (index >= context->getCaps().maxVertexAttributes)
5072 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005073 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005074 return false;
5075 }
5076
5077 if (pointer)
5078 {
5079 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5080 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005081 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005082 return false;
5083 }
5084 }
5085 else
5086 {
5087 switch (pname)
5088 {
5089 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5090 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5091 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5092 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5093 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5094 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5095 case GL_CURRENT_VERTEX_ATTRIB:
5096 break;
5097
5098 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5099 static_assert(
5100 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5101 "ANGLE extension enums not equal to GL enums.");
5102 if (context->getClientMajorVersion() < 3 &&
5103 !context->getExtensions().instancedArrays)
5104 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005105 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5106 "requires OpenGL ES 3.0 or "
5107 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005108 return false;
5109 }
5110 break;
5111
5112 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5113 if (context->getClientMajorVersion() < 3)
5114 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005115 context->handleError(
5116 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005117 return false;
5118 }
5119 break;
5120
5121 case GL_VERTEX_ATTRIB_BINDING:
5122 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5123 if (context->getClientVersion() < ES_3_1)
5124 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005125 context->handleError(InvalidEnum()
5126 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005127 return false;
5128 }
5129 break;
5130
5131 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005132 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005133 return false;
5134 }
5135 }
5136
5137 if (length)
5138 {
5139 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5140 {
5141 *length = 4;
5142 }
5143 else
5144 {
5145 *length = 1;
5146 }
5147 }
5148
5149 return true;
5150}
5151
Jamie Madill4928b7c2017-06-20 12:57:39 -04005152bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005153 GLint x,
5154 GLint y,
5155 GLsizei width,
5156 GLsizei height,
5157 GLenum format,
5158 GLenum type,
5159 GLsizei bufSize,
5160 GLsizei *length,
5161 GLsizei *columns,
5162 GLsizei *rows,
5163 void *pixels)
5164{
5165 if (length != nullptr)
5166 {
5167 *length = 0;
5168 }
5169 if (rows != nullptr)
5170 {
5171 *rows = 0;
5172 }
5173 if (columns != nullptr)
5174 {
5175 *columns = 0;
5176 }
5177
5178 if (width < 0 || height < 0)
5179 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005180 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005181 return false;
5182 }
5183
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005184 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005185
5186 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5187 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005188 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005189 return false;
5190 }
5191
5192 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5193 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005194 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005195 return false;
5196 }
5197
5198 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5199 ASSERT(framebuffer);
5200
5201 if (framebuffer->getReadBufferState() == GL_NONE)
5202 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005203 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005204 return false;
5205 }
5206
5207 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5208 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5209 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5210 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5211 // situation is an application error that would lead to a crash in ANGLE.
5212 if (readBuffer == nullptr)
5213 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005214 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005215 return false;
5216 }
5217
Martin Radev28031682017-07-28 14:47:56 +03005218 // ANGLE_multiview, Revision 1:
5219 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5220 // current read framebuffer is not NONE.
5221 if (readBuffer->getMultiviewLayout() != GL_NONE)
5222 {
5223 context->handleError(InvalidFramebufferOperation()
5224 << "Attempting to read from a multi-view framebuffer.");
5225 return false;
5226 }
5227
Geoff Lang280ba992017-04-18 16:30:58 -04005228 if (context->getExtensions().webglCompatibility)
5229 {
5230 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5231 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5232 // and type before validating the combination of format and type. However, the
5233 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5234 // verifies that GL_INVALID_OPERATION is generated.
5235 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5236 // dEQP/WebGL.
5237 if (!ValidReadPixelsFormatEnum(context, format))
5238 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005239 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005240 return false;
5241 }
5242
5243 if (!ValidReadPixelsTypeEnum(context, type))
5244 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005245 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005246 return false;
5247 }
5248 }
5249
Jamie Madill4928b7c2017-06-20 12:57:39 -04005250 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5251 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005252 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5253
5254 bool validFormatTypeCombination =
5255 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5256
5257 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5258 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005259 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005260 return false;
5261 }
5262
5263 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005264 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005265 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5266 {
5267 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005268 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005269 return false;
5270 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005271 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5272 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5273 {
5274 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5275 return false;
5276 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005277
5278 // .. the data would be packed to the buffer object such that the memory writes required
5279 // would exceed the data store size.
5280 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5281 const gl::Extents size(width, height, 1);
5282 const auto &pack = context->getGLState().getPackState();
5283
5284 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5285 if (endByteOrErr.isError())
5286 {
5287 context->handleError(endByteOrErr.getError());
5288 return false;
5289 }
5290
5291 size_t endByte = endByteOrErr.getResult();
5292 if (bufSize >= 0)
5293 {
5294 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5295 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005296 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005297 return false;
5298 }
5299 }
5300
5301 if (pixelPackBuffer != nullptr)
5302 {
5303 CheckedNumeric<size_t> checkedEndByte(endByte);
5304 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5305 checkedEndByte += checkedOffset;
5306
5307 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5308 {
5309 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005310 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005311 return false;
5312 }
5313 }
5314
5315 if (pixelPackBuffer == nullptr && length != nullptr)
5316 {
5317 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5318 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005319 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005320 return false;
5321 }
5322
5323 *length = static_cast<GLsizei>(endByte);
5324 }
5325
Geoff Langa953b522018-02-21 16:56:23 -05005326 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005327 angle::CheckedNumeric<int> clippedExtent(length);
5328 if (start < 0)
5329 {
5330 // "subtract" the area that is less than 0
5331 clippedExtent += start;
5332 }
5333
Geoff Langa953b522018-02-21 16:56:23 -05005334 angle::CheckedNumeric<int> readExtent = start;
5335 readExtent += length;
5336 if (!readExtent.IsValid())
5337 {
5338 return false;
5339 }
5340
5341 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005342 {
5343 // Subtract the region to the right of the read buffer
5344 clippedExtent -= (readExtent - bufferSize);
5345 }
5346
5347 if (!clippedExtent.IsValid())
5348 {
Geoff Langa953b522018-02-21 16:56:23 -05005349 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005350 }
5351
Geoff Langa953b522018-02-21 16:56:23 -05005352 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5353 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005354 };
5355
Geoff Langa953b522018-02-21 16:56:23 -05005356 GLsizei writtenColumns = 0;
5357 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5358 {
5359 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5360 return false;
5361 }
5362
5363 GLsizei writtenRows = 0;
5364 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5365 {
5366 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5367 return false;
5368 }
5369
Jamie Madillbe849e42017-05-02 15:49:00 -04005370 if (columns != nullptr)
5371 {
Geoff Langa953b522018-02-21 16:56:23 -05005372 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005373 }
5374
5375 if (rows != nullptr)
5376 {
Geoff Langa953b522018-02-21 16:56:23 -05005377 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005378 }
5379
5380 return true;
5381}
5382
5383template <typename ParamType>
5384bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005385 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005386 GLenum pname,
5387 GLsizei bufSize,
5388 const ParamType *params)
5389{
5390 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5391 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005392 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005393 return false;
5394 }
5395
5396 if (context->getTargetTexture(target) == nullptr)
5397 {
5398 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005399 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005400 return false;
5401 }
5402
5403 const GLsizei minBufSize = 1;
5404 if (bufSize >= 0 && bufSize < minBufSize)
5405 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005406 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005407 return false;
5408 }
5409
5410 switch (pname)
5411 {
5412 case GL_TEXTURE_WRAP_R:
5413 case GL_TEXTURE_SWIZZLE_R:
5414 case GL_TEXTURE_SWIZZLE_G:
5415 case GL_TEXTURE_SWIZZLE_B:
5416 case GL_TEXTURE_SWIZZLE_A:
5417 case GL_TEXTURE_BASE_LEVEL:
5418 case GL_TEXTURE_MAX_LEVEL:
5419 case GL_TEXTURE_COMPARE_MODE:
5420 case GL_TEXTURE_COMPARE_FUNC:
5421 case GL_TEXTURE_MIN_LOD:
5422 case GL_TEXTURE_MAX_LOD:
5423 if (context->getClientMajorVersion() < 3)
5424 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005425 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005426 return false;
5427 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005428 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005429 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005430 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5431 "available without "
5432 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005433 return false;
5434 }
5435 break;
5436
5437 default:
5438 break;
5439 }
5440
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005441 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005442 {
5443 switch (pname)
5444 {
5445 case GL_TEXTURE_MIN_FILTER:
5446 case GL_TEXTURE_MAG_FILTER:
5447 case GL_TEXTURE_WRAP_S:
5448 case GL_TEXTURE_WRAP_T:
5449 case GL_TEXTURE_WRAP_R:
5450 case GL_TEXTURE_MIN_LOD:
5451 case GL_TEXTURE_MAX_LOD:
5452 case GL_TEXTURE_COMPARE_MODE:
5453 case GL_TEXTURE_COMPARE_FUNC:
5454 context->handleError(InvalidEnum()
5455 << "Invalid parameter for 2D multisampled textures.");
5456 return false;
5457 }
5458 }
5459
Jamie Madillbe849e42017-05-02 15:49:00 -04005460 switch (pname)
5461 {
5462 case GL_TEXTURE_WRAP_S:
5463 case GL_TEXTURE_WRAP_T:
5464 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005465 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005466 bool restrictedWrapModes =
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005467 target == TextureType::External || target == TextureType::Rectangle;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005468 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5469 {
5470 return false;
5471 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005472 }
5473 break;
5474
5475 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005476 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005477 bool restrictedMinFilter =
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005478 target == TextureType::External || target == TextureType::Rectangle;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005479 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5480 {
5481 return false;
5482 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005483 }
5484 break;
5485
5486 case GL_TEXTURE_MAG_FILTER:
5487 if (!ValidateTextureMagFilterValue(context, params))
5488 {
5489 return false;
5490 }
5491 break;
5492
5493 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005494 if (!context->getExtensions().textureUsage)
5495 {
5496 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5497 return false;
5498 }
5499
Jamie Madillbe849e42017-05-02 15:49:00 -04005500 switch (ConvertToGLenum(params[0]))
5501 {
5502 case GL_NONE:
5503 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5504 break;
5505
5506 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005507 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005508 return false;
5509 }
5510 break;
5511
5512 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Jamie Madillbe849e42017-05-02 15:49:00 -04005513 {
Luc Ferron1b1a8642018-01-23 15:12:01 -05005514 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5515 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5516 {
5517 return false;
5518 }
5519 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
Jamie Madillbe849e42017-05-02 15:49:00 -04005520 }
5521 break;
5522
5523 case GL_TEXTURE_MIN_LOD:
5524 case GL_TEXTURE_MAX_LOD:
5525 // any value is permissible
5526 break;
5527
5528 case GL_TEXTURE_COMPARE_MODE:
5529 if (!ValidateTextureCompareModeValue(context, params))
5530 {
5531 return false;
5532 }
5533 break;
5534
5535 case GL_TEXTURE_COMPARE_FUNC:
5536 if (!ValidateTextureCompareFuncValue(context, params))
5537 {
5538 return false;
5539 }
5540 break;
5541
5542 case GL_TEXTURE_SWIZZLE_R:
5543 case GL_TEXTURE_SWIZZLE_G:
5544 case GL_TEXTURE_SWIZZLE_B:
5545 case GL_TEXTURE_SWIZZLE_A:
5546 switch (ConvertToGLenum(params[0]))
5547 {
5548 case GL_RED:
5549 case GL_GREEN:
5550 case GL_BLUE:
5551 case GL_ALPHA:
5552 case GL_ZERO:
5553 case GL_ONE:
5554 break;
5555
5556 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005557 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005558 return false;
5559 }
5560 break;
5561
5562 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005563 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005564 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005565 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005566 return false;
5567 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005568 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005569 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005570 context->handleError(InvalidOperation()
5571 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005572 return false;
5573 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005574 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005575 {
5576 context->handleError(InvalidOperation()
5577 << "Base level must be 0 for multisampled textures.");
5578 return false;
5579 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005580 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005581 {
5582 context->handleError(InvalidOperation()
5583 << "Base level must be 0 for rectangle textures.");
5584 return false;
5585 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005586 break;
5587
5588 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005589 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005590 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005591 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005592 return false;
5593 }
5594 break;
5595
5596 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5597 if (context->getClientVersion() < Version(3, 1))
5598 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005599 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005600 return false;
5601 }
5602 switch (ConvertToGLenum(params[0]))
5603 {
5604 case GL_DEPTH_COMPONENT:
5605 case GL_STENCIL_INDEX:
5606 break;
5607
5608 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005609 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005610 return false;
5611 }
5612 break;
5613
5614 case GL_TEXTURE_SRGB_DECODE_EXT:
5615 if (!ValidateTextureSRGBDecodeValue(context, params))
5616 {
5617 return false;
5618 }
5619 break;
5620
5621 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005622 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005623 return false;
5624 }
5625
5626 return true;
5627}
5628
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005629template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
5630template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04005631
Jamie Madill12e957f2017-08-26 21:42:26 -04005632bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5633{
5634 if (index >= MAX_VERTEX_ATTRIBS)
5635 {
5636 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5637 return false;
5638 }
5639
5640 return true;
5641}
5642
5643bool ValidateGetActiveUniformBlockivBase(Context *context,
5644 GLuint program,
5645 GLuint uniformBlockIndex,
5646 GLenum pname,
5647 GLsizei *length)
5648{
5649 if (length)
5650 {
5651 *length = 0;
5652 }
5653
5654 if (context->getClientMajorVersion() < 3)
5655 {
5656 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5657 return false;
5658 }
5659
5660 Program *programObject = GetValidProgram(context, program);
5661 if (!programObject)
5662 {
5663 return false;
5664 }
5665
5666 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5667 {
5668 context->handleError(InvalidValue()
5669 << "uniformBlockIndex exceeds active uniform block count.");
5670 return false;
5671 }
5672
5673 switch (pname)
5674 {
5675 case GL_UNIFORM_BLOCK_BINDING:
5676 case GL_UNIFORM_BLOCK_DATA_SIZE:
5677 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5678 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5679 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5680 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5681 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5682 break;
5683
5684 default:
5685 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5686 return false;
5687 }
5688
5689 if (length)
5690 {
5691 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5692 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005693 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005694 programObject->getUniformBlockByIndex(uniformBlockIndex);
5695 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5696 }
5697 else
5698 {
5699 *length = 1;
5700 }
5701 }
5702
5703 return true;
5704}
5705
Jamie Madill9696d072017-08-26 23:19:57 -04005706template <typename ParamType>
5707bool ValidateSamplerParameterBase(Context *context,
5708 GLuint sampler,
5709 GLenum pname,
5710 GLsizei bufSize,
5711 ParamType *params)
5712{
5713 if (context->getClientMajorVersion() < 3)
5714 {
5715 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5716 return false;
5717 }
5718
5719 if (!context->isSampler(sampler))
5720 {
5721 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5722 return false;
5723 }
5724
5725 const GLsizei minBufSize = 1;
5726 if (bufSize >= 0 && bufSize < minBufSize)
5727 {
5728 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5729 return false;
5730 }
5731
5732 switch (pname)
5733 {
5734 case GL_TEXTURE_WRAP_S:
5735 case GL_TEXTURE_WRAP_T:
5736 case GL_TEXTURE_WRAP_R:
5737 if (!ValidateTextureWrapModeValue(context, params, false))
5738 {
5739 return false;
5740 }
5741 break;
5742
5743 case GL_TEXTURE_MIN_FILTER:
5744 if (!ValidateTextureMinFilterValue(context, params, false))
5745 {
5746 return false;
5747 }
5748 break;
5749
5750 case GL_TEXTURE_MAG_FILTER:
5751 if (!ValidateTextureMagFilterValue(context, params))
5752 {
5753 return false;
5754 }
5755 break;
5756
5757 case GL_TEXTURE_MIN_LOD:
5758 case GL_TEXTURE_MAX_LOD:
5759 // any value is permissible
5760 break;
5761
5762 case GL_TEXTURE_COMPARE_MODE:
5763 if (!ValidateTextureCompareModeValue(context, params))
5764 {
5765 return false;
5766 }
5767 break;
5768
5769 case GL_TEXTURE_COMPARE_FUNC:
5770 if (!ValidateTextureCompareFuncValue(context, params))
5771 {
5772 return false;
5773 }
5774 break;
5775
5776 case GL_TEXTURE_SRGB_DECODE_EXT:
5777 if (!ValidateTextureSRGBDecodeValue(context, params))
5778 {
5779 return false;
5780 }
5781 break;
5782
Luc Ferron1b1a8642018-01-23 15:12:01 -05005783 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5784 {
5785 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5786 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5787 {
5788 return false;
5789 }
5790 }
5791 break;
5792
Jamie Madill9696d072017-08-26 23:19:57 -04005793 default:
5794 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5795 return false;
5796 }
5797
5798 return true;
5799}
5800
5801template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5802template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5803
5804bool ValidateGetSamplerParameterBase(Context *context,
5805 GLuint sampler,
5806 GLenum pname,
5807 GLsizei *length)
5808{
5809 if (length)
5810 {
5811 *length = 0;
5812 }
5813
5814 if (context->getClientMajorVersion() < 3)
5815 {
5816 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5817 return false;
5818 }
5819
5820 if (!context->isSampler(sampler))
5821 {
5822 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5823 return false;
5824 }
5825
5826 switch (pname)
5827 {
5828 case GL_TEXTURE_WRAP_S:
5829 case GL_TEXTURE_WRAP_T:
5830 case GL_TEXTURE_WRAP_R:
5831 case GL_TEXTURE_MIN_FILTER:
5832 case GL_TEXTURE_MAG_FILTER:
5833 case GL_TEXTURE_MIN_LOD:
5834 case GL_TEXTURE_MAX_LOD:
5835 case GL_TEXTURE_COMPARE_MODE:
5836 case GL_TEXTURE_COMPARE_FUNC:
5837 break;
5838
Luc Ferron1b1a8642018-01-23 15:12:01 -05005839 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5840 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
5841 {
5842 return false;
5843 }
5844 break;
5845
Jamie Madill9696d072017-08-26 23:19:57 -04005846 case GL_TEXTURE_SRGB_DECODE_EXT:
5847 if (!context->getExtensions().textureSRGBDecode)
5848 {
5849 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5850 return false;
5851 }
5852 break;
5853
5854 default:
5855 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5856 return false;
5857 }
5858
5859 if (length)
5860 {
5861 *length = 1;
5862 }
5863 return true;
5864}
5865
5866bool ValidateGetInternalFormativBase(Context *context,
5867 GLenum target,
5868 GLenum internalformat,
5869 GLenum pname,
5870 GLsizei bufSize,
5871 GLsizei *numParams)
5872{
5873 if (numParams)
5874 {
5875 *numParams = 0;
5876 }
5877
5878 if (context->getClientMajorVersion() < 3)
5879 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005880 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005881 return false;
5882 }
5883
5884 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5885 if (!formatCaps.renderable)
5886 {
5887 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5888 return false;
5889 }
5890
5891 switch (target)
5892 {
5893 case GL_RENDERBUFFER:
5894 break;
5895
5896 case GL_TEXTURE_2D_MULTISAMPLE:
5897 if (context->getClientVersion() < ES_3_1)
5898 {
5899 context->handleError(InvalidOperation()
5900 << "Texture target requires at least OpenGL ES 3.1.");
5901 return false;
5902 }
5903 break;
5904
5905 default:
5906 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5907 return false;
5908 }
5909
5910 if (bufSize < 0)
5911 {
5912 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5913 return false;
5914 }
5915
5916 GLsizei maxWriteParams = 0;
5917 switch (pname)
5918 {
5919 case GL_NUM_SAMPLE_COUNTS:
5920 maxWriteParams = 1;
5921 break;
5922
5923 case GL_SAMPLES:
5924 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5925 break;
5926
5927 default:
5928 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5929 return false;
5930 }
5931
5932 if (numParams)
5933 {
5934 // glGetInternalFormativ will not overflow bufSize
5935 *numParams = std::min(bufSize, maxWriteParams);
5936 }
5937
5938 return true;
5939}
5940
Jamie Madillc29968b2016-01-20 11:17:23 -05005941} // namespace gl