blob: 47cc3c71b22ead6fe8049110aef8ee5c35f94fac [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}
Jamie Madill5b772312018-03-08 20:28:32 -050070bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex, GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040071{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070072 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040073 const gl::Program *program = state.getProgram();
74
Corentin Wallez327411e2016-12-09 11:09:17 -050075 bool webglCompatibility = context->getExtensions().webglCompatibility;
76
Jamie Madill231c7f52017-04-26 13:45:37 -040077 const VertexArray *vao = state.getVertexArray();
78 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080079 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madilld078c682018-01-02 11:50:24 -050080 for (size_t attributeIndex : vao->getEnabledAttributesMask())
Jamie Madill1ca74672015-07-21 15:14:11 -040081 {
82 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallez672f7f32017-06-15 17:42:17 -040083
84 // No need to range check for disabled attribs.
85 if (!attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040086 {
Corentin Wallezfd456442016-12-21 17:57:00 -050087 continue;
88 }
Jamie Madill1ca74672015-07-21 15:14:11 -040089
Jamie Madill231c7f52017-04-26 13:45:37 -040090 // If we have no buffer, then we either get an error, or there are no more checks to be
91 // done.
Corentin Wallez672f7f32017-06-15 17:42:17 -040092 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
93 gl::Buffer *buffer = binding.getBuffer().get();
Corentin Wallezfd456442016-12-21 17:57:00 -050094 if (!buffer)
95 {
Geoff Langfeb8c682017-02-13 16:07:35 -050096 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -050097 {
98 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050099 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
100 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
101 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
102 // error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700103 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
Corentin Wallezfd456442016-12-21 17:57:00 -0500104 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -0500105 }
Corentin Wallezfd456442016-12-21 17:57:00 -0500106 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -0400107 {
108 // This is an application error that would normally result in a crash,
109 // but we catch it and return an error
Brandon Jonesafa75152017-07-21 13:11:29 -0700110 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
Jamie Madill1ca74672015-07-21 15:14:11 -0400111 return false;
112 }
Corentin Wallezfd456442016-12-21 17:57:00 -0500113 continue;
114 }
115
Corentin Wallez672f7f32017-06-15 17:42:17 -0400116 // This needs to come after the check for client arrays as even unused attributes cannot use
117 // client-side arrays
118 if (!program->isAttribLocationActive(attributeIndex))
119 {
120 continue;
121 }
122
Corentin Wallezfd456442016-12-21 17:57:00 -0500123 // If we're drawing zero vertices, we have enough data.
124 if (vertexCount <= 0 || primcount <= 0)
125 {
126 continue;
127 }
128
129 GLint maxVertexElement = 0;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300130 GLuint divisor = binding.getDivisor();
131 if (divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500132 {
133 maxVertexElement = maxVertex;
134 }
135 else
136 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300137 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500138 }
139
140 // We do manual overflow checks here instead of using safe_math.h because it was
141 // a bottleneck. Thanks to some properties of GL we know inequalities that can
142 // help us make the overflow checks faster.
143
144 // The max possible attribSize is 16 for a vector of 4 32 bit values.
145 constexpr uint64_t kMaxAttribSize = 16;
146 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
147 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
148
149 // We know attribStride is given as a GLsizei which is typedefed to int.
150 // We also know an upper bound for attribSize.
151 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800152 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500153 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
154 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
155
156 // Computing the max offset using uint64_t without attrib.offset is overflow
157 // safe. Note: Last vertex element does not take the full stride!
158 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
159 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
160
161 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800162 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
163 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500164 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700165 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500166 return false;
167 }
168 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
169
170 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
171 // We can return INVALID_OPERATION if our vertex attribute does not have
172 // enough backing data.
173 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
174 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700175 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500176 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400177 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800178
179 if (webglCompatibility && buffer->isBoundForTransformFeedbackAndOtherUse())
180 {
181 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
182 VertexBufferBoundForTransformFeedback);
183 return false;
184 }
Jamie Madill1ca74672015-07-21 15:14:11 -0400185 }
186
187 return true;
188}
189
Jamie Madill5b772312018-03-08 20:28:32 -0500190bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400191{
192 switch (type)
193 {
194 // Types referenced in Table 3.4 of the ES 2.0.25 spec
195 case GL_UNSIGNED_BYTE:
196 case GL_UNSIGNED_SHORT_4_4_4_4:
197 case GL_UNSIGNED_SHORT_5_5_5_1:
198 case GL_UNSIGNED_SHORT_5_6_5:
199 return context->getClientVersion() >= ES_2_0;
200
201 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
202 case GL_BYTE:
203 case GL_INT:
204 case GL_SHORT:
205 case GL_UNSIGNED_INT:
206 case GL_UNSIGNED_INT_10F_11F_11F_REV:
207 case GL_UNSIGNED_INT_24_8:
208 case GL_UNSIGNED_INT_2_10_10_10_REV:
209 case GL_UNSIGNED_INT_5_9_9_9_REV:
210 case GL_UNSIGNED_SHORT:
211 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
212 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
213 return context->getClientVersion() >= ES_3_0;
214
215 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400216 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
217 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400218
219 case GL_HALF_FLOAT:
220 return context->getClientVersion() >= ES_3_0 ||
221 context->getExtensions().textureHalfFloat;
222
223 case GL_HALF_FLOAT_OES:
224 return context->getExtensions().colorBufferHalfFloat;
225
226 default:
227 return false;
228 }
229}
230
Jamie Madill5b772312018-03-08 20:28:32 -0500231bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400232{
233 switch (format)
234 {
235 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
236 case GL_RGBA:
237 case GL_RGB:
238 case GL_ALPHA:
239 return context->getClientVersion() >= ES_2_0;
240
241 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
242 case GL_RG:
243 case GL_RED:
244 case GL_RGBA_INTEGER:
245 case GL_RGB_INTEGER:
246 case GL_RG_INTEGER:
247 case GL_RED_INTEGER:
248 return context->getClientVersion() >= ES_3_0;
249
250 case GL_SRGB_ALPHA_EXT:
251 case GL_SRGB_EXT:
252 return context->getExtensions().sRGB;
253
254 case GL_BGRA_EXT:
255 return context->getExtensions().readFormatBGRA;
256
257 default:
258 return false;
259 }
260}
261
Jamie Madill5b772312018-03-08 20:28:32 -0500262bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400263 GLenum framebufferComponentType,
264 GLenum format,
265 GLenum type)
266{
267 switch (framebufferComponentType)
268 {
269 case GL_UNSIGNED_NORMALIZED:
270 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
271 // ReadPixels with BGRA even if the extension is not present
272 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
273 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
274 type == GL_UNSIGNED_BYTE);
275
276 case GL_SIGNED_NORMALIZED:
277 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
278
279 case GL_INT:
280 return (format == GL_RGBA_INTEGER && type == GL_INT);
281
282 case GL_UNSIGNED_INT:
283 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
284
285 case GL_FLOAT:
286 return (format == GL_RGBA && type == GL_FLOAT);
287
288 default:
289 UNREACHABLE();
290 return false;
291 }
292}
293
Geoff Langc1984ed2016-10-07 12:41:00 -0400294template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400295bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400296{
297 switch (ConvertToGLenum(params[0]))
298 {
299 case GL_CLAMP_TO_EDGE:
300 break;
301
302 case GL_REPEAT:
303 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400304 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400305 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400306 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700307 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400308 return false;
309 }
310 break;
311
312 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700313 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400314 return false;
315 }
316
317 return true;
318}
319
320template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400321bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400322{
323 switch (ConvertToGLenum(params[0]))
324 {
325 case GL_NEAREST:
326 case GL_LINEAR:
327 break;
328
329 case GL_NEAREST_MIPMAP_NEAREST:
330 case GL_LINEAR_MIPMAP_NEAREST:
331 case GL_NEAREST_MIPMAP_LINEAR:
332 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400333 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400334 {
335 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700336 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400337 return false;
338 }
339 break;
340
341 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700342 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400343 return false;
344 }
345
346 return true;
347}
348
349template <typename ParamType>
350bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
351{
352 switch (ConvertToGLenum(params[0]))
353 {
354 case GL_NEAREST:
355 case GL_LINEAR:
356 break;
357
358 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700359 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400360 return false;
361 }
362
363 return true;
364}
365
366template <typename ParamType>
367bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
368{
369 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
370 switch (ConvertToGLenum(params[0]))
371 {
372 case GL_NONE:
373 case GL_COMPARE_REF_TO_TEXTURE:
374 break;
375
376 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700377 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400378 return false;
379 }
380
381 return true;
382}
383
384template <typename ParamType>
385bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
386{
387 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
388 switch (ConvertToGLenum(params[0]))
389 {
390 case GL_LEQUAL:
391 case GL_GEQUAL:
392 case GL_LESS:
393 case GL_GREATER:
394 case GL_EQUAL:
395 case GL_NOTEQUAL:
396 case GL_ALWAYS:
397 case GL_NEVER:
398 break;
399
400 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700401 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400402 return false;
403 }
404
405 return true;
406}
407
408template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700409bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
410{
411 if (!context->getExtensions().textureSRGBDecode)
412 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700413 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700414 return false;
415 }
416
417 switch (ConvertToGLenum(params[0]))
418 {
419 case GL_DECODE_EXT:
420 case GL_SKIP_DECODE_EXT:
421 break;
422
423 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700424 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700425 return false;
426 }
427
428 return true;
429}
430
Luc Ferron1b1a8642018-01-23 15:12:01 -0500431bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
432{
433 if (!context->getExtensions().textureFilterAnisotropic)
434 {
435 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
436 return false;
437 }
438
439 return true;
440}
441
442bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
443{
444 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
445 {
446 return false;
447 }
448
449 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
450
451 if (paramValue < 1 || paramValue > largest)
452 {
453 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
454 return false;
455 }
456
457 return true;
458}
459
Jamie Madill5b772312018-03-08 20:28:32 -0500460bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400461{
462 const Program *program = context->getGLState().getProgram();
463 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
464
Brandon Jonesc405ae72017-12-06 14:15:03 -0800465 if (!ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
466 framebuffer->getDrawBufferTypeMask().to_ulong(),
467 program->getActiveOutputVariables().to_ulong(),
468 framebuffer->getDrawBufferMask().to_ulong()))
Geoff Lange0cff192017-05-30 13:04:56 -0400469 {
Brandon Jones76746f92017-11-22 11:44:41 -0800470 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
471 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400472 }
473
474 return true;
475}
476
Jamie Madill5b772312018-03-08 20:28:32 -0500477bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400478{
Jamie Madillcac94a92017-11-10 10:09:32 -0500479 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400480 const Program *program = context->getGLState().getProgram();
481 const VertexArray *vao = context->getGLState().getVertexArray();
482
Brandon Jonesc405ae72017-12-06 14:15:03 -0800483 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
484 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
485 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
486
487 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
488 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
489 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
490
491 if (!ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
492 program->getAttributesMask().to_ulong(), 0xFFFF))
Geoff Lang9ab5b822017-05-30 16:19:23 -0400493 {
Brandon Jonesc405ae72017-12-06 14:15:03 -0800494 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexShaderTypeMismatch);
495 return false;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400496 }
Geoff Lang9ab5b822017-05-30 16:19:23 -0400497 return true;
498}
499
Geoff Langf41a7152016-09-19 15:11:17 -0400500} // anonymous namespace
501
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500502bool IsETC2EACFormat(const GLenum format)
503{
504 // ES 3.1, Table 8.19
505 switch (format)
506 {
507 case GL_COMPRESSED_R11_EAC:
508 case GL_COMPRESSED_SIGNED_R11_EAC:
509 case GL_COMPRESSED_RG11_EAC:
510 case GL_COMPRESSED_SIGNED_RG11_EAC:
511 case GL_COMPRESSED_RGB8_ETC2:
512 case GL_COMPRESSED_SRGB8_ETC2:
513 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
514 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
515 case GL_COMPRESSED_RGBA8_ETC2_EAC:
516 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
517 return true;
518
519 default:
520 return false;
521 }
522}
523
Jamie Madill5b772312018-03-08 20:28:32 -0500524bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400525{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800526 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400527 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800528 case TextureType::_2D:
529 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800530 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400531
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800532 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400533 return context->getExtensions().textureRectangle;
534
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800535 case TextureType::_3D:
536 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800537 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500538
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800539 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800540 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400541
He Yunchaoced53ae2016-11-29 15:00:51 +0800542 default:
543 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500544 }
Jamie Madill35d15012013-10-07 10:46:37 -0400545}
546
Jamie Madill5b772312018-03-08 20:28:32 -0500547bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500548{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800549 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500550 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800551 case TextureType::_2D:
552 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500553 return true;
554
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800555 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400556 return context->getExtensions().textureRectangle;
557
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500558 default:
559 return false;
560 }
561}
562
Jamie Madill5b772312018-03-08 20:28:32 -0500563bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500564{
565 switch (target)
566 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800567 case TextureType::_3D:
568 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300569 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500570
571 default:
572 return false;
573 }
574}
575
Ian Ewellbda75592016-04-18 17:25:54 -0400576// Most texture GL calls are not compatible with external textures, so we have a separate validation
577// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500578bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400579{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800580 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400581 (context->getExtensions().eglImageExternal ||
582 context->getExtensions().eglStreamConsumerExternal);
583}
584
Shannon Woods4dfed832014-03-17 20:03:39 -0400585// This function differs from ValidTextureTarget in that the target must be
586// usable as the destination of a 2D operation-- so a cube face is valid, but
587// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400588// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500589bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400590{
591 switch (target)
592 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800593 case TextureTarget::_2D:
594 case TextureTarget::CubeMapNegativeX:
595 case TextureTarget::CubeMapNegativeY:
596 case TextureTarget::CubeMapNegativeZ:
597 case TextureTarget::CubeMapPositiveX:
598 case TextureTarget::CubeMapPositiveY:
599 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800600 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800601 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400602 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800603 default:
604 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500605 }
606}
607
Jamie Madill5b772312018-03-08 20:28:32 -0500608bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -0400609 GLenum mode,
610 GLsizei count,
611 GLenum type,
612 const GLvoid *indices,
613 GLsizei primcount)
614{
615 if (primcount < 0)
616 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700617 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400618 return false;
619 }
620
621 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
622 {
623 return false;
624 }
625
Jamie Madill9fdaa492018-02-16 10:52:11 -0500626 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400627}
628
629bool ValidateDrawArraysInstancedBase(Context *context,
630 GLenum mode,
631 GLint first,
632 GLsizei count,
633 GLsizei primcount)
634{
635 if (primcount < 0)
636 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700637 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400638 return false;
639 }
640
641 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
642 {
643 return false;
644 }
645
Jamie Madill9fdaa492018-02-16 10:52:11 -0500646 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400647}
648
Jamie Madill5b772312018-03-08 20:28:32 -0500649bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400650{
651 // Verify there is at least one active attribute with a divisor of zero
652 const State &state = context->getGLState();
653
654 Program *program = state.getProgram();
655
656 const auto &attribs = state.getVertexArray()->getVertexAttributes();
657 const auto &bindings = state.getVertexArray()->getVertexBindings();
658 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
659 {
660 const VertexAttribute &attrib = attribs[attributeIndex];
661 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300662 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400663 {
664 return true;
665 }
666 }
667
Brandon Jonesafa75152017-07-21 13:11:29 -0700668 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400669 return false;
670}
671
Jamie Madill5b772312018-03-08 20:28:32 -0500672bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500673{
674 switch (target)
675 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800676 case TextureType::_3D:
677 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800678 return true;
679 default:
680 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400681 }
682}
683
Jamie Madill5b772312018-03-08 20:28:32 -0500684bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800685{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800686 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800687 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800688 case TextureType::_2D:
689 case TextureType::_2DArray:
690 case TextureType::_2DMultisample:
691 case TextureType::CubeMap:
692 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800693 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800694 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400695 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800696 default:
697 return false;
698 }
699}
700
Jamie Madill5b772312018-03-08 20:28:32 -0500701bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500702{
He Yunchaoced53ae2016-11-29 15:00:51 +0800703 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
704 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400705 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500706
707 switch (target)
708 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800709 case GL_FRAMEBUFFER:
710 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400711
He Yunchaoced53ae2016-11-29 15:00:51 +0800712 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800713 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400714 return (context->getExtensions().framebufferBlit ||
715 context->getClientMajorVersion() >= 3);
716
He Yunchaoced53ae2016-11-29 15:00:51 +0800717 default:
718 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500719 }
720}
721
Jamie Madill5b772312018-03-08 20:28:32 -0500722bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400723{
Jamie Madillc29968b2016-01-20 11:17:23 -0500724 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400725 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800726 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400727 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800728 case TextureType::_2D:
729 case TextureType::_2DArray:
730 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500731 maxDimension = caps.max2DTextureSize;
732 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800733 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800734 maxDimension = caps.maxCubeMapTextureSize;
735 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800736 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400737 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800738 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800739 maxDimension = caps.max3DTextureSize;
740 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800741 default:
742 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400743 }
744
Brandon Jones6cad5662017-06-14 13:25:13 -0700745 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400746}
747
Jamie Madill5b772312018-03-08 20:28:32 -0500748bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800749 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700750 GLint level,
751 GLsizei width,
752 GLsizei height,
753 GLsizei depth,
754 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400755{
Brandon Jones6cad5662017-06-14 13:25:13 -0700756 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400757 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700758 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400759 return false;
760 }
Austin Kinross08528e12015-10-07 16:24:40 -0700761 // TexSubImage parameters can be NPOT without textureNPOT extension,
762 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500763 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500764 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500765 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400766 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400767 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700768 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400769 return false;
770 }
771
772 if (!ValidMipLevel(context, target, level))
773 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700774 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400775 return false;
776 }
777
778 return true;
779}
780
Geoff Lang966c9402017-04-18 12:38:27 -0400781bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
782{
783 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
784 (size % blockSize == 0);
785}
786
Jamie Madill5b772312018-03-08 20:28:32 -0500787bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500788 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400789 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500790 GLsizei width,
791 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400792{
Geoff Langca271392017-04-05 12:30:00 -0400793 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400794 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400795 {
796 return false;
797 }
798
Geoff Lang966c9402017-04-18 12:38:27 -0400799 if (width < 0 || height < 0)
800 {
801 return false;
802 }
803
804 if (CompressedTextureFormatRequiresExactSize(internalFormat))
805 {
806 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
807 // block size for level 0 but WebGL disallows this.
808 bool smallerThanBlockSizeAllowed =
809 level > 0 || !context->getExtensions().webglCompatibility;
810
811 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
812 smallerThanBlockSizeAllowed) ||
813 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
814 smallerThanBlockSizeAllowed))
815 {
816 return false;
817 }
818 }
819
820 return true;
821}
822
Jamie Madill5b772312018-03-08 20:28:32 -0500823bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400824 GLenum internalFormat,
825 GLint xoffset,
826 GLint yoffset,
827 GLsizei width,
828 GLsizei height,
829 size_t textureWidth,
830 size_t textureHeight)
831{
832 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
833 if (!formatInfo.compressed)
834 {
835 return false;
836 }
837
Geoff Lang44ff5a72017-02-03 15:15:43 -0500838 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400839 {
840 return false;
841 }
842
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500843 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400844 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500845 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400846 yoffset % formatInfo.compressedBlockHeight != 0)
847 {
848 return false;
849 }
850
851 // Allowed to either have data that is a multiple of block size or is smaller than the block
852 // size but fills the entire mip
853 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
854 static_cast<size_t>(width) == textureWidth &&
855 static_cast<size_t>(height) == textureHeight;
856 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
857 (height % formatInfo.compressedBlockHeight) == 0;
858 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400859 {
860 return false;
861 }
862 }
863
Geoff Langd4f180b2013-09-24 13:57:44 -0400864 return true;
865}
866
Jamie Madill5b772312018-03-08 20:28:32 -0500867bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800868 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400869 GLsizei width,
870 GLsizei height,
871 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400872 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400873 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400874 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400875 GLsizei imageSize)
876{
Corentin Wallez336129f2017-10-17 15:55:40 -0400877 gl::Buffer *pixelUnpackBuffer =
878 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400879 if (pixelUnpackBuffer == nullptr && imageSize < 0)
880 {
881 // Checks are not required
882 return true;
883 }
884
885 // ...the data would be unpacked from the buffer object such that the memory reads required
886 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400887 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
888 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400889 const gl::Extents size(width, height, depth);
890 const auto &unpack = context->getGLState().getUnpackState();
891
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800892 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Geoff Langff5b2d52016-09-07 11:32:23 -0400893 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
894 if (endByteOrErr.isError())
895 {
896 context->handleError(endByteOrErr.getError());
897 return false;
898 }
899
900 GLuint endByte = endByteOrErr.getResult();
901
902 if (pixelUnpackBuffer)
903 {
904 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
905 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
906 checkedEndByte += checkedOffset;
907
908 if (!checkedEndByte.IsValid() ||
909 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
910 {
911 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500912 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -0400913 return false;
914 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800915 if (context->getExtensions().webglCompatibility &&
916 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
917 {
918 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
919 PixelUnpackBufferBoundForTransformFeedback);
920 return false;
921 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400922 }
923 else
924 {
925 ASSERT(imageSize >= 0);
926 if (pixels == nullptr && imageSize != 0)
927 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500928 context->handleError(InvalidOperation()
929 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400930 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400931 }
932
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400933 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400934 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500935 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400936 return false;
937 }
938 }
939
940 return true;
941}
942
Geoff Lang37dde692014-01-31 16:34:54 -0500943bool ValidQueryType(const Context *context, GLenum queryType)
944{
He Yunchaoced53ae2016-11-29 15:00:51 +0800945 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
946 "GL extension enums not equal.");
947 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
948 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -0500949
950 switch (queryType)
951 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800952 case GL_ANY_SAMPLES_PASSED:
953 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400954 return context->getClientMajorVersion() >= 3 ||
955 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +0800956 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
957 return (context->getClientMajorVersion() >= 3);
958 case GL_TIME_ELAPSED_EXT:
959 return context->getExtensions().disjointTimerQuery;
960 case GL_COMMANDS_COMPLETED_CHROMIUM:
961 return context->getExtensions().syncQuery;
962 default:
963 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500964 }
965}
966
Jamie Madill5b772312018-03-08 20:28:32 -0500967bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400968 GLenum type,
969 GLboolean normalized,
970 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400971 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400972 bool pureInteger)
973{
974 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400975 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
976 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
977 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
978 // parameter exceeds 255.
979 constexpr GLsizei kMaxWebGLStride = 255;
980 if (stride > kMaxWebGLStride)
981 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500982 context->handleError(InvalidValue()
983 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -0400984 return false;
985 }
986
987 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
988 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
989 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
990 // or an INVALID_OPERATION error is generated.
991 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
992 size_t typeSize = GetVertexFormatTypeSize(internalType);
993
994 ASSERT(isPow2(typeSize) && typeSize > 0);
995 size_t sizeMask = (typeSize - 1);
996 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
997 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700998 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400999 return false;
1000 }
1001
1002 if ((stride & sizeMask) != 0)
1003 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001004 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001005 return false;
1006 }
1007
1008 return true;
1009}
1010
Jamie Madill5b772312018-03-08 20:28:32 -05001011Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001012{
He Yunchaoced53ae2016-11-29 15:00:51 +08001013 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1014 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1015 // or program object and INVALID_OPERATION if the provided name identifies an object
1016 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001017
Dian Xiang769769a2015-09-09 15:20:08 -07001018 Program *validProgram = context->getProgram(id);
1019
1020 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001021 {
Dian Xiang769769a2015-09-09 15:20:08 -07001022 if (context->getShader(id))
1023 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001024 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001025 }
1026 else
1027 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001028 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001029 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001030 }
Dian Xiang769769a2015-09-09 15:20:08 -07001031
1032 return validProgram;
1033}
1034
Jamie Madill5b772312018-03-08 20:28:32 -05001035Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001036{
1037 // See ValidProgram for spec details.
1038
1039 Shader *validShader = context->getShader(id);
1040
1041 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001042 {
Dian Xiang769769a2015-09-09 15:20:08 -07001043 if (context->getProgram(id))
1044 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001045 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001046 }
1047 else
1048 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001049 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001050 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001051 }
Dian Xiang769769a2015-09-09 15:20:08 -07001052
1053 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001054}
1055
Geoff Langb1196682014-07-23 13:47:29 -04001056bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001057{
Geoff Langfa125c92017-10-24 13:01:46 -04001058 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001059 {
Geoff Langfa125c92017-10-24 13:01:46 -04001060 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1061 {
1062 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1063 return false;
1064 }
Jamie Madillb4472272014-07-03 10:38:55 -04001065
Geoff Langfa125c92017-10-24 13:01:46 -04001066 // Color attachment 0 is validated below because it is always valid
1067 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001068 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001069 {
Geoff Langfa125c92017-10-24 13:01:46 -04001070 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001071 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001072 }
1073 }
1074 else
1075 {
1076 switch (attachment)
1077 {
Geoff Langfa125c92017-10-24 13:01:46 -04001078 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001079 case GL_DEPTH_ATTACHMENT:
1080 case GL_STENCIL_ATTACHMENT:
1081 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001082
He Yunchaoced53ae2016-11-29 15:00:51 +08001083 case GL_DEPTH_STENCIL_ATTACHMENT:
1084 if (!context->getExtensions().webglCompatibility &&
1085 context->getClientMajorVersion() < 3)
1086 {
Geoff Langfa125c92017-10-24 13:01:46 -04001087 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001088 return false;
1089 }
1090 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001091
He Yunchaoced53ae2016-11-29 15:00:51 +08001092 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001093 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001094 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001095 }
1096 }
1097
1098 return true;
1099}
1100
Jamie Madill5b772312018-03-08 20:28:32 -05001101bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001102 GLenum target,
1103 GLsizei samples,
1104 GLenum internalformat,
1105 GLsizei width,
1106 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001107{
1108 switch (target)
1109 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001110 case GL_RENDERBUFFER:
1111 break;
1112 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001113 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001114 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001115 }
1116
1117 if (width < 0 || height < 0 || samples < 0)
1118 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001119 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001120 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001121 }
1122
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001123 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1124 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1125
1126 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001127 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001128 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001129 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001130 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001131 }
1132
1133 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1134 // 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 -08001135 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001136 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1137 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001138 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001139 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001140 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001141 }
1142
Geoff Langaae65a42014-05-26 12:43:44 -04001143 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001144 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001145 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001146 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001147 }
1148
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001149 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001150 if (handle == 0)
1151 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001152 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001153 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001154 }
1155
1156 return true;
1157}
1158
He Yunchaoced53ae2016-11-29 15:00:51 +08001159bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1160 GLenum target,
1161 GLenum attachment,
1162 GLenum renderbuffertarget,
1163 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001164{
Geoff Lange8afa902017-09-27 15:00:43 -04001165 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001166 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001167 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001168 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001169 }
1170
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001171 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001172
Jamie Madill84115c92015-04-23 15:00:07 -04001173 ASSERT(framebuffer);
1174 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001175 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001176 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001177 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001178 }
1179
Jamie Madillb4472272014-07-03 10:38:55 -04001180 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001181 {
Jamie Madillb4472272014-07-03 10:38:55 -04001182 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001183 }
1184
Jamie Madillab9d82c2014-01-21 16:38:14 -05001185 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1186 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1187 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1188 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1189 if (renderbuffer != 0)
1190 {
1191 if (!context->getRenderbuffer(renderbuffer))
1192 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001193 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001194 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001195 }
1196 }
1197
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001198 return true;
1199}
1200
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001201bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001202 GLint srcX0,
1203 GLint srcY0,
1204 GLint srcX1,
1205 GLint srcY1,
1206 GLint dstX0,
1207 GLint dstY0,
1208 GLint dstX1,
1209 GLint dstY1,
1210 GLbitfield mask,
1211 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001212{
1213 switch (filter)
1214 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001215 case GL_NEAREST:
1216 break;
1217 case GL_LINEAR:
1218 break;
1219 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001220 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001221 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001222 }
1223
1224 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1225 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001226 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001227 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001228 }
1229
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001230 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1231 // color buffer, leaving only nearest being unfiltered from above
1232 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1233 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001234 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001235 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001236 }
1237
Jamie Madill51f40ec2016-06-15 14:06:00 -04001238 const auto &glState = context->getGLState();
1239 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1240 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001241
1242 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001243 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001244 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001245 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001246 }
1247
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001248 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001249 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001250 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001251 return false;
1252 }
1253
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001254 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001255 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001256 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001257 return false;
1258 }
1259
Qin Jiajiaaef92162018-02-27 13:51:44 +08001260 if (readFramebuffer->id() == drawFramebuffer->id())
1261 {
1262 context->handleError(InvalidOperation());
1263 return false;
1264 }
1265
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001266 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001267 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001268 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001269 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001270 }
1271
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001272 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1273
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001274 if (mask & GL_COLOR_BUFFER_BIT)
1275 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001276 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001277 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001278
He Yunchao66a41a22016-12-15 16:45:05 +08001279 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001280 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001281 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001282
Geoff Langa15472a2015-08-11 11:48:03 -04001283 for (size_t drawbufferIdx = 0;
1284 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001285 {
Geoff Langa15472a2015-08-11 11:48:03 -04001286 const FramebufferAttachment *attachment =
1287 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1288 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001289 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001290 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001291
Geoff Langb2f3d052013-08-13 12:49:27 -04001292 // The GL ES 3.0.2 spec (pg 193) states that:
1293 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001294 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1295 // as well
1296 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1297 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001298 // Changes with EXT_color_buffer_float:
1299 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001300 GLenum readComponentType = readFormat.info->componentType;
1301 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001302 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001303 readComponentType == GL_SIGNED_NORMALIZED);
1304 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1305 drawComponentType == GL_SIGNED_NORMALIZED);
1306
1307 if (extensions.colorBufferFloat)
1308 {
1309 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1310 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1311
1312 if (readFixedOrFloat != drawFixedOrFloat)
1313 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001314 context->handleError(InvalidOperation()
1315 << "If the read buffer contains fixed-point or "
1316 "floating-point values, the draw buffer must "
1317 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001318 return false;
1319 }
1320 }
1321 else if (readFixedPoint != drawFixedPoint)
1322 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001323 context->handleError(InvalidOperation()
1324 << "If the read buffer contains fixed-point values, "
1325 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001326 return false;
1327 }
1328
1329 if (readComponentType == GL_UNSIGNED_INT &&
1330 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001331 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001332 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001333 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001334 }
1335
Jamie Madill6163c752015-12-07 16:32:59 -05001336 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001337 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001338 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001339 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001340 }
1341
Jamie Madilla3944d42016-07-22 22:13:26 -04001342 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001343 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001344 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001345 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001346 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001347 }
Geoff Lange4915782017-04-12 15:19:07 -04001348
1349 if (context->getExtensions().webglCompatibility &&
1350 *readColorBuffer == *attachment)
1351 {
1352 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001353 InvalidOperation()
1354 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001355 return false;
1356 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001357 }
1358 }
1359
Jamie Madilla3944d42016-07-22 22:13:26 -04001360 if ((readFormat.info->componentType == GL_INT ||
1361 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1362 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001363 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001364 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001365 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001366 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001367 }
He Yunchao66a41a22016-12-15 16:45:05 +08001368 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1369 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1370 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1371 // situation is an application error that would lead to a crash in ANGLE.
1372 else if (drawFramebuffer->hasEnabledDrawBuffer())
1373 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001374 context->handleError(
1375 InvalidOperation()
1376 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001377 return false;
1378 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001379 }
1380
He Yunchaoced53ae2016-11-29 15:00:51 +08001381 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001382 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1383 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001384 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001385 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001386 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001387 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001388 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001389 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001390 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001391
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001392 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001393 {
Kenneth Russell69382852017-07-21 16:38:44 -04001394 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001395 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001396 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001397 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001398 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001399
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001400 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001401 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001402 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001403 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001404 }
Geoff Lange4915782017-04-12 15:19:07 -04001405
1406 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1407 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001408 context->handleError(
1409 InvalidOperation()
1410 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001411 return false;
1412 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001413 }
He Yunchao66a41a22016-12-15 16:45:05 +08001414 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1415 else if (drawBuffer)
1416 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001417 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1418 "depth/stencil attachment of a "
1419 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001420 return false;
1421 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001422 }
1423 }
1424
Martin Radeva3ed4572017-07-27 18:29:37 +03001425 // ANGLE_multiview, Revision 1:
1426 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1427 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1428 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1429 {
1430 context->handleError(InvalidFramebufferOperation()
1431 << "Attempt to read from a multi-view framebuffer.");
1432 return false;
1433 }
1434 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1435 {
1436 context->handleError(InvalidFramebufferOperation()
1437 << "Attempt to write to a multi-view framebuffer.");
1438 return false;
1439 }
1440
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001441 return true;
1442}
1443
Jamie Madill4928b7c2017-06-20 12:57:39 -04001444bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001445 GLint x,
1446 GLint y,
1447 GLsizei width,
1448 GLsizei height,
1449 GLenum format,
1450 GLenum type,
1451 GLsizei bufSize,
1452 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001453 GLsizei *columns,
1454 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001455 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001456{
1457 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001458 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001459 return false;
1460 }
1461
Geoff Lang62fce5b2016-09-30 10:46:35 -04001462 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001463 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001464 {
Geoff Langb1196682014-07-23 13:47:29 -04001465 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001466 }
1467
Geoff Lang62fce5b2016-09-30 10:46:35 -04001468 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001469 {
Geoff Langb1196682014-07-23 13:47:29 -04001470 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001471 }
1472
Jamie Madillc29968b2016-01-20 11:17:23 -05001473 return true;
1474}
1475
1476bool ValidateReadnPixelsEXT(Context *context,
1477 GLint x,
1478 GLint y,
1479 GLsizei width,
1480 GLsizei height,
1481 GLenum format,
1482 GLenum type,
1483 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001484 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001485{
1486 if (bufSize < 0)
1487 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001488 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001489 return false;
1490 }
1491
Geoff Lang62fce5b2016-09-30 10:46:35 -04001492 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001493 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001494}
Jamie Madill26e91952014-03-05 15:01:27 -05001495
Jamie Madill4928b7c2017-06-20 12:57:39 -04001496bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001497 GLint x,
1498 GLint y,
1499 GLsizei width,
1500 GLsizei height,
1501 GLenum format,
1502 GLenum type,
1503 GLsizei bufSize,
1504 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001505 GLsizei *columns,
1506 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001507 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001508{
1509 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001510 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001511 return false;
1512 }
1513
Geoff Lange93daba2017-03-30 13:54:40 -04001514 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1515 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001516 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001517 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001518 }
1519
Geoff Lang62fce5b2016-09-30 10:46:35 -04001520 if (!ValidateRobustBufferSize(context, bufSize, *length))
1521 {
1522 return false;
1523 }
1524
1525 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001526}
1527
Jamie Madillf0e04492017-08-26 15:28:42 -04001528bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001529{
1530 if (!context->getExtensions().occlusionQueryBoolean &&
1531 !context->getExtensions().disjointTimerQuery)
1532 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001533 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001534 return false;
1535 }
1536
Olli Etuaho41997e72016-03-10 13:38:39 +02001537 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001538}
1539
Jamie Madillf0e04492017-08-26 15:28:42 -04001540bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001541{
1542 if (!context->getExtensions().occlusionQueryBoolean &&
1543 !context->getExtensions().disjointTimerQuery)
1544 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001545 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001546 return false;
1547 }
1548
Olli Etuaho41997e72016-03-10 13:38:39 +02001549 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001550}
1551
Jamie Madillf0e04492017-08-26 15:28:42 -04001552bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1553{
1554 if (!context->getExtensions().occlusionQueryBoolean &&
1555 !context->getExtensions().disjointTimerQuery)
1556 {
1557 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1558 return false;
1559 }
1560
1561 return true;
1562}
1563
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001564bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001565{
1566 if (!ValidQueryType(context, target))
1567 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001568 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001569 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001570 }
1571
1572 if (id == 0)
1573 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001574 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001575 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001576 }
1577
1578 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1579 // of zero, if the active query object name for <target> is non-zero (for the
1580 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1581 // the active query for either target is non-zero), if <id> is the name of an
1582 // existing query object whose type does not match <target>, or if <id> is the
1583 // active query object name for any query type, the error INVALID_OPERATION is
1584 // generated.
1585
1586 // Ensure no other queries are active
1587 // NOTE: If other queries than occlusion are supported, we will need to check
1588 // separately that:
1589 // a) The query ID passed is not the current active query for any target/type
1590 // b) There are no active queries for the requested target (and in the case
1591 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1592 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001593
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001594 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001595 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001596 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001597 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001598 }
1599
1600 Query *queryObject = context->getQuery(id, true, target);
1601
1602 // check that name was obtained with glGenQueries
1603 if (!queryObject)
1604 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001605 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001606 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001607 }
1608
1609 // check for type mismatch
1610 if (queryObject->getType() != target)
1611 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001612 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001613 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001614 }
1615
1616 return true;
1617}
1618
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001619bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1620{
1621 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001622 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001623 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001624 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001625 return false;
1626 }
1627
1628 return ValidateBeginQueryBase(context, target, id);
1629}
1630
1631bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001632{
1633 if (!ValidQueryType(context, target))
1634 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001635 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001636 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001637 }
1638
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001639 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001640
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001641 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001642 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001643 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001644 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001645 }
1646
Jamie Madill45c785d2014-05-13 14:09:34 -04001647 return true;
1648}
1649
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001650bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1651{
1652 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001653 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001654 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001655 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001656 return false;
1657 }
1658
1659 return ValidateEndQueryBase(context, target);
1660}
1661
1662bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1663{
1664 if (!context->getExtensions().disjointTimerQuery)
1665 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001666 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001667 return false;
1668 }
1669
1670 if (target != GL_TIMESTAMP_EXT)
1671 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001672 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001673 return false;
1674 }
1675
1676 Query *queryObject = context->getQuery(id, true, target);
1677 if (queryObject == nullptr)
1678 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001679 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001680 return false;
1681 }
1682
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001683 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001684 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001685 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001686 return false;
1687 }
1688
1689 return true;
1690}
1691
Geoff Lang2186c382016-10-14 10:54:54 -04001692bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001693{
Geoff Lang2186c382016-10-14 10:54:54 -04001694 if (numParams)
1695 {
1696 *numParams = 0;
1697 }
1698
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001699 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1700 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001701 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001702 return false;
1703 }
1704
1705 switch (pname)
1706 {
1707 case GL_CURRENT_QUERY_EXT:
1708 if (target == GL_TIMESTAMP_EXT)
1709 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001710 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001711 return false;
1712 }
1713 break;
1714 case GL_QUERY_COUNTER_BITS_EXT:
1715 if (!context->getExtensions().disjointTimerQuery ||
1716 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1717 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001718 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001719 return false;
1720 }
1721 break;
1722 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001723 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001724 return false;
1725 }
1726
Geoff Lang2186c382016-10-14 10:54:54 -04001727 if (numParams)
1728 {
1729 // All queries return only one value
1730 *numParams = 1;
1731 }
1732
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001733 return true;
1734}
1735
1736bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1737{
1738 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001739 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001740 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001741 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001742 return false;
1743 }
1744
Geoff Lang2186c382016-10-14 10:54:54 -04001745 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001746}
1747
Geoff Lang2186c382016-10-14 10:54:54 -04001748bool ValidateGetQueryivRobustANGLE(Context *context,
1749 GLenum target,
1750 GLenum pname,
1751 GLsizei bufSize,
1752 GLsizei *length,
1753 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001754{
Geoff Lang2186c382016-10-14 10:54:54 -04001755 if (!ValidateRobustEntryPoint(context, bufSize))
1756 {
1757 return false;
1758 }
1759
1760 if (!ValidateGetQueryivBase(context, target, pname, length))
1761 {
1762 return false;
1763 }
1764
1765 if (!ValidateRobustBufferSize(context, bufSize, *length))
1766 {
1767 return false;
1768 }
1769
1770 return true;
1771}
1772
1773bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1774{
1775 if (numParams)
1776 {
1777 *numParams = 0;
1778 }
1779
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001780 Query *queryObject = context->getQuery(id, false, GL_NONE);
1781
1782 if (!queryObject)
1783 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001784 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001785 return false;
1786 }
1787
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001788 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001789 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001790 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001791 return false;
1792 }
1793
1794 switch (pname)
1795 {
1796 case GL_QUERY_RESULT_EXT:
1797 case GL_QUERY_RESULT_AVAILABLE_EXT:
1798 break;
1799
1800 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001801 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001802 return false;
1803 }
1804
Geoff Lang2186c382016-10-14 10:54:54 -04001805 if (numParams)
1806 {
1807 *numParams = 1;
1808 }
1809
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001810 return true;
1811}
1812
1813bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1814{
1815 if (!context->getExtensions().disjointTimerQuery)
1816 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001817 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001818 return false;
1819 }
Geoff Lang2186c382016-10-14 10:54:54 -04001820 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1821}
1822
1823bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1824 GLuint id,
1825 GLenum pname,
1826 GLsizei bufSize,
1827 GLsizei *length,
1828 GLint *params)
1829{
1830 if (!context->getExtensions().disjointTimerQuery)
1831 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001832 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001833 return false;
1834 }
1835
1836 if (!ValidateRobustEntryPoint(context, bufSize))
1837 {
1838 return false;
1839 }
1840
1841 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1842 {
1843 return false;
1844 }
1845
1846 if (!ValidateRobustBufferSize(context, bufSize, *length))
1847 {
1848 return false;
1849 }
1850
1851 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001852}
1853
1854bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1855{
1856 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001857 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001858 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001859 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001860 return false;
1861 }
Geoff Lang2186c382016-10-14 10:54:54 -04001862 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1863}
1864
1865bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1866 GLuint id,
1867 GLenum pname,
1868 GLsizei bufSize,
1869 GLsizei *length,
1870 GLuint *params)
1871{
1872 if (!context->getExtensions().disjointTimerQuery &&
1873 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1874 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001875 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001876 return false;
1877 }
1878
1879 if (!ValidateRobustEntryPoint(context, bufSize))
1880 {
1881 return false;
1882 }
1883
1884 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1885 {
1886 return false;
1887 }
1888
1889 if (!ValidateRobustBufferSize(context, bufSize, *length))
1890 {
1891 return false;
1892 }
1893
1894 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001895}
1896
1897bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1898{
1899 if (!context->getExtensions().disjointTimerQuery)
1900 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001901 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001902 return false;
1903 }
Geoff Lang2186c382016-10-14 10:54:54 -04001904 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1905}
1906
1907bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1908 GLuint id,
1909 GLenum pname,
1910 GLsizei bufSize,
1911 GLsizei *length,
1912 GLint64 *params)
1913{
1914 if (!context->getExtensions().disjointTimerQuery)
1915 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001916 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001917 return false;
1918 }
1919
1920 if (!ValidateRobustEntryPoint(context, bufSize))
1921 {
1922 return false;
1923 }
1924
1925 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1926 {
1927 return false;
1928 }
1929
1930 if (!ValidateRobustBufferSize(context, bufSize, *length))
1931 {
1932 return false;
1933 }
1934
1935 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001936}
1937
1938bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1939{
1940 if (!context->getExtensions().disjointTimerQuery)
1941 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001942 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001943 return false;
1944 }
Geoff Lang2186c382016-10-14 10:54:54 -04001945 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1946}
1947
1948bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1949 GLuint id,
1950 GLenum pname,
1951 GLsizei bufSize,
1952 GLsizei *length,
1953 GLuint64 *params)
1954{
1955 if (!context->getExtensions().disjointTimerQuery)
1956 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001957 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001958 return false;
1959 }
1960
1961 if (!ValidateRobustEntryPoint(context, bufSize))
1962 {
1963 return false;
1964 }
1965
1966 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1967 {
1968 return false;
1969 }
1970
1971 if (!ValidateRobustBufferSize(context, bufSize, *length))
1972 {
1973 return false;
1974 }
1975
1976 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001977}
1978
Jamie Madill5b772312018-03-08 20:28:32 -05001979bool ValidateUniformCommonBase(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08001980 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05001981 GLint location,
1982 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08001983 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05001984{
Jiajia Qin5451d532017-11-16 17:16:34 +08001985 // TODO(Jiajia): Add image uniform check in future.
1986 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05001987 {
Jiajia Qin5451d532017-11-16 17:16:34 +08001988 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05001989 return false;
1990 }
1991
Jiajia Qin5451d532017-11-16 17:16:34 +08001992 if (!program)
1993 {
1994 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
1995 return false;
1996 }
1997
1998 if (!program->isLinked())
1999 {
2000 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2001 return false;
2002 }
2003
2004 if (location == -1)
2005 {
2006 // Silently ignore the uniform command
2007 return false;
2008 }
2009
2010 const auto &uniformLocations = program->getUniformLocations();
2011 size_t castedLocation = static_cast<size_t>(location);
2012 if (castedLocation >= uniformLocations.size())
2013 {
2014 context->handleError(InvalidOperation() << "Invalid uniform location");
2015 return false;
2016 }
2017
2018 const auto &uniformLocation = uniformLocations[castedLocation];
2019 if (uniformLocation.ignored)
2020 {
2021 // Silently ignore the uniform command
2022 return false;
2023 }
2024
2025 if (!uniformLocation.used())
2026 {
2027 context->handleError(InvalidOperation());
2028 return false;
2029 }
2030
2031 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2032
2033 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2034 if (!uniform.isArray() && count > 1)
2035 {
2036 context->handleError(InvalidOperation());
2037 return false;
2038 }
2039
2040 *uniformOut = &uniform;
2041 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002042}
2043
Jamie Madill5b772312018-03-08 20:28:32 -05002044bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002045 GLenum uniformType,
2046 GLsizei count,
2047 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002048{
Jiajia Qin5451d532017-11-16 17:16:34 +08002049 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2050 // It is compatible with INT or BOOL.
2051 // Do these cheap tests first, for a little extra speed.
2052 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002053 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002054 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002055 }
2056
Jiajia Qin5451d532017-11-16 17:16:34 +08002057 if (IsSamplerType(uniformType))
2058 {
2059 // Check that the values are in range.
2060 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2061 for (GLsizei i = 0; i < count; ++i)
2062 {
2063 if (value[i] < 0 || value[i] >= max)
2064 {
2065 context->handleError(InvalidValue() << "sampler uniform value out of range");
2066 return false;
2067 }
2068 }
2069 return true;
2070 }
2071
2072 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2073 return false;
2074}
2075
Jamie Madill5b772312018-03-08 20:28:32 -05002076bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002077{
2078 // Check that the value type is compatible with uniform type.
2079 // Do the cheaper test first, for a little extra speed.
2080 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2081 {
2082 return true;
2083 }
2084
2085 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2086 return false;
2087}
2088
Jamie Madill5b772312018-03-08 20:28:32 -05002089bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002090{
2091 // Check that the value type is compatible with uniform type.
2092 if (valueType == uniformType)
2093 {
2094 return true;
2095 }
2096
2097 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2098 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002099}
2100
Jamie Madill5b772312018-03-08 20:28:32 -05002101bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002102{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002103 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002104 gl::Program *programObject = context->getGLState().getProgram();
2105 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2106 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002107}
2108
Jamie Madill5b772312018-03-08 20:28:32 -05002109bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002110{
2111 const LinkedUniform *uniform = nullptr;
2112 gl::Program *programObject = context->getGLState().getProgram();
2113 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2114 ValidateUniform1ivValue(context, uniform->type, count, value);
2115}
2116
Jamie Madill5b772312018-03-08 20:28:32 -05002117bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002118 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002119 GLint location,
2120 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002121 GLboolean transpose)
2122{
Geoff Lang92019432017-11-20 13:09:34 -05002123 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002124 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002125 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002126 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002127 }
2128
Jamie Madill62d31cb2015-09-11 13:25:51 -04002129 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002130 gl::Program *programObject = context->getGLState().getProgram();
2131 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2132 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002133}
2134
Jamie Madill5b772312018-03-08 20:28:32 -05002135bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002136{
2137 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2138 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002139 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002140 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002141 }
2142
Jamie Madill0af26e12015-03-05 19:54:33 -05002143 const Caps &caps = context->getCaps();
2144
Jamie Madill893ab082014-05-16 16:56:10 -04002145 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2146 {
2147 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2148
Jamie Madill0af26e12015-03-05 19:54:33 -05002149 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002150 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002151 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002152 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002153 }
2154 }
2155
2156 switch (pname)
2157 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002158 case GL_TEXTURE_BINDING_2D:
2159 case GL_TEXTURE_BINDING_CUBE_MAP:
2160 case GL_TEXTURE_BINDING_3D:
2161 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002162 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002163 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002164 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2165 if (!context->getExtensions().textureRectangle)
2166 {
2167 context->handleError(InvalidEnum()
2168 << "ANGLE_texture_rectangle extension not present");
2169 return false;
2170 }
2171 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002172 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2173 if (!context->getExtensions().eglStreamConsumerExternal &&
2174 !context->getExtensions().eglImageExternal)
2175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002176 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2177 "nor GL_OES_EGL_image_external "
2178 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002179 return false;
2180 }
2181 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002182
He Yunchaoced53ae2016-11-29 15:00:51 +08002183 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2184 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002185 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002186 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2187 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002188 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002189 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002190 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002191 }
2192
Jamie Madill51f40ec2016-06-15 14:06:00 -04002193 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2194 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002195
2196 if (framebuffer->getReadBufferState() == GL_NONE)
2197 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002198 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002199 return false;
2200 }
2201
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002202 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002203 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002204 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002205 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002206 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002207 }
2208 }
2209 break;
2210
He Yunchaoced53ae2016-11-29 15:00:51 +08002211 default:
2212 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002213 }
2214
2215 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002216 if (*numParams == 0)
2217 {
2218 return false;
2219 }
2220
2221 return true;
2222}
2223
Jamie Madill5b772312018-03-08 20:28:32 -05002224bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002225 GLenum pname,
2226 GLsizei bufSize,
2227 GLenum *nativeType,
2228 unsigned int *numParams)
2229{
2230 if (!ValidateRobustEntryPoint(context, bufSize))
2231 {
2232 return false;
2233 }
2234
2235 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2236 {
2237 return false;
2238 }
2239
2240 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002241 {
2242 return false;
2243 }
2244
2245 return true;
2246}
2247
Jamie Madill5b772312018-03-08 20:28:32 -05002248bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002249 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002250 GLint level,
2251 GLenum internalformat,
2252 bool isSubImage,
2253 GLint xoffset,
2254 GLint yoffset,
2255 GLint zoffset,
2256 GLint x,
2257 GLint y,
2258 GLsizei width,
2259 GLsizei height,
2260 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002261 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002262{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002263 TextureType texType = TextureTargetToType(target);
2264
Brandon Jones6cad5662017-06-14 13:25:13 -07002265 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002266 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002267 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2268 return false;
2269 }
2270
2271 if (width < 0 || height < 0)
2272 {
2273 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002274 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002275 }
2276
He Yunchaoced53ae2016-11-29 15:00:51 +08002277 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2278 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002279 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002280 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002281 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002282 }
2283
2284 if (border != 0)
2285 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002286 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002287 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002288 }
2289
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002290 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002291 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002292 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002293 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002294 }
2295
Jamie Madill51f40ec2016-06-15 14:06:00 -04002296 const auto &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002297 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002298 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002299 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002300 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002301 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002302 }
2303
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002304 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002305 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002306 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002307 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002308 }
2309
Martin Radev138064f2016-07-15 12:03:41 +03002310 if (readFramebuffer->getReadBufferState() == GL_NONE)
2311 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002312 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002313 return false;
2314 }
2315
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002316 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2317 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002318 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002319 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002320 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2321 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002322 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002323 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002324 return false;
2325 }
2326
Martin Radev04e2c3b2017-07-27 16:54:35 +03002327 // ANGLE_multiview spec, Revision 1:
2328 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2329 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2330 // is not NONE.
2331 if (source->getMultiviewLayout() != GL_NONE)
2332 {
2333 context->handleError(InvalidFramebufferOperation()
2334 << "The active read framebuffer object has multiview attachments.");
2335 return false;
2336 }
2337
Geoff Langaae65a42014-05-26 12:43:44 -04002338 const gl::Caps &caps = context->getCaps();
2339
Geoff Langaae65a42014-05-26 12:43:44 -04002340 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002341 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002342 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002343 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002344 maxDimension = caps.max2DTextureSize;
2345 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002346
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002347 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002348 maxDimension = caps.maxCubeMapTextureSize;
2349 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002350
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002351 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002352 maxDimension = caps.maxRectangleTextureSize;
2353 break;
2354
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002355 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002356 maxDimension = caps.max2DTextureSize;
2357 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002358
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002359 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002360 maxDimension = caps.max3DTextureSize;
2361 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002362
He Yunchaoced53ae2016-11-29 15:00:51 +08002363 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002364 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002365 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002366 }
2367
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002368 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002369 if (!texture)
2370 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002371 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002372 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002373 }
2374
Geoff Lang69cce582015-09-17 13:20:36 -04002375 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002376 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002377 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002378 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002379 }
2380
Geoff Langca271392017-04-05 12:30:00 -04002381 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002382 isSubImage ? *texture->getFormat(target, level).info
2383 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002384
Geoff Lang966c9402017-04-18 12:38:27 -04002385 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002386 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002387 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002388 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002389 }
2390
2391 if (isSubImage)
2392 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002393 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2394 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2395 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002397 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002398 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002399 }
2400 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002401 else
2402 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002403 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002404 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002405 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002406 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002407 }
2408
Geoff Langeb66a6e2016-10-31 13:06:12 -04002409 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002410 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002411 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002412 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002413 }
2414
2415 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002416 if (static_cast<int>(width) > maxLevelDimension ||
2417 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002418 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002419 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002420 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002421 }
2422 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002423
Jamie Madill0c8abca2016-07-22 20:21:26 -04002424 if (textureFormatOut)
2425 {
2426 *textureFormatOut = texture->getFormat(target, level);
2427 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002428
2429 // Detect texture copying feedback loops for WebGL.
2430 if (context->getExtensions().webglCompatibility)
2431 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002432 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002433 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002434 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002435 return false;
2436 }
2437 }
2438
Jamie Madill560a8d82014-05-21 13:06:20 -04002439 return true;
2440}
2441
Jamie Madill5b772312018-03-08 20:28:32 -05002442bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002443{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002444 switch (mode)
2445 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002446 case GL_POINTS:
2447 case GL_LINES:
2448 case GL_LINE_LOOP:
2449 case GL_LINE_STRIP:
2450 case GL_TRIANGLES:
2451 case GL_TRIANGLE_STRIP:
2452 case GL_TRIANGLE_FAN:
2453 break;
2454 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002455 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002456 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002457 }
2458
Jamie Madill250d33f2014-06-06 17:09:03 -04002459 if (count < 0)
2460 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002461 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002462 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002463 }
2464
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002465 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002466
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002467 const Extensions &extensions = context->getExtensions();
2468
2469 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2470 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2471 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2472 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002473 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002474 // Check for mapped buffers
2475 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002476 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002477 {
2478 context->handleError(InvalidOperation());
2479 return false;
2480 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002481 }
2482
Jamie Madillcbcde722017-01-06 14:50:00 -05002483 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2484 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002485 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002486 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002487 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002488 const FramebufferAttachment *dsAttachment =
2489 framebuffer->getStencilOrDepthStencilAttachment();
2490 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002491 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002492 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002493
2494 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2495 bool differentWritemasks =
2496 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2497 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2498 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2499 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2500
2501 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002502 {
Martin Radevffe754b2017-07-31 10:38:07 +03002503 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002504 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002505 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2506 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002507 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002508 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002509 return false;
2510 }
Jamie Madillac528012014-06-20 13:21:23 -04002511 }
2512
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002513 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002514 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002515 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002516 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002517 }
2518
Geoff Lang7dd2e102014-11-10 15:19:26 -05002519 gl::Program *program = state.getProgram();
2520 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002521 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002522 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002523 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002524 }
2525
Yunchao Hecddcb592017-11-13 15:27:35 +08002526 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2527 // vertex shader stage or fragment shader stage is a undefined behaviour.
2528 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2529 // produce undefined result.
Yunchao Heece12532017-11-21 15:50:21 +08002530 if (!program->hasLinkedVertexShader() || !program->hasLinkedFragmentShader())
Yunchao Hecddcb592017-11-13 15:27:35 +08002531 {
2532 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2533 "vertex shader stage or fragment shader stage.");
2534 return false;
2535 }
2536
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002537 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002538 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002539 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002540 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002541 }
2542
Martin Radevffe754b2017-07-31 10:38:07 +03002543 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002544 {
Martin Radevda8e2572017-09-12 17:21:16 +03002545 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002546 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002547 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002548 {
2549 context->handleError(InvalidOperation() << "The number of views in the active program "
2550 "and draw framebuffer does not match.");
2551 return false;
2552 }
Martin Radev7e69f762017-07-27 14:54:13 +03002553
2554 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2555 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2556 framebufferNumViews > 1)
2557 {
2558 context->handleError(InvalidOperation()
2559 << "There is an active transform feedback object "
2560 "when the number of views in the active draw "
2561 "framebuffer is greater than 1.");
2562 return false;
2563 }
Martin Radevffe754b2017-07-31 10:38:07 +03002564
2565 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2566 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2567 {
2568 context->handleError(InvalidOperation() << "There is an active query for target "
2569 "GL_TIME_ELAPSED_EXT when the number of "
2570 "views in the active draw framebuffer is "
2571 "greater than 1.");
2572 return false;
2573 }
Martin Radev7cf61662017-07-26 17:10:53 +03002574 }
2575
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002576 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002577 for (unsigned int uniformBlockIndex = 0;
2578 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002579 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002580 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002581 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002582 const OffsetBindingPointer<Buffer> &uniformBuffer =
2583 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002584
Geoff Lang5d124a62015-09-15 13:03:27 -04002585 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002586 {
2587 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002588 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002589 InvalidOperation()
2590 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002591 return false;
2592 }
2593
Geoff Lang5d124a62015-09-15 13:03:27 -04002594 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002595 if (uniformBufferSize == 0)
2596 {
2597 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002598 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002599 }
2600
Jamie Madill62d31cb2015-09-11 13:25:51 -04002601 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002602 {
2603 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002604 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002605 InvalidOperation()
2606 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002607 return false;
2608 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002609
2610 if (extensions.webglCompatibility &&
2611 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2612 {
2613 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2614 UniformBufferBoundForTransformFeedback);
2615 return false;
2616 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002617 }
2618
Geoff Lange0cff192017-05-30 13:04:56 -04002619 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002620 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002621 {
James Darpiniane8a93c62018-01-04 18:02:24 -08002622 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2623 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2624 transformFeedbackObject->buffersBoundForOtherUse())
2625 {
2626 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferDoubleBound);
2627 return false;
2628 }
Geoff Lange0cff192017-05-30 13:04:56 -04002629 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002630 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2631 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002632 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002633 return false;
2634 }
Geoff Lange0cff192017-05-30 13:04:56 -04002635
Geoff Lang9ab5b822017-05-30 16:19:23 -04002636 // Detect that the vertex shader input types match the attribute types
2637 if (!ValidateVertexShaderAttributeTypeMatch(context))
2638 {
2639 return false;
2640 }
2641
Geoff Lange0cff192017-05-30 13:04:56 -04002642 // Detect that the color buffer types match the fragment shader output types
2643 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2644 {
2645 return false;
2646 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002647 }
2648
Jamie Madill9fdaa492018-02-16 10:52:11 -05002649 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002650}
2651
Jamie Madill5b772312018-03-08 20:28:32 -05002652bool ValidateDrawArraysCommon(Context *context,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002653 GLenum mode,
2654 GLint first,
2655 GLsizei count,
2656 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002657{
Jamie Madillfd716582014-06-06 17:09:04 -04002658 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002659 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002660 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002661 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002662 }
2663
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002664 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002665 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002666 if (curTransformFeedback && curTransformFeedback->isActive() &&
2667 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002668 {
2669 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002670 // that does not match the current transform feedback object's draw mode (if transform
2671 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002672 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002673 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002674 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002675 }
2676
Jiajia Qind9671222016-11-29 16:30:31 +08002677 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002678 {
2679 return false;
2680 }
2681
Corentin Wallez71168a02016-12-19 15:11:18 -08002682 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002683 // - first < 0 has been checked as an error condition.
2684 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002685 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002686 ASSERT(first >= 0);
2687 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002688 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002689 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2690 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2691 {
2692 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2693 return false;
2694 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002695
Jamie Madill9fdaa492018-02-16 10:52:11 -05002696 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2697 {
2698 return false;
2699 }
Jamie Madillfd716582014-06-06 17:09:04 -04002700 }
2701
2702 return true;
2703}
2704
He Yunchaoced53ae2016-11-29 15:00:51 +08002705bool ValidateDrawArraysInstancedANGLE(Context *context,
2706 GLenum mode,
2707 GLint first,
2708 GLsizei count,
2709 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002710{
Geoff Lang63c5a592017-09-27 14:08:16 -04002711 if (!context->getExtensions().instancedArrays)
2712 {
2713 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2714 return false;
2715 }
2716
Corentin Wallez170efbf2017-05-02 13:45:01 -04002717 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002718 {
2719 return false;
2720 }
2721
Corentin Wallez0dc97812017-06-22 14:38:44 -04002722 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002723}
2724
Jamie Madill5b772312018-03-08 20:28:32 -05002725bool ValidateDrawElementsBase(Context *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002726{
Jamie Madill250d33f2014-06-06 17:09:03 -04002727 switch (type)
2728 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002729 case GL_UNSIGNED_BYTE:
2730 case GL_UNSIGNED_SHORT:
2731 break;
2732 case GL_UNSIGNED_INT:
2733 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2734 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002735 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002736 return false;
2737 }
2738 break;
2739 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002740 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002741 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002742 }
2743
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002744 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002745
2746 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002747 if (curTransformFeedback && curTransformFeedback->isActive() &&
2748 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002749 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002750 // It is an invalid operation to call DrawElements, DrawRangeElements or
2751 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002752 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002753 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002754 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002755 }
2756
Jiajia Qind9671222016-11-29 16:30:31 +08002757 return true;
2758}
2759
Jamie Madill5b772312018-03-08 20:28:32 -05002760bool ValidateDrawElementsCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002761 GLenum mode,
2762 GLsizei count,
2763 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002764 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002765 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002766{
2767 if (!ValidateDrawElementsBase(context, type))
2768 return false;
2769
2770 const State &state = context->getGLState();
2771
Corentin Wallez170efbf2017-05-02 13:45:01 -04002772 if (!ValidateDrawBase(context, mode, count))
2773 {
2774 return false;
2775 }
2776
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002777 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2778 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2779 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2780 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002781 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002782 // Check for mapped buffers
2783 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002784 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002785 {
2786 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2787 return false;
2788 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002789 }
2790
He Yunchaoced53ae2016-11-29 15:00:51 +08002791 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002792 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002793
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002794 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2795
2796 if (context->getExtensions().webglCompatibility)
2797 {
2798 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2799 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2800 {
2801 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2802 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2803 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002804 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002805 return false;
2806 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002807
2808 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2809 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2810 // error is generated.
2811 if (reinterpret_cast<intptr_t>(indices) < 0)
2812 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002813 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002814 return false;
2815 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002816 }
2817
2818 if (context->getExtensions().webglCompatibility ||
2819 !context->getGLState().areClientArraysEnabled())
2820 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002821 if (!elementArrayBuffer && count > 0)
2822 {
2823 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2824 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2825 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002826 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002827 return false;
2828 }
2829 }
2830
Jamie Madill9fdaa492018-02-16 10:52:11 -05002831 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04002832 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002833 // This is an application error that would normally result in a crash, but we catch it and
2834 // return an error
2835 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
2836 return false;
2837 }
2838
2839 if (count > 0 && elementArrayBuffer)
2840 {
2841 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2842 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2843 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2844 constexpr uint64_t kMaxTypeSize = 8;
2845 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2846 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2847 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
2848
2849 uint64_t typeSize = typeBytes;
2850 uint64_t elementCount = static_cast<uint64_t>(count);
2851 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2852
2853 // Doing the multiplication here is overflow-safe
2854 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2855
2856 // The offset can be any value, check for overflows
2857 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2858 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04002859 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002860 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2861 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002862 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05002863
2864 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2865 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002866 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002867 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
2868 return false;
2869 }
2870
2871 ASSERT(isPow2(typeSize) && typeSize > 0);
2872 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
2873 {
2874 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04002875 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002876 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002877
2878 if (context->getExtensions().webglCompatibility &&
2879 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
2880 {
2881 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2882 ElementArrayBufferBoundForTransformFeedback);
2883 return false;
2884 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002885 }
2886
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002887 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002888 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002889 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2890 // access is enabled.
2891 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2892 {
2893 return false;
2894 }
2895 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05002896 else if (count == 0)
2897 {
2898 // ValidateDrawAttribs also does some extra validation that is independent of the vertex
2899 // count.
2900 if (!ValidateDrawAttribs(context, 0, 0, 0))
2901 {
2902 return false;
2903 }
2904 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002905 else
2906 {
2907 // Use the parameter buffer to retrieve and cache the index range.
2908 const auto &params = context->getParams<HasIndexRange>();
2909 const auto &indexRangeOpt = params.getIndexRange();
2910 if (!indexRangeOpt.valid())
2911 {
2912 // Unexpected error.
2913 return false;
2914 }
2915
2916 // If we use an index greater than our maximum supported index range, return an error.
2917 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2918 // return an error if possible here.
2919 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2920 {
2921 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2922 return false;
2923 }
2924
2925 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2926 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2927 {
2928 return false;
2929 }
2930
2931 // No op if there are no real indices in the index data (all are primitive restart).
2932 return (indexRangeOpt.value().vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002933 }
2934
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002935 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002936}
2937
Jamie Madill5b772312018-03-08 20:28:32 -05002938bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002939 GLenum mode,
2940 GLsizei count,
2941 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002942 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002943 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002944{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002945 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002946}
2947
Geoff Lang3edfe032015-09-04 16:38:24 -04002948bool ValidateDrawElementsInstancedANGLE(Context *context,
2949 GLenum mode,
2950 GLsizei count,
2951 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002952 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002953 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002954{
Geoff Lang63c5a592017-09-27 14:08:16 -04002955 if (!context->getExtensions().instancedArrays)
2956 {
2957 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2958 return false;
2959 }
2960
Corentin Wallez170efbf2017-05-02 13:45:01 -04002961 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002962 {
2963 return false;
2964 }
2965
Corentin Wallez0dc97812017-06-22 14:38:44 -04002966 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002967}
2968
He Yunchaoced53ae2016-11-29 15:00:51 +08002969bool ValidateFramebufferTextureBase(Context *context,
2970 GLenum target,
2971 GLenum attachment,
2972 GLuint texture,
2973 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002974{
Geoff Lange8afa902017-09-27 15:00:43 -04002975 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002976 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002977 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002978 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002979 }
2980
2981 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002982 {
2983 return false;
2984 }
2985
Jamie Madill55ec3b12014-07-03 10:38:57 -04002986 if (texture != 0)
2987 {
2988 gl::Texture *tex = context->getTexture(texture);
2989
Luc Ferronadcf0ae2018-01-24 08:27:37 -05002990 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002991 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002992 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002993 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002994 }
2995
2996 if (level < 0)
2997 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002998 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002999 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003000 }
3001 }
3002
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003003 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003004 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003005
Jamie Madill84115c92015-04-23 15:00:07 -04003006 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003007 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003008 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003009 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003010 }
3011
3012 return true;
3013}
3014
Geoff Langb1196682014-07-23 13:47:29 -04003015bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003016{
3017 if (program == 0)
3018 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003019 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003020 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003021 }
3022
Dian Xiang769769a2015-09-09 15:20:08 -07003023 gl::Program *programObject = GetValidProgram(context, program);
3024 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003025 {
3026 return false;
3027 }
3028
Jamie Madill0063c512014-08-25 15:47:53 -04003029 if (!programObject || !programObject->isLinked())
3030 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003031 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003032 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003033 }
3034
Geoff Lang7dd2e102014-11-10 15:19:26 -05003035 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003036 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003037 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003038 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003039 }
3040
Jamie Madill0063c512014-08-25 15:47:53 -04003041 return true;
3042}
3043
Geoff Langf41d0ee2016-10-07 13:04:23 -04003044static bool ValidateSizedGetUniform(Context *context,
3045 GLuint program,
3046 GLint location,
3047 GLsizei bufSize,
3048 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003049{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003050 if (length)
3051 {
3052 *length = 0;
3053 }
3054
Jamie Madill78f41802014-08-25 15:47:55 -04003055 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003056 {
Jamie Madill78f41802014-08-25 15:47:55 -04003057 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003058 }
3059
Geoff Langf41d0ee2016-10-07 13:04:23 -04003060 if (bufSize < 0)
3061 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003062 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003063 return false;
3064 }
3065
Jamie Madilla502c742014-08-28 17:19:13 -04003066 gl::Program *programObject = context->getProgram(program);
3067 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003068
Jamie Madill78f41802014-08-25 15:47:55 -04003069 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003070 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003071 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003072 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003073 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003074 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003075 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003076 }
3077
Geoff Langf41d0ee2016-10-07 13:04:23 -04003078 if (length)
3079 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003080 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003081 }
3082
Jamie Madill0063c512014-08-25 15:47:53 -04003083 return true;
3084}
3085
He Yunchaoced53ae2016-11-29 15:00:51 +08003086bool ValidateGetnUniformfvEXT(Context *context,
3087 GLuint program,
3088 GLint location,
3089 GLsizei bufSize,
3090 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003091{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003092 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003093}
3094
He Yunchaoced53ae2016-11-29 15:00:51 +08003095bool ValidateGetnUniformivEXT(Context *context,
3096 GLuint program,
3097 GLint location,
3098 GLsizei bufSize,
3099 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003100{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003101 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3102}
3103
3104bool ValidateGetUniformfvRobustANGLE(Context *context,
3105 GLuint program,
3106 GLint location,
3107 GLsizei bufSize,
3108 GLsizei *length,
3109 GLfloat *params)
3110{
3111 if (!ValidateRobustEntryPoint(context, bufSize))
3112 {
3113 return false;
3114 }
3115
3116 // bufSize is validated in ValidateSizedGetUniform
3117 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3118}
3119
3120bool ValidateGetUniformivRobustANGLE(Context *context,
3121 GLuint program,
3122 GLint location,
3123 GLsizei bufSize,
3124 GLsizei *length,
3125 GLint *params)
3126{
3127 if (!ValidateRobustEntryPoint(context, bufSize))
3128 {
3129 return false;
3130 }
3131
3132 // bufSize is validated in ValidateSizedGetUniform
3133 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3134}
3135
3136bool ValidateGetUniformuivRobustANGLE(Context *context,
3137 GLuint program,
3138 GLint location,
3139 GLsizei bufSize,
3140 GLsizei *length,
3141 GLuint *params)
3142{
3143 if (!ValidateRobustEntryPoint(context, bufSize))
3144 {
3145 return false;
3146 }
3147
3148 if (context->getClientMajorVersion() < 3)
3149 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003150 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003151 return false;
3152 }
3153
3154 // bufSize is validated in ValidateSizedGetUniform
3155 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003156}
3157
He Yunchaoced53ae2016-11-29 15:00:51 +08003158bool ValidateDiscardFramebufferBase(Context *context,
3159 GLenum target,
3160 GLsizei numAttachments,
3161 const GLenum *attachments,
3162 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003163{
3164 if (numAttachments < 0)
3165 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003166 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003167 return false;
3168 }
3169
3170 for (GLsizei i = 0; i < numAttachments; ++i)
3171 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003172 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003173 {
3174 if (defaultFramebuffer)
3175 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003176 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003177 return false;
3178 }
3179
3180 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3181 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003182 context->handleError(InvalidOperation() << "Requested color attachment is "
3183 "greater than the maximum supported "
3184 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003185 return false;
3186 }
3187 }
3188 else
3189 {
3190 switch (attachments[i])
3191 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003192 case GL_DEPTH_ATTACHMENT:
3193 case GL_STENCIL_ATTACHMENT:
3194 case GL_DEPTH_STENCIL_ATTACHMENT:
3195 if (defaultFramebuffer)
3196 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003197 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3198 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003199 return false;
3200 }
3201 break;
3202 case GL_COLOR:
3203 case GL_DEPTH:
3204 case GL_STENCIL:
3205 if (!defaultFramebuffer)
3206 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003207 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3208 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003209 return false;
3210 }
3211 break;
3212 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003213 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003214 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003215 }
3216 }
3217 }
3218
3219 return true;
3220}
3221
Austin Kinross6ee1e782015-05-29 17:05:37 -07003222bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3223{
Jamie Madill007530e2017-12-28 14:27:04 -05003224 if (!context->getExtensions().debugMarker)
3225 {
3226 // The debug marker calls should not set error state
3227 // However, it seems reasonable to set an error state if the extension is not enabled
3228 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3229 return false;
3230 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003231
Jamie Madill007530e2017-12-28 14:27:04 -05003232 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003233 if (length < 0)
3234 {
3235 return false;
3236 }
3237
3238 if (marker == nullptr)
3239 {
3240 return false;
3241 }
3242
3243 return true;
3244}
3245
3246bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3247{
Jamie Madill007530e2017-12-28 14:27:04 -05003248 if (!context->getExtensions().debugMarker)
3249 {
3250 // The debug marker calls should not set error state
3251 // However, it seems reasonable to set an error state if the extension is not enabled
3252 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3253 return false;
3254 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003255
Jamie Madill007530e2017-12-28 14:27:04 -05003256 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003257 if (length < 0)
3258 {
3259 return false;
3260 }
3261
3262 if (length > 0 && marker == nullptr)
3263 {
3264 return false;
3265 }
3266
3267 return true;
3268}
3269
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003270bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003271{
Geoff Langa8406172015-07-21 16:53:39 -04003272 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3273 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003274 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003275 return false;
3276 }
3277
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003278 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003279 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003280 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003281 if (!context->getExtensions().eglImage)
3282 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003283 context->handleError(InvalidEnum()
3284 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003285 }
3286 break;
3287
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003288 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003289 if (!context->getExtensions().eglImageExternal)
3290 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003291 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3292 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003293 }
Geoff Langa8406172015-07-21 16:53:39 -04003294 break;
3295
3296 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003297 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003298 return false;
3299 }
3300
Jamie Madill007530e2017-12-28 14:27:04 -05003301 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3302
Jamie Madill61e16b42017-06-19 11:13:23 -04003303 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003304 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003305 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003306 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003307 return false;
3308 }
3309
Jamie Madill007530e2017-12-28 14:27:04 -05003310 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003311 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003312 context->handleError(InvalidOperation()
3313 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003314 return false;
3315 }
3316
Geoff Langca271392017-04-05 12:30:00 -04003317 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003318 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003319 if (!textureCaps.texturable)
3320 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003321 context->handleError(InvalidOperation()
3322 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003323 return false;
3324 }
3325
Geoff Langdcab33b2015-07-21 13:03:16 -04003326 return true;
3327}
3328
3329bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003330 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003331 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003332{
Geoff Langa8406172015-07-21 16:53:39 -04003333 if (!context->getExtensions().eglImage)
3334 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003335 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003336 return false;
3337 }
3338
3339 switch (target)
3340 {
3341 case GL_RENDERBUFFER:
3342 break;
3343
3344 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003345 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003346 return false;
3347 }
3348
Jamie Madill007530e2017-12-28 14:27:04 -05003349 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3350
Jamie Madill61e16b42017-06-19 11:13:23 -04003351 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003352 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003353 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003354 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003355 return false;
3356 }
3357
Geoff Langca271392017-04-05 12:30:00 -04003358 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003359 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003360 if (!textureCaps.renderable)
3361 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003362 context->handleError(InvalidOperation()
3363 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003364 return false;
3365 }
3366
Geoff Langdcab33b2015-07-21 13:03:16 -04003367 return true;
3368}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003369
3370bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3371{
Geoff Lang36167ab2015-12-07 10:27:14 -05003372 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003373 {
3374 // The default VAO should always exist
3375 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003376 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003377 return false;
3378 }
3379
3380 return true;
3381}
3382
Geoff Langc5629752015-12-07 16:29:04 -05003383bool ValidateProgramBinaryBase(Context *context,
3384 GLuint program,
3385 GLenum binaryFormat,
3386 const void *binary,
3387 GLint length)
3388{
3389 Program *programObject = GetValidProgram(context, program);
3390 if (programObject == nullptr)
3391 {
3392 return false;
3393 }
3394
3395 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3396 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3397 programBinaryFormats.end())
3398 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003399 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003400 return false;
3401 }
3402
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003403 if (context->hasActiveTransformFeedback(program))
3404 {
3405 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003406 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3407 "is associated with an active transform "
3408 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003409 return false;
3410 }
3411
Geoff Langc5629752015-12-07 16:29:04 -05003412 return true;
3413}
3414
3415bool ValidateGetProgramBinaryBase(Context *context,
3416 GLuint program,
3417 GLsizei bufSize,
3418 GLsizei *length,
3419 GLenum *binaryFormat,
3420 void *binary)
3421{
3422 Program *programObject = GetValidProgram(context, program);
3423 if (programObject == nullptr)
3424 {
3425 return false;
3426 }
3427
3428 if (!programObject->isLinked())
3429 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003430 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003431 return false;
3432 }
3433
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003434 if (context->getCaps().programBinaryFormats.empty())
3435 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003436 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003437 return false;
3438 }
3439
Geoff Langc5629752015-12-07 16:29:04 -05003440 return true;
3441}
Jamie Madillc29968b2016-01-20 11:17:23 -05003442
Jamie Madill5b772312018-03-08 20:28:32 -05003443bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003444{
3445 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003446 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003447 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003448 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3449 return false;
3450 }
3451 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3452 {
3453 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003454 return false;
3455 }
3456
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003457 ASSERT(context->getGLState().getDrawFramebuffer());
3458 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003459 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3460
3461 // This should come first before the check for the default frame buffer
3462 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3463 // rather than INVALID_OPERATION
3464 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3465 {
3466 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3467
3468 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003469 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3470 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003471 {
3472 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003473 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3474 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3475 // 3.1 is still a bit ambiguous about the error, but future specs are
3476 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003477 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003478 return false;
3479 }
3480 else if (bufs[colorAttachment] >= maxColorAttachment)
3481 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003482 context->handleError(InvalidOperation()
3483 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003484 return false;
3485 }
3486 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3487 frameBufferId != 0)
3488 {
3489 // INVALID_OPERATION-GL is bound to buffer and ith argument
3490 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003491 context->handleError(InvalidOperation()
3492 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003493 return false;
3494 }
3495 }
3496
3497 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3498 // and n is not 1 or bufs is bound to value other than BACK and NONE
3499 if (frameBufferId == 0)
3500 {
3501 if (n != 1)
3502 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003503 context->handleError(InvalidOperation()
3504 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003505 return false;
3506 }
3507
3508 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3509 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003510 context->handleError(
3511 InvalidOperation()
3512 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003513 return false;
3514 }
3515 }
3516
3517 return true;
3518}
3519
Geoff Lang496c02d2016-10-20 11:38:11 -07003520bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003521 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003522 GLenum pname,
3523 GLsizei *length,
3524 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003525{
Geoff Lang496c02d2016-10-20 11:38:11 -07003526 if (length)
3527 {
3528 *length = 0;
3529 }
3530
3531 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3532 {
3533 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003534 InvalidOperation()
3535 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003536 return false;
3537 }
3538
Corentin Walleze4477002017-12-01 14:39:58 -05003539 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003540 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003541 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003542 return false;
3543 }
3544
Geoff Lang496c02d2016-10-20 11:38:11 -07003545 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003546 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003547 case GL_BUFFER_MAP_POINTER:
3548 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003549
Geoff Lang496c02d2016-10-20 11:38:11 -07003550 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003551 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003552 return false;
3553 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003554
3555 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3556 // target bound to zero generate an INVALID_OPERATION error."
3557 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003558 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003559 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003560 context->handleError(InvalidOperation()
3561 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003562 return false;
3563 }
3564
Geoff Lang496c02d2016-10-20 11:38:11 -07003565 if (length)
3566 {
3567 *length = 1;
3568 }
3569
Olli Etuaho4f667482016-03-30 15:56:35 +03003570 return true;
3571}
3572
Corentin Wallez336129f2017-10-17 15:55:40 -04003573bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003574{
Corentin Walleze4477002017-12-01 14:39:58 -05003575 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003576 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003577 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003578 return false;
3579 }
3580
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003581 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003582
3583 if (buffer == nullptr || !buffer->isMapped())
3584 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003585 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003586 return false;
3587 }
3588
3589 return true;
3590}
3591
3592bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003593 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003594 GLintptr offset,
3595 GLsizeiptr length,
3596 GLbitfield access)
3597{
Corentin Walleze4477002017-12-01 14:39:58 -05003598 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003599 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003600 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003601 return false;
3602 }
3603
Brandon Jones6cad5662017-06-14 13:25:13 -07003604 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003605 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003606 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3607 return false;
3608 }
3609
3610 if (length < 0)
3611 {
3612 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003613 return false;
3614 }
3615
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003616 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003617
3618 if (!buffer)
3619 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003620 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003621 return false;
3622 }
3623
3624 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003625 CheckedNumeric<size_t> checkedOffset(offset);
3626 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003627
Jamie Madille2e406c2016-06-02 13:04:10 -04003628 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003629 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003630 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003631 return false;
3632 }
3633
3634 // Check for invalid bits in the mask
3635 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3636 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3637 GL_MAP_UNSYNCHRONIZED_BIT;
3638
3639 if (access & ~(allAccessBits))
3640 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003641 context->handleError(InvalidValue()
3642 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003643 return false;
3644 }
3645
3646 if (length == 0)
3647 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003648 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003649 return false;
3650 }
3651
3652 if (buffer->isMapped())
3653 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003654 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003655 return false;
3656 }
3657
3658 // Check for invalid bit combinations
3659 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3660 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003661 context->handleError(InvalidOperation()
3662 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003663 return false;
3664 }
3665
3666 GLbitfield writeOnlyBits =
3667 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3668
3669 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3670 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003671 context->handleError(InvalidOperation()
3672 << "Invalid access bits when mapping buffer for reading: 0x"
3673 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003674 return false;
3675 }
3676
3677 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3678 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003679 context->handleError(
3680 InvalidOperation()
3681 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003682 return false;
3683 }
Geoff Lang79f71042017-08-14 16:43:43 -04003684
3685 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003686}
3687
3688bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003689 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003690 GLintptr offset,
3691 GLsizeiptr length)
3692{
Brandon Jones6cad5662017-06-14 13:25:13 -07003693 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003694 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003695 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3696 return false;
3697 }
3698
3699 if (length < 0)
3700 {
3701 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003702 return false;
3703 }
3704
Corentin Walleze4477002017-12-01 14:39:58 -05003705 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003706 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003707 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003708 return false;
3709 }
3710
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003711 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003712
3713 if (buffer == nullptr)
3714 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003715 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003716 return false;
3717 }
3718
3719 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3720 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003721 context->handleError(InvalidOperation()
3722 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003723 return false;
3724 }
3725
3726 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003727 CheckedNumeric<size_t> checkedOffset(offset);
3728 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003729
Jamie Madille2e406c2016-06-02 13:04:10 -04003730 if (!checkedSize.IsValid() ||
3731 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003732 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003733 context->handleError(InvalidValue()
3734 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003735 return false;
3736 }
3737
3738 return true;
3739}
3740
Olli Etuaho41997e72016-03-10 13:38:39 +02003741bool ValidateGenOrDelete(Context *context, GLint n)
3742{
3743 if (n < 0)
3744 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003745 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003746 return false;
3747 }
3748 return true;
3749}
3750
Jamie Madill5b772312018-03-08 20:28:32 -05003751bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003752{
3753 if (!context->getExtensions().robustClientMemory)
3754 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003755 context->handleError(InvalidOperation()
3756 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003757 return false;
3758 }
3759
3760 if (bufSize < 0)
3761 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003762 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003763 return false;
3764 }
3765
3766 return true;
3767}
3768
Jamie Madill5b772312018-03-08 20:28:32 -05003769bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003770{
3771 if (bufSize < numParams)
3772 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003773 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3774 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003775 return false;
3776 }
3777
3778 return true;
3779}
3780
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003781bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04003782 GLenum target,
3783 GLenum attachment,
3784 GLenum pname,
3785 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003786{
Geoff Lange8afa902017-09-27 15:00:43 -04003787 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003788 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003789 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003790 return false;
3791 }
3792
3793 int clientVersion = context->getClientMajorVersion();
3794
3795 switch (pname)
3796 {
3797 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3798 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3799 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3800 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3801 break;
3802
Martin Radeve5285d22017-07-14 16:23:53 +03003803 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3804 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3805 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3806 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3807 if (clientVersion < 3 || !context->getExtensions().multiview)
3808 {
3809 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3810 return false;
3811 }
3812 break;
3813
Geoff Langff5b2d52016-09-07 11:32:23 -04003814 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3815 if (clientVersion < 3 && !context->getExtensions().sRGB)
3816 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003817 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003818 return false;
3819 }
3820 break;
3821
3822 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3823 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3824 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3825 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3826 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3827 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3828 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3829 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3830 if (clientVersion < 3)
3831 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003832 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003833 return false;
3834 }
3835 break;
3836
3837 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003838 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003839 return false;
3840 }
3841
3842 // Determine if the attachment is a valid enum
3843 switch (attachment)
3844 {
3845 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04003846 case GL_DEPTH:
3847 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04003848 if (clientVersion < 3)
3849 {
Geoff Langfa125c92017-10-24 13:01:46 -04003850 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003851 return false;
3852 }
3853 break;
3854
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003855 case GL_DEPTH_STENCIL_ATTACHMENT:
3856 if (clientVersion < 3 && !context->isWebGL1())
3857 {
3858 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3859 return false;
3860 }
3861 break;
3862
Geoff Langfa125c92017-10-24 13:01:46 -04003863 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003864 case GL_DEPTH_ATTACHMENT:
3865 case GL_STENCIL_ATTACHMENT:
3866 break;
3867
3868 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003869 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3870 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003871 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3872 {
Geoff Langfa125c92017-10-24 13:01:46 -04003873 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003874 return false;
3875 }
3876 break;
3877 }
3878
3879 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3880 ASSERT(framebuffer);
3881
3882 if (framebuffer->id() == 0)
3883 {
3884 if (clientVersion < 3)
3885 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003886 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003887 return false;
3888 }
3889
3890 switch (attachment)
3891 {
3892 case GL_BACK:
3893 case GL_DEPTH:
3894 case GL_STENCIL:
3895 break;
3896
3897 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003898 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003899 return false;
3900 }
3901 }
3902 else
3903 {
3904 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3905 {
3906 // Valid attachment query
3907 }
3908 else
3909 {
3910 switch (attachment)
3911 {
3912 case GL_DEPTH_ATTACHMENT:
3913 case GL_STENCIL_ATTACHMENT:
3914 break;
3915
3916 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003917 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04003918 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003919 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003920 return false;
3921 }
3922 break;
3923
3924 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003925 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003926 return false;
3927 }
3928 }
3929 }
3930
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003931 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003932 if (attachmentObject)
3933 {
3934 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3935 attachmentObject->type() == GL_TEXTURE ||
3936 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3937
3938 switch (pname)
3939 {
3940 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3941 if (attachmentObject->type() != GL_RENDERBUFFER &&
3942 attachmentObject->type() != GL_TEXTURE)
3943 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003944 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003945 return false;
3946 }
3947 break;
3948
3949 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3950 if (attachmentObject->type() != GL_TEXTURE)
3951 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003952 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003953 return false;
3954 }
3955 break;
3956
3957 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3958 if (attachmentObject->type() != GL_TEXTURE)
3959 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003960 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003961 return false;
3962 }
3963 break;
3964
3965 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3966 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3967 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003968 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003969 return false;
3970 }
3971 break;
3972
3973 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3974 if (attachmentObject->type() != GL_TEXTURE)
3975 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003976 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003977 return false;
3978 }
3979 break;
3980
3981 default:
3982 break;
3983 }
3984 }
3985 else
3986 {
3987 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3988 // is NONE, then querying any other pname will generate INVALID_ENUM.
3989
3990 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3991 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3992 // INVALID_OPERATION for all other pnames
3993
3994 switch (pname)
3995 {
3996 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3997 break;
3998
3999 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4000 if (clientVersion < 3)
4001 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004002 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004003 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004004 return false;
4005 }
4006 break;
4007
4008 default:
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 else
4016 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004017 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004018 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004019 return false;
4020 }
4021 }
4022 }
4023
Martin Radeve5285d22017-07-14 16:23:53 +03004024 if (numParams)
4025 {
4026 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4027 {
4028 // Only when the viewport offsets are queried we can have a varying number of output
4029 // parameters.
4030 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4031 *numParams = numViews * 2;
4032 }
4033 else
4034 {
4035 // For all other queries we can have only one output parameter.
4036 *numParams = 1;
4037 }
4038 }
4039
Geoff Langff5b2d52016-09-07 11:32:23 -04004040 return true;
4041}
4042
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004043bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004044 GLenum target,
4045 GLenum attachment,
4046 GLenum pname,
4047 GLsizei bufSize,
4048 GLsizei *numParams)
4049{
4050 if (!ValidateRobustEntryPoint(context, bufSize))
4051 {
4052 return false;
4053 }
4054
Jamie Madillbe849e42017-05-02 15:49:00 -04004055 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4056 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004057 {
4058 return false;
4059 }
4060
4061 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4062 {
4063 return false;
4064 }
4065
4066 return true;
4067}
4068
Jamie Madill5b772312018-03-08 20:28:32 -05004069bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004070 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004071 GLenum pname,
4072 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004073 GLsizei *length,
4074 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004075{
4076 if (!ValidateRobustEntryPoint(context, bufSize))
4077 {
4078 return false;
4079 }
4080
Geoff Langebebe1c2016-10-14 12:01:31 -04004081 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004082 {
4083 return false;
4084 }
4085
Geoff Langebebe1c2016-10-14 12:01:31 -04004086 if (!ValidateRobustBufferSize(context, bufSize, *length))
4087 {
4088 return false;
4089 }
4090
4091 return true;
4092}
4093
Jamie Madill5b772312018-03-08 20:28:32 -05004094bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004095 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004096 GLenum pname,
4097 GLsizei bufSize,
4098 GLsizei *length,
4099 GLint64 *params)
4100{
4101 if (!ValidateRobustEntryPoint(context, bufSize))
4102 {
4103 return false;
4104 }
4105
4106 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4107 {
4108 return false;
4109 }
4110
4111 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004112 {
4113 return false;
4114 }
4115
4116 return true;
4117}
4118
Jamie Madill5b772312018-03-08 20:28:32 -05004119bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004120{
4121 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004122 if (numParams)
4123 {
4124 *numParams = 1;
4125 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004126
4127 Program *programObject = GetValidProgram(context, program);
4128 if (!programObject)
4129 {
4130 return false;
4131 }
4132
4133 switch (pname)
4134 {
4135 case GL_DELETE_STATUS:
4136 case GL_LINK_STATUS:
4137 case GL_VALIDATE_STATUS:
4138 case GL_INFO_LOG_LENGTH:
4139 case GL_ATTACHED_SHADERS:
4140 case GL_ACTIVE_ATTRIBUTES:
4141 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4142 case GL_ACTIVE_UNIFORMS:
4143 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4144 break;
4145
4146 case GL_PROGRAM_BINARY_LENGTH:
4147 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4148 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004149 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4150 "requires GL_OES_get_program_binary or "
4151 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004152 return false;
4153 }
4154 break;
4155
4156 case GL_ACTIVE_UNIFORM_BLOCKS:
4157 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4158 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4159 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4160 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4161 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4162 if (context->getClientMajorVersion() < 3)
4163 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004164 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004165 return false;
4166 }
4167 break;
4168
Yunchao He61afff12017-03-14 15:34:03 +08004169 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004170 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004171 if (context->getClientVersion() < Version(3, 1))
4172 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004173 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004174 return false;
4175 }
4176 break;
4177
Jiawei Shao6ae51612018-02-23 14:03:25 +08004178 case GL_COMPUTE_WORK_GROUP_SIZE:
4179 if (context->getClientVersion() < Version(3, 1))
4180 {
4181 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4182 return false;
4183 }
4184
4185 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4186 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4187 // program which has not been linked successfully, or which does not contain objects to
4188 // form a compute shader.
4189 if (!programObject->isLinked())
4190 {
4191 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4192 return false;
4193 }
4194 if (!programObject->hasLinkedComputeShader())
4195 {
4196 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4197 return false;
4198 }
4199 break;
4200
Geoff Langff5b2d52016-09-07 11:32:23 -04004201 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004202 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004203 return false;
4204 }
4205
4206 return true;
4207}
4208
4209bool ValidateGetProgramivRobustANGLE(Context *context,
4210 GLuint program,
4211 GLenum pname,
4212 GLsizei bufSize,
4213 GLsizei *numParams)
4214{
4215 if (!ValidateRobustEntryPoint(context, bufSize))
4216 {
4217 return false;
4218 }
4219
Jamie Madillbe849e42017-05-02 15:49:00 -04004220 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004221 {
4222 return false;
4223 }
4224
4225 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4226 {
4227 return false;
4228 }
4229
4230 return true;
4231}
4232
Geoff Lang740d9022016-10-07 11:20:52 -04004233bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4234 GLenum target,
4235 GLenum pname,
4236 GLsizei bufSize,
4237 GLsizei *length,
4238 GLint *params)
4239{
4240 if (!ValidateRobustEntryPoint(context, bufSize))
4241 {
4242 return false;
4243 }
4244
4245 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4246 {
4247 return false;
4248 }
4249
4250 if (!ValidateRobustBufferSize(context, bufSize, *length))
4251 {
4252 return false;
4253 }
4254
4255 return true;
4256}
4257
Geoff Langd7d0ed32016-10-07 11:33:51 -04004258bool ValidateGetShaderivRobustANGLE(Context *context,
4259 GLuint shader,
4260 GLenum pname,
4261 GLsizei bufSize,
4262 GLsizei *length,
4263 GLint *params)
4264{
4265 if (!ValidateRobustEntryPoint(context, bufSize))
4266 {
4267 return false;
4268 }
4269
4270 if (!ValidateGetShaderivBase(context, shader, pname, length))
4271 {
4272 return false;
4273 }
4274
4275 if (!ValidateRobustBufferSize(context, bufSize, *length))
4276 {
4277 return false;
4278 }
4279
4280 return true;
4281}
4282
Geoff Langc1984ed2016-10-07 12:41:00 -04004283bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004284 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004285 GLenum pname,
4286 GLsizei bufSize,
4287 GLsizei *length,
4288 GLfloat *params)
4289{
4290 if (!ValidateRobustEntryPoint(context, bufSize))
4291 {
4292 return false;
4293 }
4294
4295 if (!ValidateGetTexParameterBase(context, target, pname, length))
4296 {
4297 return false;
4298 }
4299
4300 if (!ValidateRobustBufferSize(context, bufSize, *length))
4301 {
4302 return false;
4303 }
4304
4305 return true;
4306}
4307
Geoff Langc1984ed2016-10-07 12:41:00 -04004308bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004309 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004310 GLenum pname,
4311 GLsizei bufSize,
4312 GLsizei *length,
4313 GLint *params)
4314{
4315 if (!ValidateRobustEntryPoint(context, bufSize))
4316 {
4317 return false;
4318 }
4319
4320 if (!ValidateGetTexParameterBase(context, target, pname, length))
4321 {
4322 return false;
4323 }
4324
4325 if (!ValidateRobustBufferSize(context, bufSize, *length))
4326 {
4327 return false;
4328 }
4329
4330 return true;
4331}
4332
Geoff Langc1984ed2016-10-07 12:41:00 -04004333bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004334 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004335 GLenum pname,
4336 GLsizei bufSize,
4337 const GLfloat *params)
4338{
4339 if (!ValidateRobustEntryPoint(context, bufSize))
4340 {
4341 return false;
4342 }
4343
4344 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4345}
4346
Geoff Langc1984ed2016-10-07 12:41:00 -04004347bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004348 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004349 GLenum pname,
4350 GLsizei bufSize,
4351 const GLint *params)
4352{
4353 if (!ValidateRobustEntryPoint(context, bufSize))
4354 {
4355 return false;
4356 }
4357
4358 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4359}
4360
Geoff Langc1984ed2016-10-07 12:41:00 -04004361bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4362 GLuint sampler,
4363 GLenum pname,
4364 GLuint bufSize,
4365 GLsizei *length,
4366 GLfloat *params)
4367{
4368 if (!ValidateRobustEntryPoint(context, bufSize))
4369 {
4370 return false;
4371 }
4372
4373 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4374 {
4375 return false;
4376 }
4377
4378 if (!ValidateRobustBufferSize(context, bufSize, *length))
4379 {
4380 return false;
4381 }
4382
4383 return true;
4384}
4385
Geoff Langc1984ed2016-10-07 12:41:00 -04004386bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4387 GLuint sampler,
4388 GLenum pname,
4389 GLuint bufSize,
4390 GLsizei *length,
4391 GLint *params)
4392{
4393 if (!ValidateRobustEntryPoint(context, bufSize))
4394 {
4395 return false;
4396 }
4397
4398 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4399 {
4400 return false;
4401 }
4402
4403 if (!ValidateRobustBufferSize(context, bufSize, *length))
4404 {
4405 return false;
4406 }
4407
4408 return true;
4409}
4410
Geoff Langc1984ed2016-10-07 12:41:00 -04004411bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4412 GLuint sampler,
4413 GLenum pname,
4414 GLsizei bufSize,
4415 const GLfloat *params)
4416{
4417 if (!ValidateRobustEntryPoint(context, bufSize))
4418 {
4419 return false;
4420 }
4421
4422 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4423}
4424
Geoff Langc1984ed2016-10-07 12:41:00 -04004425bool ValidateSamplerParameterivRobustANGLE(Context *context,
4426 GLuint sampler,
4427 GLenum pname,
4428 GLsizei bufSize,
4429 const GLint *params)
4430{
4431 if (!ValidateRobustEntryPoint(context, bufSize))
4432 {
4433 return false;
4434 }
4435
4436 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4437}
4438
Geoff Lang0b031062016-10-13 14:30:04 -04004439bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4440 GLuint index,
4441 GLenum pname,
4442 GLsizei bufSize,
4443 GLsizei *length,
4444 GLfloat *params)
4445{
4446 if (!ValidateRobustEntryPoint(context, bufSize))
4447 {
4448 return false;
4449 }
4450
4451 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4452 {
4453 return false;
4454 }
4455
4456 if (!ValidateRobustBufferSize(context, bufSize, *length))
4457 {
4458 return false;
4459 }
4460
4461 return true;
4462}
4463
Geoff Lang0b031062016-10-13 14:30:04 -04004464bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4465 GLuint index,
4466 GLenum pname,
4467 GLsizei bufSize,
4468 GLsizei *length,
4469 GLint *params)
4470{
4471 if (!ValidateRobustEntryPoint(context, bufSize))
4472 {
4473 return false;
4474 }
4475
4476 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4477 {
4478 return false;
4479 }
4480
4481 if (!ValidateRobustBufferSize(context, bufSize, *length))
4482 {
4483 return false;
4484 }
4485
4486 return true;
4487}
4488
Geoff Lang0b031062016-10-13 14:30:04 -04004489bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4490 GLuint index,
4491 GLenum pname,
4492 GLsizei bufSize,
4493 GLsizei *length,
4494 void **pointer)
4495{
4496 if (!ValidateRobustEntryPoint(context, bufSize))
4497 {
4498 return false;
4499 }
4500
4501 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4502 {
4503 return false;
4504 }
4505
4506 if (!ValidateRobustBufferSize(context, bufSize, *length))
4507 {
4508 return false;
4509 }
4510
4511 return true;
4512}
4513
Geoff Lang0b031062016-10-13 14:30:04 -04004514bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4515 GLuint index,
4516 GLenum pname,
4517 GLsizei bufSize,
4518 GLsizei *length,
4519 GLint *params)
4520{
4521 if (!ValidateRobustEntryPoint(context, bufSize))
4522 {
4523 return false;
4524 }
4525
4526 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4527 {
4528 return false;
4529 }
4530
4531 if (!ValidateRobustBufferSize(context, bufSize, *length))
4532 {
4533 return false;
4534 }
4535
4536 return true;
4537}
4538
Geoff Lang0b031062016-10-13 14:30:04 -04004539bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4540 GLuint index,
4541 GLenum pname,
4542 GLsizei bufSize,
4543 GLsizei *length,
4544 GLuint *params)
4545{
4546 if (!ValidateRobustEntryPoint(context, bufSize))
4547 {
4548 return false;
4549 }
4550
4551 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4552 {
4553 return false;
4554 }
4555
4556 if (!ValidateRobustBufferSize(context, bufSize, *length))
4557 {
4558 return false;
4559 }
4560
4561 return true;
4562}
4563
Geoff Lang6899b872016-10-14 11:30:13 -04004564bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4565 GLuint program,
4566 GLuint uniformBlockIndex,
4567 GLenum pname,
4568 GLsizei bufSize,
4569 GLsizei *length,
4570 GLint *params)
4571{
4572 if (!ValidateRobustEntryPoint(context, bufSize))
4573 {
4574 return false;
4575 }
4576
4577 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4578 {
4579 return false;
4580 }
4581
4582 if (!ValidateRobustBufferSize(context, bufSize, *length))
4583 {
4584 return false;
4585 }
4586
4587 return true;
4588}
4589
Geoff Lang0a9661f2016-10-20 10:59:20 -07004590bool ValidateGetInternalFormativRobustANGLE(Context *context,
4591 GLenum target,
4592 GLenum internalformat,
4593 GLenum pname,
4594 GLsizei bufSize,
4595 GLsizei *length,
4596 GLint *params)
4597{
4598 if (!ValidateRobustEntryPoint(context, bufSize))
4599 {
4600 return false;
4601 }
4602
4603 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4604 {
4605 return false;
4606 }
4607
4608 if (!ValidateRobustBufferSize(context, bufSize, *length))
4609 {
4610 return false;
4611 }
4612
4613 return true;
4614}
4615
Jamie Madill5b772312018-03-08 20:28:32 -05004616bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08004617 GLuint attribIndex,
4618 GLint size,
4619 GLenum type,
4620 GLboolean pureInteger)
4621{
4622 const Caps &caps = context->getCaps();
4623 if (attribIndex >= caps.maxVertexAttributes)
4624 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004625 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004626 return false;
4627 }
4628
4629 if (size < 1 || size > 4)
4630 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004631 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004632 return false;
Shao80957d92017-02-20 21:25:59 +08004633 }
4634
4635 switch (type)
4636 {
4637 case GL_BYTE:
4638 case GL_UNSIGNED_BYTE:
4639 case GL_SHORT:
4640 case GL_UNSIGNED_SHORT:
4641 break;
4642
4643 case GL_INT:
4644 case GL_UNSIGNED_INT:
4645 if (context->getClientMajorVersion() < 3)
4646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004647 context->handleError(InvalidEnum()
4648 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004649 return false;
4650 }
4651 break;
4652
4653 case GL_FIXED:
4654 case GL_FLOAT:
4655 if (pureInteger)
4656 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004657 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004658 return false;
4659 }
4660 break;
4661
4662 case GL_HALF_FLOAT:
4663 if (context->getClientMajorVersion() < 3)
4664 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004665 context->handleError(InvalidEnum()
4666 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004667 return false;
4668 }
4669 if (pureInteger)
4670 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004671 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004672 return false;
4673 }
4674 break;
4675
4676 case GL_INT_2_10_10_10_REV:
4677 case GL_UNSIGNED_INT_2_10_10_10_REV:
4678 if (context->getClientMajorVersion() < 3)
4679 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004680 context->handleError(InvalidEnum()
4681 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004682 return false;
4683 }
4684 if (pureInteger)
4685 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004686 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004687 return false;
4688 }
4689 if (size != 4)
4690 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004691 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4692 "UNSIGNED_INT_2_10_10_10_REV and "
4693 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004694 return false;
4695 }
4696 break;
4697
4698 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004699 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004700 return false;
4701 }
4702
4703 return true;
4704}
4705
Geoff Lang76e65652017-03-27 14:58:02 -04004706// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4707// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4708// specified clear value and the type of a buffer that is being cleared generates an
4709// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05004710bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04004711 GLint drawbuffer,
4712 const GLenum *validComponentTypes,
4713 size_t validComponentTypeCount)
4714{
4715 const FramebufferAttachment *attachment =
4716 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4717 if (attachment)
4718 {
4719 GLenum componentType = attachment->getFormat().info->componentType;
4720 const GLenum *end = validComponentTypes + validComponentTypeCount;
4721 if (std::find(validComponentTypes, end, componentType) == end)
4722 {
4723 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004724 InvalidOperation()
4725 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004726 return false;
4727 }
4728 }
4729
4730 return true;
4731}
4732
Jamie Madill5b772312018-03-08 20:28:32 -05004733bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04004734{
4735 if (!ValidateRobustEntryPoint(context, dataSize))
4736 {
4737 return false;
4738 }
4739
Corentin Wallez336129f2017-10-17 15:55:40 -04004740 gl::Buffer *pixelUnpackBuffer =
4741 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004742 if (pixelUnpackBuffer == nullptr)
4743 {
4744 if (dataSize < imageSize)
4745 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004746 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004747 }
4748 }
4749 return true;
4750}
4751
Jamie Madill5b772312018-03-08 20:28:32 -05004752bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004753 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004754 GLenum pname,
4755 bool pointerVersion,
4756 GLsizei *numParams)
4757{
4758 if (numParams)
4759 {
4760 *numParams = 0;
4761 }
4762
Corentin Walleze4477002017-12-01 14:39:58 -05004763 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004764 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004765 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004766 return false;
4767 }
4768
4769 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4770 if (!buffer)
4771 {
4772 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004773 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004774 return false;
4775 }
4776
4777 const Extensions &extensions = context->getExtensions();
4778
4779 switch (pname)
4780 {
4781 case GL_BUFFER_USAGE:
4782 case GL_BUFFER_SIZE:
4783 break;
4784
4785 case GL_BUFFER_ACCESS_OES:
4786 if (!extensions.mapBuffer)
4787 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004788 context->handleError(InvalidEnum()
4789 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004790 return false;
4791 }
4792 break;
4793
4794 case GL_BUFFER_MAPPED:
4795 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4796 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4797 !extensions.mapBufferRange)
4798 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004799 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4800 "GL_OES_mapbuffer or "
4801 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004802 return false;
4803 }
4804 break;
4805
4806 case GL_BUFFER_MAP_POINTER:
4807 if (!pointerVersion)
4808 {
4809 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004810 InvalidEnum()
4811 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004812 return false;
4813 }
4814 break;
4815
4816 case GL_BUFFER_ACCESS_FLAGS:
4817 case GL_BUFFER_MAP_OFFSET:
4818 case GL_BUFFER_MAP_LENGTH:
4819 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4820 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004821 context->handleError(InvalidEnum()
4822 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004823 return false;
4824 }
4825 break;
4826
4827 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004828 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004829 return false;
4830 }
4831
4832 // All buffer parameter queries return one value.
4833 if (numParams)
4834 {
4835 *numParams = 1;
4836 }
4837
4838 return true;
4839}
4840
4841bool ValidateGetRenderbufferParameterivBase(Context *context,
4842 GLenum target,
4843 GLenum pname,
4844 GLsizei *length)
4845{
4846 if (length)
4847 {
4848 *length = 0;
4849 }
4850
4851 if (target != GL_RENDERBUFFER)
4852 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004853 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004854 return false;
4855 }
4856
4857 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4858 if (renderbuffer == nullptr)
4859 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004860 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004861 return false;
4862 }
4863
4864 switch (pname)
4865 {
4866 case GL_RENDERBUFFER_WIDTH:
4867 case GL_RENDERBUFFER_HEIGHT:
4868 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4869 case GL_RENDERBUFFER_RED_SIZE:
4870 case GL_RENDERBUFFER_GREEN_SIZE:
4871 case GL_RENDERBUFFER_BLUE_SIZE:
4872 case GL_RENDERBUFFER_ALPHA_SIZE:
4873 case GL_RENDERBUFFER_DEPTH_SIZE:
4874 case GL_RENDERBUFFER_STENCIL_SIZE:
4875 break;
4876
4877 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4878 if (!context->getExtensions().framebufferMultisample)
4879 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004880 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004881 return false;
4882 }
4883 break;
4884
4885 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004886 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004887 return false;
4888 }
4889
4890 if (length)
4891 {
4892 *length = 1;
4893 }
4894 return true;
4895}
4896
4897bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4898{
4899 if (length)
4900 {
4901 *length = 0;
4902 }
4903
4904 if (GetValidShader(context, shader) == nullptr)
4905 {
4906 return false;
4907 }
4908
4909 switch (pname)
4910 {
4911 case GL_SHADER_TYPE:
4912 case GL_DELETE_STATUS:
4913 case GL_COMPILE_STATUS:
4914 case GL_INFO_LOG_LENGTH:
4915 case GL_SHADER_SOURCE_LENGTH:
4916 break;
4917
4918 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4919 if (!context->getExtensions().translatedShaderSource)
4920 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004921 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004922 return false;
4923 }
4924 break;
4925
4926 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004927 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004928 return false;
4929 }
4930
4931 if (length)
4932 {
4933 *length = 1;
4934 }
4935 return true;
4936}
4937
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004938bool ValidateGetTexParameterBase(Context *context,
4939 TextureType target,
4940 GLenum pname,
4941 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04004942{
4943 if (length)
4944 {
4945 *length = 0;
4946 }
4947
4948 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4949 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004950 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004951 return false;
4952 }
4953
4954 if (context->getTargetTexture(target) == nullptr)
4955 {
4956 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004957 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004958 return false;
4959 }
4960
4961 switch (pname)
4962 {
4963 case GL_TEXTURE_MAG_FILTER:
4964 case GL_TEXTURE_MIN_FILTER:
4965 case GL_TEXTURE_WRAP_S:
4966 case GL_TEXTURE_WRAP_T:
4967 break;
4968
4969 case GL_TEXTURE_USAGE_ANGLE:
4970 if (!context->getExtensions().textureUsage)
4971 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004972 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004973 return false;
4974 }
4975 break;
4976
4977 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05004978 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04004979 {
Jamie Madillbe849e42017-05-02 15:49:00 -04004980 return false;
4981 }
4982 break;
4983
4984 case GL_TEXTURE_IMMUTABLE_FORMAT:
4985 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4986 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004987 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004988 return false;
4989 }
4990 break;
4991
4992 case GL_TEXTURE_WRAP_R:
4993 case GL_TEXTURE_IMMUTABLE_LEVELS:
4994 case GL_TEXTURE_SWIZZLE_R:
4995 case GL_TEXTURE_SWIZZLE_G:
4996 case GL_TEXTURE_SWIZZLE_B:
4997 case GL_TEXTURE_SWIZZLE_A:
4998 case GL_TEXTURE_BASE_LEVEL:
4999 case GL_TEXTURE_MAX_LEVEL:
5000 case GL_TEXTURE_MIN_LOD:
5001 case GL_TEXTURE_MAX_LOD:
5002 case GL_TEXTURE_COMPARE_MODE:
5003 case GL_TEXTURE_COMPARE_FUNC:
5004 if (context->getClientMajorVersion() < 3)
5005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005006 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005007 return false;
5008 }
5009 break;
5010
5011 case GL_TEXTURE_SRGB_DECODE_EXT:
5012 if (!context->getExtensions().textureSRGBDecode)
5013 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005014 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005015 return false;
5016 }
5017 break;
5018
Yunchao Hebacaa712018-01-30 14:01:39 +08005019 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5020 if (context->getClientVersion() < Version(3, 1))
5021 {
5022 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5023 return false;
5024 }
5025 break;
5026
Jamie Madillbe849e42017-05-02 15:49:00 -04005027 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005028 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005029 return false;
5030 }
5031
5032 if (length)
5033 {
5034 *length = 1;
5035 }
5036 return true;
5037}
5038
5039bool ValidateGetVertexAttribBase(Context *context,
5040 GLuint index,
5041 GLenum pname,
5042 GLsizei *length,
5043 bool pointer,
5044 bool pureIntegerEntryPoint)
5045{
5046 if (length)
5047 {
5048 *length = 0;
5049 }
5050
5051 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5052 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005053 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005054 return false;
5055 }
5056
5057 if (index >= context->getCaps().maxVertexAttributes)
5058 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005059 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005060 return false;
5061 }
5062
5063 if (pointer)
5064 {
5065 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5066 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005067 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005068 return false;
5069 }
5070 }
5071 else
5072 {
5073 switch (pname)
5074 {
5075 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5076 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5077 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5078 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5079 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5080 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5081 case GL_CURRENT_VERTEX_ATTRIB:
5082 break;
5083
5084 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5085 static_assert(
5086 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5087 "ANGLE extension enums not equal to GL enums.");
5088 if (context->getClientMajorVersion() < 3 &&
5089 !context->getExtensions().instancedArrays)
5090 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005091 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5092 "requires OpenGL ES 3.0 or "
5093 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005094 return false;
5095 }
5096 break;
5097
5098 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5099 if (context->getClientMajorVersion() < 3)
5100 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005101 context->handleError(
5102 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005103 return false;
5104 }
5105 break;
5106
5107 case GL_VERTEX_ATTRIB_BINDING:
5108 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5109 if (context->getClientVersion() < ES_3_1)
5110 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005111 context->handleError(InvalidEnum()
5112 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005113 return false;
5114 }
5115 break;
5116
5117 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005118 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005119 return false;
5120 }
5121 }
5122
5123 if (length)
5124 {
5125 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5126 {
5127 *length = 4;
5128 }
5129 else
5130 {
5131 *length = 1;
5132 }
5133 }
5134
5135 return true;
5136}
5137
Jamie Madill4928b7c2017-06-20 12:57:39 -04005138bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005139 GLint x,
5140 GLint y,
5141 GLsizei width,
5142 GLsizei height,
5143 GLenum format,
5144 GLenum type,
5145 GLsizei bufSize,
5146 GLsizei *length,
5147 GLsizei *columns,
5148 GLsizei *rows,
5149 void *pixels)
5150{
5151 if (length != nullptr)
5152 {
5153 *length = 0;
5154 }
5155 if (rows != nullptr)
5156 {
5157 *rows = 0;
5158 }
5159 if (columns != nullptr)
5160 {
5161 *columns = 0;
5162 }
5163
5164 if (width < 0 || height < 0)
5165 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005166 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005167 return false;
5168 }
5169
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005170 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005171
5172 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5173 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005174 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005175 return false;
5176 }
5177
5178 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5179 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005180 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005181 return false;
5182 }
5183
5184 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5185 ASSERT(framebuffer);
5186
5187 if (framebuffer->getReadBufferState() == GL_NONE)
5188 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005189 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005190 return false;
5191 }
5192
5193 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5194 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5195 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5196 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5197 // situation is an application error that would lead to a crash in ANGLE.
5198 if (readBuffer == nullptr)
5199 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005200 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005201 return false;
5202 }
5203
Martin Radev28031682017-07-28 14:47:56 +03005204 // ANGLE_multiview, Revision 1:
5205 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5206 // current read framebuffer is not NONE.
5207 if (readBuffer->getMultiviewLayout() != GL_NONE)
5208 {
5209 context->handleError(InvalidFramebufferOperation()
5210 << "Attempting to read from a multi-view framebuffer.");
5211 return false;
5212 }
5213
Geoff Lang280ba992017-04-18 16:30:58 -04005214 if (context->getExtensions().webglCompatibility)
5215 {
5216 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5217 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5218 // and type before validating the combination of format and type. However, the
5219 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5220 // verifies that GL_INVALID_OPERATION is generated.
5221 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5222 // dEQP/WebGL.
5223 if (!ValidReadPixelsFormatEnum(context, format))
5224 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005225 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005226 return false;
5227 }
5228
5229 if (!ValidReadPixelsTypeEnum(context, type))
5230 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005231 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005232 return false;
5233 }
5234 }
5235
Jamie Madill4928b7c2017-06-20 12:57:39 -04005236 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5237 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005238 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5239
5240 bool validFormatTypeCombination =
5241 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5242
5243 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5244 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005245 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005246 return false;
5247 }
5248
5249 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005250 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005251 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5252 {
5253 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005254 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005255 return false;
5256 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005257 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5258 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5259 {
5260 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5261 return false;
5262 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005263
5264 // .. the data would be packed to the buffer object such that the memory writes required
5265 // would exceed the data store size.
5266 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5267 const gl::Extents size(width, height, 1);
5268 const auto &pack = context->getGLState().getPackState();
5269
5270 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5271 if (endByteOrErr.isError())
5272 {
5273 context->handleError(endByteOrErr.getError());
5274 return false;
5275 }
5276
5277 size_t endByte = endByteOrErr.getResult();
5278 if (bufSize >= 0)
5279 {
5280 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5281 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005282 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005283 return false;
5284 }
5285 }
5286
5287 if (pixelPackBuffer != nullptr)
5288 {
5289 CheckedNumeric<size_t> checkedEndByte(endByte);
5290 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5291 checkedEndByte += checkedOffset;
5292
5293 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5294 {
5295 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005296 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005297 return false;
5298 }
5299 }
5300
5301 if (pixelPackBuffer == nullptr && length != nullptr)
5302 {
5303 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5304 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005305 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005306 return false;
5307 }
5308
5309 *length = static_cast<GLsizei>(endByte);
5310 }
5311
Geoff Langa953b522018-02-21 16:56:23 -05005312 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005313 angle::CheckedNumeric<int> clippedExtent(length);
5314 if (start < 0)
5315 {
5316 // "subtract" the area that is less than 0
5317 clippedExtent += start;
5318 }
5319
Geoff Langa953b522018-02-21 16:56:23 -05005320 angle::CheckedNumeric<int> readExtent = start;
5321 readExtent += length;
5322 if (!readExtent.IsValid())
5323 {
5324 return false;
5325 }
5326
5327 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005328 {
5329 // Subtract the region to the right of the read buffer
5330 clippedExtent -= (readExtent - bufferSize);
5331 }
5332
5333 if (!clippedExtent.IsValid())
5334 {
Geoff Langa953b522018-02-21 16:56:23 -05005335 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005336 }
5337
Geoff Langa953b522018-02-21 16:56:23 -05005338 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5339 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005340 };
5341
Geoff Langa953b522018-02-21 16:56:23 -05005342 GLsizei writtenColumns = 0;
5343 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5344 {
5345 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5346 return false;
5347 }
5348
5349 GLsizei writtenRows = 0;
5350 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5351 {
5352 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5353 return false;
5354 }
5355
Jamie Madillbe849e42017-05-02 15:49:00 -04005356 if (columns != nullptr)
5357 {
Geoff Langa953b522018-02-21 16:56:23 -05005358 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005359 }
5360
5361 if (rows != nullptr)
5362 {
Geoff Langa953b522018-02-21 16:56:23 -05005363 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005364 }
5365
5366 return true;
5367}
5368
5369template <typename ParamType>
5370bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005371 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005372 GLenum pname,
5373 GLsizei bufSize,
5374 const ParamType *params)
5375{
5376 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5377 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005378 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005379 return false;
5380 }
5381
5382 if (context->getTargetTexture(target) == nullptr)
5383 {
5384 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005385 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005386 return false;
5387 }
5388
5389 const GLsizei minBufSize = 1;
5390 if (bufSize >= 0 && bufSize < minBufSize)
5391 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005392 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005393 return false;
5394 }
5395
5396 switch (pname)
5397 {
5398 case GL_TEXTURE_WRAP_R:
5399 case GL_TEXTURE_SWIZZLE_R:
5400 case GL_TEXTURE_SWIZZLE_G:
5401 case GL_TEXTURE_SWIZZLE_B:
5402 case GL_TEXTURE_SWIZZLE_A:
5403 case GL_TEXTURE_BASE_LEVEL:
5404 case GL_TEXTURE_MAX_LEVEL:
5405 case GL_TEXTURE_COMPARE_MODE:
5406 case GL_TEXTURE_COMPARE_FUNC:
5407 case GL_TEXTURE_MIN_LOD:
5408 case GL_TEXTURE_MAX_LOD:
5409 if (context->getClientMajorVersion() < 3)
5410 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005411 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005412 return false;
5413 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005414 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005415 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005416 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5417 "available without "
5418 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005419 return false;
5420 }
5421 break;
5422
5423 default:
5424 break;
5425 }
5426
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005427 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005428 {
5429 switch (pname)
5430 {
5431 case GL_TEXTURE_MIN_FILTER:
5432 case GL_TEXTURE_MAG_FILTER:
5433 case GL_TEXTURE_WRAP_S:
5434 case GL_TEXTURE_WRAP_T:
5435 case GL_TEXTURE_WRAP_R:
5436 case GL_TEXTURE_MIN_LOD:
5437 case GL_TEXTURE_MAX_LOD:
5438 case GL_TEXTURE_COMPARE_MODE:
5439 case GL_TEXTURE_COMPARE_FUNC:
5440 context->handleError(InvalidEnum()
5441 << "Invalid parameter for 2D multisampled textures.");
5442 return false;
5443 }
5444 }
5445
Jamie Madillbe849e42017-05-02 15:49:00 -04005446 switch (pname)
5447 {
5448 case GL_TEXTURE_WRAP_S:
5449 case GL_TEXTURE_WRAP_T:
5450 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005451 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005452 bool restrictedWrapModes =
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005453 target == TextureType::External || target == TextureType::Rectangle;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005454 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5455 {
5456 return false;
5457 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005458 }
5459 break;
5460
5461 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005462 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005463 bool restrictedMinFilter =
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005464 target == TextureType::External || target == TextureType::Rectangle;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005465 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5466 {
5467 return false;
5468 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005469 }
5470 break;
5471
5472 case GL_TEXTURE_MAG_FILTER:
5473 if (!ValidateTextureMagFilterValue(context, params))
5474 {
5475 return false;
5476 }
5477 break;
5478
5479 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005480 if (!context->getExtensions().textureUsage)
5481 {
5482 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5483 return false;
5484 }
5485
Jamie Madillbe849e42017-05-02 15:49:00 -04005486 switch (ConvertToGLenum(params[0]))
5487 {
5488 case GL_NONE:
5489 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5490 break;
5491
5492 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005493 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005494 return false;
5495 }
5496 break;
5497
5498 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Jamie Madillbe849e42017-05-02 15:49:00 -04005499 {
Luc Ferron1b1a8642018-01-23 15:12:01 -05005500 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5501 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5502 {
5503 return false;
5504 }
5505 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
Jamie Madillbe849e42017-05-02 15:49:00 -04005506 }
5507 break;
5508
5509 case GL_TEXTURE_MIN_LOD:
5510 case GL_TEXTURE_MAX_LOD:
5511 // any value is permissible
5512 break;
5513
5514 case GL_TEXTURE_COMPARE_MODE:
5515 if (!ValidateTextureCompareModeValue(context, params))
5516 {
5517 return false;
5518 }
5519 break;
5520
5521 case GL_TEXTURE_COMPARE_FUNC:
5522 if (!ValidateTextureCompareFuncValue(context, params))
5523 {
5524 return false;
5525 }
5526 break;
5527
5528 case GL_TEXTURE_SWIZZLE_R:
5529 case GL_TEXTURE_SWIZZLE_G:
5530 case GL_TEXTURE_SWIZZLE_B:
5531 case GL_TEXTURE_SWIZZLE_A:
5532 switch (ConvertToGLenum(params[0]))
5533 {
5534 case GL_RED:
5535 case GL_GREEN:
5536 case GL_BLUE:
5537 case GL_ALPHA:
5538 case GL_ZERO:
5539 case GL_ONE:
5540 break;
5541
5542 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005543 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005544 return false;
5545 }
5546 break;
5547
5548 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005549 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005550 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005551 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005552 return false;
5553 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005554 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005555 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005556 context->handleError(InvalidOperation()
5557 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005558 return false;
5559 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005560 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005561 {
5562 context->handleError(InvalidOperation()
5563 << "Base level must be 0 for multisampled textures.");
5564 return false;
5565 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005566 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005567 {
5568 context->handleError(InvalidOperation()
5569 << "Base level must be 0 for rectangle textures.");
5570 return false;
5571 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005572 break;
5573
5574 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005575 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005576 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005577 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005578 return false;
5579 }
5580 break;
5581
5582 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5583 if (context->getClientVersion() < Version(3, 1))
5584 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005585 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005586 return false;
5587 }
5588 switch (ConvertToGLenum(params[0]))
5589 {
5590 case GL_DEPTH_COMPONENT:
5591 case GL_STENCIL_INDEX:
5592 break;
5593
5594 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005595 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005596 return false;
5597 }
5598 break;
5599
5600 case GL_TEXTURE_SRGB_DECODE_EXT:
5601 if (!ValidateTextureSRGBDecodeValue(context, params))
5602 {
5603 return false;
5604 }
5605 break;
5606
5607 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005608 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005609 return false;
5610 }
5611
5612 return true;
5613}
5614
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005615template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
5616template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04005617
Jamie Madill5b772312018-03-08 20:28:32 -05005618bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04005619{
5620 if (index >= MAX_VERTEX_ATTRIBS)
5621 {
5622 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5623 return false;
5624 }
5625
5626 return true;
5627}
5628
5629bool ValidateGetActiveUniformBlockivBase(Context *context,
5630 GLuint program,
5631 GLuint uniformBlockIndex,
5632 GLenum pname,
5633 GLsizei *length)
5634{
5635 if (length)
5636 {
5637 *length = 0;
5638 }
5639
5640 if (context->getClientMajorVersion() < 3)
5641 {
5642 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5643 return false;
5644 }
5645
5646 Program *programObject = GetValidProgram(context, program);
5647 if (!programObject)
5648 {
5649 return false;
5650 }
5651
5652 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5653 {
5654 context->handleError(InvalidValue()
5655 << "uniformBlockIndex exceeds active uniform block count.");
5656 return false;
5657 }
5658
5659 switch (pname)
5660 {
5661 case GL_UNIFORM_BLOCK_BINDING:
5662 case GL_UNIFORM_BLOCK_DATA_SIZE:
5663 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5664 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5665 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5666 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5667 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5668 break;
5669
5670 default:
5671 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5672 return false;
5673 }
5674
5675 if (length)
5676 {
5677 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5678 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005679 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005680 programObject->getUniformBlockByIndex(uniformBlockIndex);
5681 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5682 }
5683 else
5684 {
5685 *length = 1;
5686 }
5687 }
5688
5689 return true;
5690}
5691
Jamie Madill9696d072017-08-26 23:19:57 -04005692template <typename ParamType>
5693bool ValidateSamplerParameterBase(Context *context,
5694 GLuint sampler,
5695 GLenum pname,
5696 GLsizei bufSize,
5697 ParamType *params)
5698{
5699 if (context->getClientMajorVersion() < 3)
5700 {
5701 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5702 return false;
5703 }
5704
5705 if (!context->isSampler(sampler))
5706 {
5707 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5708 return false;
5709 }
5710
5711 const GLsizei minBufSize = 1;
5712 if (bufSize >= 0 && bufSize < minBufSize)
5713 {
5714 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5715 return false;
5716 }
5717
5718 switch (pname)
5719 {
5720 case GL_TEXTURE_WRAP_S:
5721 case GL_TEXTURE_WRAP_T:
5722 case GL_TEXTURE_WRAP_R:
5723 if (!ValidateTextureWrapModeValue(context, params, false))
5724 {
5725 return false;
5726 }
5727 break;
5728
5729 case GL_TEXTURE_MIN_FILTER:
5730 if (!ValidateTextureMinFilterValue(context, params, false))
5731 {
5732 return false;
5733 }
5734 break;
5735
5736 case GL_TEXTURE_MAG_FILTER:
5737 if (!ValidateTextureMagFilterValue(context, params))
5738 {
5739 return false;
5740 }
5741 break;
5742
5743 case GL_TEXTURE_MIN_LOD:
5744 case GL_TEXTURE_MAX_LOD:
5745 // any value is permissible
5746 break;
5747
5748 case GL_TEXTURE_COMPARE_MODE:
5749 if (!ValidateTextureCompareModeValue(context, params))
5750 {
5751 return false;
5752 }
5753 break;
5754
5755 case GL_TEXTURE_COMPARE_FUNC:
5756 if (!ValidateTextureCompareFuncValue(context, params))
5757 {
5758 return false;
5759 }
5760 break;
5761
5762 case GL_TEXTURE_SRGB_DECODE_EXT:
5763 if (!ValidateTextureSRGBDecodeValue(context, params))
5764 {
5765 return false;
5766 }
5767 break;
5768
Luc Ferron1b1a8642018-01-23 15:12:01 -05005769 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5770 {
5771 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5772 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5773 {
5774 return false;
5775 }
5776 }
5777 break;
5778
Jamie Madill9696d072017-08-26 23:19:57 -04005779 default:
5780 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5781 return false;
5782 }
5783
5784 return true;
5785}
5786
5787template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5788template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5789
5790bool ValidateGetSamplerParameterBase(Context *context,
5791 GLuint sampler,
5792 GLenum pname,
5793 GLsizei *length)
5794{
5795 if (length)
5796 {
5797 *length = 0;
5798 }
5799
5800 if (context->getClientMajorVersion() < 3)
5801 {
5802 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5803 return false;
5804 }
5805
5806 if (!context->isSampler(sampler))
5807 {
5808 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5809 return false;
5810 }
5811
5812 switch (pname)
5813 {
5814 case GL_TEXTURE_WRAP_S:
5815 case GL_TEXTURE_WRAP_T:
5816 case GL_TEXTURE_WRAP_R:
5817 case GL_TEXTURE_MIN_FILTER:
5818 case GL_TEXTURE_MAG_FILTER:
5819 case GL_TEXTURE_MIN_LOD:
5820 case GL_TEXTURE_MAX_LOD:
5821 case GL_TEXTURE_COMPARE_MODE:
5822 case GL_TEXTURE_COMPARE_FUNC:
5823 break;
5824
Luc Ferron1b1a8642018-01-23 15:12:01 -05005825 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5826 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
5827 {
5828 return false;
5829 }
5830 break;
5831
Jamie Madill9696d072017-08-26 23:19:57 -04005832 case GL_TEXTURE_SRGB_DECODE_EXT:
5833 if (!context->getExtensions().textureSRGBDecode)
5834 {
5835 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5836 return false;
5837 }
5838 break;
5839
5840 default:
5841 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5842 return false;
5843 }
5844
5845 if (length)
5846 {
5847 *length = 1;
5848 }
5849 return true;
5850}
5851
5852bool ValidateGetInternalFormativBase(Context *context,
5853 GLenum target,
5854 GLenum internalformat,
5855 GLenum pname,
5856 GLsizei bufSize,
5857 GLsizei *numParams)
5858{
5859 if (numParams)
5860 {
5861 *numParams = 0;
5862 }
5863
5864 if (context->getClientMajorVersion() < 3)
5865 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005866 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005867 return false;
5868 }
5869
5870 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5871 if (!formatCaps.renderable)
5872 {
5873 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5874 return false;
5875 }
5876
5877 switch (target)
5878 {
5879 case GL_RENDERBUFFER:
5880 break;
5881
5882 case GL_TEXTURE_2D_MULTISAMPLE:
5883 if (context->getClientVersion() < ES_3_1)
5884 {
5885 context->handleError(InvalidOperation()
5886 << "Texture target requires at least OpenGL ES 3.1.");
5887 return false;
5888 }
5889 break;
5890
5891 default:
5892 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5893 return false;
5894 }
5895
5896 if (bufSize < 0)
5897 {
5898 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5899 return false;
5900 }
5901
5902 GLsizei maxWriteParams = 0;
5903 switch (pname)
5904 {
5905 case GL_NUM_SAMPLE_COUNTS:
5906 maxWriteParams = 1;
5907 break;
5908
5909 case GL_SAMPLES:
5910 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5911 break;
5912
5913 default:
5914 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5915 return false;
5916 }
5917
5918 if (numParams)
5919 {
5920 // glGetInternalFormativ will not overflow bufSize
5921 *numParams = std::min(bufSize, maxWriteParams);
5922 }
5923
5924 return true;
5925}
5926
Jamie Madillc29968b2016-01-20 11:17:23 -05005927} // namespace gl