blob: 86c898f75bd79ab27d3a60552f2ade8436f754f3 [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 Madille98b1b52018-03-08 09:47:23 -05001248 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madill48faf802014-11-06 15:27:22 -05001249 {
Jamie Madill48faf802014-11-06 15:27:22 -05001250 return false;
1251 }
1252
Jamie Madille98b1b52018-03-08 09:47:23 -05001253 if (!ValidateFramebufferComplete(context, drawFramebuffer, true))
Jamie Madill48faf802014-11-06 15:27:22 -05001254 {
Jamie Madill48faf802014-11-06 15:27:22 -05001255 return false;
1256 }
1257
Qin Jiajiaaef92162018-02-27 13:51:44 +08001258 if (readFramebuffer->id() == drawFramebuffer->id())
1259 {
1260 context->handleError(InvalidOperation());
1261 return false;
1262 }
1263
Jamie Madille98b1b52018-03-08 09:47:23 -05001264 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001265 {
Geoff Langb1196682014-07-23 13:47:29 -04001266 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001267 }
1268
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001269 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1270
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001271 if (mask & GL_COLOR_BUFFER_BIT)
1272 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001273 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001274 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001275
He Yunchao66a41a22016-12-15 16:45:05 +08001276 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001277 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001278 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001279
Geoff Langa15472a2015-08-11 11:48:03 -04001280 for (size_t drawbufferIdx = 0;
1281 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001282 {
Geoff Langa15472a2015-08-11 11:48:03 -04001283 const FramebufferAttachment *attachment =
1284 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1285 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001286 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001287 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001288
Geoff Langb2f3d052013-08-13 12:49:27 -04001289 // The GL ES 3.0.2 spec (pg 193) states that:
1290 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001291 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1292 // as well
1293 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1294 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001295 // Changes with EXT_color_buffer_float:
1296 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001297 GLenum readComponentType = readFormat.info->componentType;
1298 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001299 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001300 readComponentType == GL_SIGNED_NORMALIZED);
1301 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1302 drawComponentType == GL_SIGNED_NORMALIZED);
1303
1304 if (extensions.colorBufferFloat)
1305 {
1306 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1307 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1308
1309 if (readFixedOrFloat != drawFixedOrFloat)
1310 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001311 context->handleError(InvalidOperation()
1312 << "If the read buffer contains fixed-point or "
1313 "floating-point values, the draw buffer must "
1314 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001315 return false;
1316 }
1317 }
1318 else if (readFixedPoint != drawFixedPoint)
1319 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001320 context->handleError(InvalidOperation()
1321 << "If the read buffer contains fixed-point values, "
1322 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001323 return false;
1324 }
1325
1326 if (readComponentType == GL_UNSIGNED_INT &&
1327 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001328 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001329 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001330 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001331 }
1332
Jamie Madill6163c752015-12-07 16:32:59 -05001333 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001334 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001335 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001336 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001337 }
1338
Jamie Madilla3944d42016-07-22 22:13:26 -04001339 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001340 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001341 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001342 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001343 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001344 }
Geoff Lange4915782017-04-12 15:19:07 -04001345
1346 if (context->getExtensions().webglCompatibility &&
1347 *readColorBuffer == *attachment)
1348 {
1349 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001350 InvalidOperation()
1351 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001352 return false;
1353 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001354 }
1355 }
1356
Jamie Madilla3944d42016-07-22 22:13:26 -04001357 if ((readFormat.info->componentType == GL_INT ||
1358 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1359 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001360 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001361 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001362 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001363 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001364 }
He Yunchao66a41a22016-12-15 16:45:05 +08001365 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1366 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1367 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1368 // situation is an application error that would lead to a crash in ANGLE.
1369 else if (drawFramebuffer->hasEnabledDrawBuffer())
1370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001371 context->handleError(
1372 InvalidOperation()
1373 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001374 return false;
1375 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001376 }
1377
He Yunchaoced53ae2016-11-29 15:00:51 +08001378 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001379 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1380 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001381 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001382 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001383 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001384 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001385 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001386 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001387 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001388
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001389 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001390 {
Kenneth Russell69382852017-07-21 16:38:44 -04001391 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001392 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001393 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001394 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001395 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001396
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001397 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001398 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001399 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001400 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001401 }
Geoff Lange4915782017-04-12 15:19:07 -04001402
1403 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1404 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001405 context->handleError(
1406 InvalidOperation()
1407 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001408 return false;
1409 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001410 }
He Yunchao66a41a22016-12-15 16:45:05 +08001411 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1412 else if (drawBuffer)
1413 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001414 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1415 "depth/stencil attachment of a "
1416 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001417 return false;
1418 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001419 }
1420 }
1421
Martin Radeva3ed4572017-07-27 18:29:37 +03001422 // ANGLE_multiview, Revision 1:
1423 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1424 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1425 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1426 {
1427 context->handleError(InvalidFramebufferOperation()
1428 << "Attempt to read from a multi-view framebuffer.");
1429 return false;
1430 }
1431 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1432 {
1433 context->handleError(InvalidFramebufferOperation()
1434 << "Attempt to write to a multi-view framebuffer.");
1435 return false;
1436 }
1437
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001438 return true;
1439}
1440
Jamie Madill4928b7c2017-06-20 12:57:39 -04001441bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001442 GLint x,
1443 GLint y,
1444 GLsizei width,
1445 GLsizei height,
1446 GLenum format,
1447 GLenum type,
1448 GLsizei bufSize,
1449 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001450 GLsizei *columns,
1451 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001452 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001453{
1454 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001455 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001456 return false;
1457 }
1458
Geoff Lang62fce5b2016-09-30 10:46:35 -04001459 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001460 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001461 {
Geoff Langb1196682014-07-23 13:47:29 -04001462 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001463 }
1464
Geoff Lang62fce5b2016-09-30 10:46:35 -04001465 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001466 {
Geoff Langb1196682014-07-23 13:47:29 -04001467 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001468 }
1469
Jamie Madillc29968b2016-01-20 11:17:23 -05001470 return true;
1471}
1472
1473bool ValidateReadnPixelsEXT(Context *context,
1474 GLint x,
1475 GLint y,
1476 GLsizei width,
1477 GLsizei height,
1478 GLenum format,
1479 GLenum type,
1480 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001481 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001482{
1483 if (bufSize < 0)
1484 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001485 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001486 return false;
1487 }
1488
Geoff Lang62fce5b2016-09-30 10:46:35 -04001489 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001490 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001491}
Jamie Madill26e91952014-03-05 15:01:27 -05001492
Jamie Madill4928b7c2017-06-20 12:57:39 -04001493bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001494 GLint x,
1495 GLint y,
1496 GLsizei width,
1497 GLsizei height,
1498 GLenum format,
1499 GLenum type,
1500 GLsizei bufSize,
1501 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001502 GLsizei *columns,
1503 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001504 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001505{
1506 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001507 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001508 return false;
1509 }
1510
Geoff Lange93daba2017-03-30 13:54:40 -04001511 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1512 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001513 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001514 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001515 }
1516
Geoff Lang62fce5b2016-09-30 10:46:35 -04001517 if (!ValidateRobustBufferSize(context, bufSize, *length))
1518 {
1519 return false;
1520 }
1521
1522 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001523}
1524
Jamie Madillf0e04492017-08-26 15:28:42 -04001525bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001526{
1527 if (!context->getExtensions().occlusionQueryBoolean &&
1528 !context->getExtensions().disjointTimerQuery)
1529 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001530 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001531 return false;
1532 }
1533
Olli Etuaho41997e72016-03-10 13:38:39 +02001534 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001535}
1536
Jamie Madillf0e04492017-08-26 15:28:42 -04001537bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001538{
1539 if (!context->getExtensions().occlusionQueryBoolean &&
1540 !context->getExtensions().disjointTimerQuery)
1541 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001542 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001543 return false;
1544 }
1545
Olli Etuaho41997e72016-03-10 13:38:39 +02001546 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001547}
1548
Jamie Madillf0e04492017-08-26 15:28:42 -04001549bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1550{
1551 if (!context->getExtensions().occlusionQueryBoolean &&
1552 !context->getExtensions().disjointTimerQuery)
1553 {
1554 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1555 return false;
1556 }
1557
1558 return true;
1559}
1560
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001561bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001562{
1563 if (!ValidQueryType(context, target))
1564 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001565 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001566 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001567 }
1568
1569 if (id == 0)
1570 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001571 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001572 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001573 }
1574
1575 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1576 // of zero, if the active query object name for <target> is non-zero (for the
1577 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1578 // the active query for either target is non-zero), if <id> is the name of an
1579 // existing query object whose type does not match <target>, or if <id> is the
1580 // active query object name for any query type, the error INVALID_OPERATION is
1581 // generated.
1582
1583 // Ensure no other queries are active
1584 // NOTE: If other queries than occlusion are supported, we will need to check
1585 // separately that:
1586 // a) The query ID passed is not the current active query for any target/type
1587 // b) There are no active queries for the requested target (and in the case
1588 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1589 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001590
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001591 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001592 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001593 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001594 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001595 }
1596
1597 Query *queryObject = context->getQuery(id, true, target);
1598
1599 // check that name was obtained with glGenQueries
1600 if (!queryObject)
1601 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001602 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001603 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001604 }
1605
1606 // check for type mismatch
1607 if (queryObject->getType() != target)
1608 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001609 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001610 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001611 }
1612
1613 return true;
1614}
1615
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001616bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1617{
1618 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001619 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001620 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001621 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001622 return false;
1623 }
1624
1625 return ValidateBeginQueryBase(context, target, id);
1626}
1627
1628bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001629{
1630 if (!ValidQueryType(context, target))
1631 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001632 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001633 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001634 }
1635
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001636 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001637
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001638 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001639 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001640 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001641 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001642 }
1643
Jamie Madill45c785d2014-05-13 14:09:34 -04001644 return true;
1645}
1646
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001647bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1648{
1649 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001650 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001651 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001652 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001653 return false;
1654 }
1655
1656 return ValidateEndQueryBase(context, target);
1657}
1658
1659bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1660{
1661 if (!context->getExtensions().disjointTimerQuery)
1662 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001663 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001664 return false;
1665 }
1666
1667 if (target != GL_TIMESTAMP_EXT)
1668 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001669 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001670 return false;
1671 }
1672
1673 Query *queryObject = context->getQuery(id, true, target);
1674 if (queryObject == nullptr)
1675 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001676 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001677 return false;
1678 }
1679
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001680 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001681 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001682 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001683 return false;
1684 }
1685
1686 return true;
1687}
1688
Geoff Lang2186c382016-10-14 10:54:54 -04001689bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001690{
Geoff Lang2186c382016-10-14 10:54:54 -04001691 if (numParams)
1692 {
1693 *numParams = 0;
1694 }
1695
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001696 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1697 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001698 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001699 return false;
1700 }
1701
1702 switch (pname)
1703 {
1704 case GL_CURRENT_QUERY_EXT:
1705 if (target == GL_TIMESTAMP_EXT)
1706 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001707 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001708 return false;
1709 }
1710 break;
1711 case GL_QUERY_COUNTER_BITS_EXT:
1712 if (!context->getExtensions().disjointTimerQuery ||
1713 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1714 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001715 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001716 return false;
1717 }
1718 break;
1719 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001720 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001721 return false;
1722 }
1723
Geoff Lang2186c382016-10-14 10:54:54 -04001724 if (numParams)
1725 {
1726 // All queries return only one value
1727 *numParams = 1;
1728 }
1729
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001730 return true;
1731}
1732
1733bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1734{
1735 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001736 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001737 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001738 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001739 return false;
1740 }
1741
Geoff Lang2186c382016-10-14 10:54:54 -04001742 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001743}
1744
Geoff Lang2186c382016-10-14 10:54:54 -04001745bool ValidateGetQueryivRobustANGLE(Context *context,
1746 GLenum target,
1747 GLenum pname,
1748 GLsizei bufSize,
1749 GLsizei *length,
1750 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001751{
Geoff Lang2186c382016-10-14 10:54:54 -04001752 if (!ValidateRobustEntryPoint(context, bufSize))
1753 {
1754 return false;
1755 }
1756
1757 if (!ValidateGetQueryivBase(context, target, pname, length))
1758 {
1759 return false;
1760 }
1761
1762 if (!ValidateRobustBufferSize(context, bufSize, *length))
1763 {
1764 return false;
1765 }
1766
1767 return true;
1768}
1769
1770bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1771{
1772 if (numParams)
1773 {
1774 *numParams = 0;
1775 }
1776
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001777 Query *queryObject = context->getQuery(id, false, GL_NONE);
1778
1779 if (!queryObject)
1780 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001781 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001782 return false;
1783 }
1784
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001785 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001786 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001787 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001788 return false;
1789 }
1790
1791 switch (pname)
1792 {
1793 case GL_QUERY_RESULT_EXT:
1794 case GL_QUERY_RESULT_AVAILABLE_EXT:
1795 break;
1796
1797 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001798 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001799 return false;
1800 }
1801
Geoff Lang2186c382016-10-14 10:54:54 -04001802 if (numParams)
1803 {
1804 *numParams = 1;
1805 }
1806
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001807 return true;
1808}
1809
1810bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1811{
1812 if (!context->getExtensions().disjointTimerQuery)
1813 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001814 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001815 return false;
1816 }
Geoff Lang2186c382016-10-14 10:54:54 -04001817 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1818}
1819
1820bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1821 GLuint id,
1822 GLenum pname,
1823 GLsizei bufSize,
1824 GLsizei *length,
1825 GLint *params)
1826{
1827 if (!context->getExtensions().disjointTimerQuery)
1828 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001829 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001830 return false;
1831 }
1832
1833 if (!ValidateRobustEntryPoint(context, bufSize))
1834 {
1835 return false;
1836 }
1837
1838 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1839 {
1840 return false;
1841 }
1842
1843 if (!ValidateRobustBufferSize(context, bufSize, *length))
1844 {
1845 return false;
1846 }
1847
1848 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001849}
1850
1851bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1852{
1853 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001854 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001855 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001856 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001857 return false;
1858 }
Geoff Lang2186c382016-10-14 10:54:54 -04001859 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1860}
1861
1862bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1863 GLuint id,
1864 GLenum pname,
1865 GLsizei bufSize,
1866 GLsizei *length,
1867 GLuint *params)
1868{
1869 if (!context->getExtensions().disjointTimerQuery &&
1870 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1871 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001872 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001873 return false;
1874 }
1875
1876 if (!ValidateRobustEntryPoint(context, bufSize))
1877 {
1878 return false;
1879 }
1880
1881 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1882 {
1883 return false;
1884 }
1885
1886 if (!ValidateRobustBufferSize(context, bufSize, *length))
1887 {
1888 return false;
1889 }
1890
1891 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001892}
1893
1894bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1895{
1896 if (!context->getExtensions().disjointTimerQuery)
1897 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001898 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001899 return false;
1900 }
Geoff Lang2186c382016-10-14 10:54:54 -04001901 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1902}
1903
1904bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1905 GLuint id,
1906 GLenum pname,
1907 GLsizei bufSize,
1908 GLsizei *length,
1909 GLint64 *params)
1910{
1911 if (!context->getExtensions().disjointTimerQuery)
1912 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001913 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001914 return false;
1915 }
1916
1917 if (!ValidateRobustEntryPoint(context, bufSize))
1918 {
1919 return false;
1920 }
1921
1922 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1923 {
1924 return false;
1925 }
1926
1927 if (!ValidateRobustBufferSize(context, bufSize, *length))
1928 {
1929 return false;
1930 }
1931
1932 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001933}
1934
1935bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1936{
1937 if (!context->getExtensions().disjointTimerQuery)
1938 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001939 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001940 return false;
1941 }
Geoff Lang2186c382016-10-14 10:54:54 -04001942 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1943}
1944
1945bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1946 GLuint id,
1947 GLenum pname,
1948 GLsizei bufSize,
1949 GLsizei *length,
1950 GLuint64 *params)
1951{
1952 if (!context->getExtensions().disjointTimerQuery)
1953 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001954 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001955 return false;
1956 }
1957
1958 if (!ValidateRobustEntryPoint(context, bufSize))
1959 {
1960 return false;
1961 }
1962
1963 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1964 {
1965 return false;
1966 }
1967
1968 if (!ValidateRobustBufferSize(context, bufSize, *length))
1969 {
1970 return false;
1971 }
1972
1973 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001974}
1975
Jamie Madill5b772312018-03-08 20:28:32 -05001976bool ValidateUniformCommonBase(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08001977 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05001978 GLint location,
1979 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08001980 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05001981{
Jiajia Qin5451d532017-11-16 17:16:34 +08001982 // TODO(Jiajia): Add image uniform check in future.
1983 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05001984 {
Jiajia Qin5451d532017-11-16 17:16:34 +08001985 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05001986 return false;
1987 }
1988
Jiajia Qin5451d532017-11-16 17:16:34 +08001989 if (!program)
1990 {
1991 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
1992 return false;
1993 }
1994
1995 if (!program->isLinked())
1996 {
1997 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
1998 return false;
1999 }
2000
2001 if (location == -1)
2002 {
2003 // Silently ignore the uniform command
2004 return false;
2005 }
2006
2007 const auto &uniformLocations = program->getUniformLocations();
2008 size_t castedLocation = static_cast<size_t>(location);
2009 if (castedLocation >= uniformLocations.size())
2010 {
2011 context->handleError(InvalidOperation() << "Invalid uniform location");
2012 return false;
2013 }
2014
2015 const auto &uniformLocation = uniformLocations[castedLocation];
2016 if (uniformLocation.ignored)
2017 {
2018 // Silently ignore the uniform command
2019 return false;
2020 }
2021
2022 if (!uniformLocation.used())
2023 {
2024 context->handleError(InvalidOperation());
2025 return false;
2026 }
2027
2028 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2029
2030 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2031 if (!uniform.isArray() && count > 1)
2032 {
2033 context->handleError(InvalidOperation());
2034 return false;
2035 }
2036
2037 *uniformOut = &uniform;
2038 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002039}
2040
Jamie Madill5b772312018-03-08 20:28:32 -05002041bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002042 GLenum uniformType,
2043 GLsizei count,
2044 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002045{
Jiajia Qin5451d532017-11-16 17:16:34 +08002046 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2047 // It is compatible with INT or BOOL.
2048 // Do these cheap tests first, for a little extra speed.
2049 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002050 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002051 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002052 }
2053
Jiajia Qin5451d532017-11-16 17:16:34 +08002054 if (IsSamplerType(uniformType))
2055 {
2056 // Check that the values are in range.
2057 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2058 for (GLsizei i = 0; i < count; ++i)
2059 {
2060 if (value[i] < 0 || value[i] >= max)
2061 {
2062 context->handleError(InvalidValue() << "sampler uniform value out of range");
2063 return false;
2064 }
2065 }
2066 return true;
2067 }
2068
2069 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2070 return false;
2071}
2072
Jamie Madill5b772312018-03-08 20:28:32 -05002073bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002074{
2075 // Check that the value type is compatible with uniform type.
2076 // Do the cheaper test first, for a little extra speed.
2077 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2078 {
2079 return true;
2080 }
2081
2082 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2083 return false;
2084}
2085
Jamie Madill5b772312018-03-08 20:28:32 -05002086bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002087{
2088 // Check that the value type is compatible with uniform type.
2089 if (valueType == uniformType)
2090 {
2091 return true;
2092 }
2093
2094 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2095 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002096}
2097
Jamie Madill5b772312018-03-08 20:28:32 -05002098bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002099{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002100 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002101 gl::Program *programObject = context->getGLState().getProgram();
2102 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2103 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002104}
2105
Jamie Madill5b772312018-03-08 20:28:32 -05002106bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002107{
2108 const LinkedUniform *uniform = nullptr;
2109 gl::Program *programObject = context->getGLState().getProgram();
2110 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2111 ValidateUniform1ivValue(context, uniform->type, count, value);
2112}
2113
Jamie Madill5b772312018-03-08 20:28:32 -05002114bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002115 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002116 GLint location,
2117 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002118 GLboolean transpose)
2119{
Geoff Lang92019432017-11-20 13:09:34 -05002120 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002121 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002122 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002123 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002124 }
2125
Jamie Madill62d31cb2015-09-11 13:25:51 -04002126 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002127 gl::Program *programObject = context->getGLState().getProgram();
2128 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2129 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002130}
2131
Jamie Madill5b772312018-03-08 20:28:32 -05002132bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002133{
2134 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2135 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002136 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002137 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002138 }
2139
Jamie Madill0af26e12015-03-05 19:54:33 -05002140 const Caps &caps = context->getCaps();
2141
Jamie Madill893ab082014-05-16 16:56:10 -04002142 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2143 {
2144 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2145
Jamie Madill0af26e12015-03-05 19:54:33 -05002146 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002147 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002148 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002149 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002150 }
2151 }
2152
2153 switch (pname)
2154 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002155 case GL_TEXTURE_BINDING_2D:
2156 case GL_TEXTURE_BINDING_CUBE_MAP:
2157 case GL_TEXTURE_BINDING_3D:
2158 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002159 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002160 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002161 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2162 if (!context->getExtensions().textureRectangle)
2163 {
2164 context->handleError(InvalidEnum()
2165 << "ANGLE_texture_rectangle extension not present");
2166 return false;
2167 }
2168 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002169 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2170 if (!context->getExtensions().eglStreamConsumerExternal &&
2171 !context->getExtensions().eglImageExternal)
2172 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002173 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2174 "nor GL_OES_EGL_image_external "
2175 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002176 return false;
2177 }
2178 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002179
He Yunchaoced53ae2016-11-29 15:00:51 +08002180 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2181 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002182 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002183 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2184 ASSERT(readFramebuffer);
2185
2186 if (!ValidateFramebufferComplete(context, readFramebuffer, false))
Jamie Madill893ab082014-05-16 16:56:10 -04002187 {
Geoff Langb1196682014-07-23 13:47:29 -04002188 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002189 }
2190
Jamie Madille98b1b52018-03-08 09:47:23 -05002191 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002192 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002193 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002194 return false;
2195 }
2196
Jamie Madille98b1b52018-03-08 09:47:23 -05002197 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002198 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002199 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002200 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002201 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002202 }
2203 }
2204 break;
2205
He Yunchaoced53ae2016-11-29 15:00:51 +08002206 default:
2207 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002208 }
2209
2210 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002211 if (*numParams == 0)
2212 {
2213 return false;
2214 }
2215
2216 return true;
2217}
2218
Jamie Madill5b772312018-03-08 20:28:32 -05002219bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002220 GLenum pname,
2221 GLsizei bufSize,
2222 GLenum *nativeType,
2223 unsigned int *numParams)
2224{
2225 if (!ValidateRobustEntryPoint(context, bufSize))
2226 {
2227 return false;
2228 }
2229
2230 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2231 {
2232 return false;
2233 }
2234
2235 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002236 {
2237 return false;
2238 }
2239
2240 return true;
2241}
2242
Jamie Madill5b772312018-03-08 20:28:32 -05002243bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002244 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002245 GLint level,
2246 GLenum internalformat,
2247 bool isSubImage,
2248 GLint xoffset,
2249 GLint yoffset,
2250 GLint zoffset,
2251 GLint x,
2252 GLint y,
2253 GLsizei width,
2254 GLsizei height,
2255 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002256 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002257{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002258 TextureType texType = TextureTargetToType(target);
2259
Brandon Jones6cad5662017-06-14 13:25:13 -07002260 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002261 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002262 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2263 return false;
2264 }
2265
2266 if (width < 0 || height < 0)
2267 {
2268 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002269 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002270 }
2271
He Yunchaoced53ae2016-11-29 15:00:51 +08002272 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2273 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002274 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002275 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002276 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002277 }
2278
2279 if (border != 0)
2280 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002281 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002282 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002283 }
2284
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002285 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002286 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002287 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002288 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002289 }
2290
Jamie Madille98b1b52018-03-08 09:47:23 -05002291 const gl::State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002292 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madille98b1b52018-03-08 09:47:23 -05002293 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madill560a8d82014-05-21 13:06:20 -04002294 {
Geoff Langb1196682014-07-23 13:47:29 -04002295 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002296 }
2297
Jamie Madille98b1b52018-03-08 09:47:23 -05002298 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002299 {
Geoff Langb1196682014-07-23 13:47:29 -04002300 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002301 }
2302
Martin Radev138064f2016-07-15 12:03:41 +03002303 if (readFramebuffer->getReadBufferState() == GL_NONE)
2304 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002305 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002306 return false;
2307 }
2308
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002309 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2310 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002311 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002312 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002313 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2314 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002315 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002316 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002317 return false;
2318 }
2319
Martin Radev04e2c3b2017-07-27 16:54:35 +03002320 // ANGLE_multiview spec, Revision 1:
2321 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2322 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2323 // is not NONE.
2324 if (source->getMultiviewLayout() != GL_NONE)
2325 {
2326 context->handleError(InvalidFramebufferOperation()
2327 << "The active read framebuffer object has multiview attachments.");
2328 return false;
2329 }
2330
Geoff Langaae65a42014-05-26 12:43:44 -04002331 const gl::Caps &caps = context->getCaps();
2332
Geoff Langaae65a42014-05-26 12:43:44 -04002333 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002334 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002335 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002336 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002337 maxDimension = caps.max2DTextureSize;
2338 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002339
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002340 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002341 maxDimension = caps.maxCubeMapTextureSize;
2342 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002343
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002344 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002345 maxDimension = caps.maxRectangleTextureSize;
2346 break;
2347
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002348 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002349 maxDimension = caps.max2DTextureSize;
2350 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002351
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002352 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002353 maxDimension = caps.max3DTextureSize;
2354 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002355
He Yunchaoced53ae2016-11-29 15:00:51 +08002356 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002357 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002358 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002359 }
2360
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002361 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002362 if (!texture)
2363 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002364 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002365 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002366 }
2367
Geoff Lang69cce582015-09-17 13:20:36 -04002368 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002369 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002370 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002371 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002372 }
2373
Geoff Langca271392017-04-05 12:30:00 -04002374 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002375 isSubImage ? *texture->getFormat(target, level).info
2376 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002377
Geoff Lang966c9402017-04-18 12:38:27 -04002378 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002379 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002380 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002381 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002382 }
2383
2384 if (isSubImage)
2385 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002386 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2387 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2388 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002389 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002390 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002391 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002392 }
2393 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002394 else
2395 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002396 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002397 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002398 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002399 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002400 }
2401
Geoff Langeb66a6e2016-10-31 13:06:12 -04002402 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002403 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002404 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002405 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002406 }
2407
2408 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002409 if (static_cast<int>(width) > maxLevelDimension ||
2410 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002411 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002412 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002413 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002414 }
2415 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002416
Jamie Madill0c8abca2016-07-22 20:21:26 -04002417 if (textureFormatOut)
2418 {
2419 *textureFormatOut = texture->getFormat(target, level);
2420 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002421
2422 // Detect texture copying feedback loops for WebGL.
2423 if (context->getExtensions().webglCompatibility)
2424 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002425 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002426 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002427 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002428 return false;
2429 }
2430 }
2431
Jamie Madill560a8d82014-05-21 13:06:20 -04002432 return true;
2433}
2434
Jamie Madill5b772312018-03-08 20:28:32 -05002435bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002436{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002437 switch (mode)
2438 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002439 case GL_POINTS:
2440 case GL_LINES:
2441 case GL_LINE_LOOP:
2442 case GL_LINE_STRIP:
2443 case GL_TRIANGLES:
2444 case GL_TRIANGLE_STRIP:
2445 case GL_TRIANGLE_FAN:
2446 break;
2447 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002448 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002449 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002450 }
2451
Jamie Madill250d33f2014-06-06 17:09:03 -04002452 if (count < 0)
2453 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002454 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002455 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002456 }
2457
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002458 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002459
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002460 const Extensions &extensions = context->getExtensions();
2461
2462 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2463 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2464 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2465 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002466 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002467 // Check for mapped buffers
2468 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002469 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002470 {
2471 context->handleError(InvalidOperation());
2472 return false;
2473 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002474 }
2475
Jamie Madillcbcde722017-01-06 14:50:00 -05002476 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2477 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002478 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002479 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002480 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002481 const FramebufferAttachment *dsAttachment =
2482 framebuffer->getStencilOrDepthStencilAttachment();
2483 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002484 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002485 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002486
2487 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2488 bool differentWritemasks =
2489 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2490 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2491 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2492 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2493
2494 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002495 {
Martin Radevffe754b2017-07-31 10:38:07 +03002496 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002497 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002498 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2499 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002500 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002501 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002502 return false;
2503 }
Jamie Madillac528012014-06-20 13:21:23 -04002504 }
2505
Jamie Madille98b1b52018-03-08 09:47:23 -05002506 if (!ValidateFramebufferComplete(context, framebuffer, true))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002507 {
Geoff Langb1196682014-07-23 13:47:29 -04002508 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002509 }
2510
Geoff Lang7dd2e102014-11-10 15:19:26 -05002511 gl::Program *program = state.getProgram();
2512 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002513 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002514 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002515 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002516 }
2517
Yunchao Hecddcb592017-11-13 15:27:35 +08002518 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2519 // vertex shader stage or fragment shader stage is a undefined behaviour.
2520 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2521 // produce undefined result.
Yunchao Heece12532017-11-21 15:50:21 +08002522 if (!program->hasLinkedVertexShader() || !program->hasLinkedFragmentShader())
Yunchao Hecddcb592017-11-13 15:27:35 +08002523 {
2524 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2525 "vertex shader stage or fragment shader stage.");
2526 return false;
2527 }
2528
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002529 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002530 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002531 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002532 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002533 }
2534
Martin Radevffe754b2017-07-31 10:38:07 +03002535 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002536 {
Martin Radevda8e2572017-09-12 17:21:16 +03002537 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002538 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002539 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002540 {
2541 context->handleError(InvalidOperation() << "The number of views in the active program "
2542 "and draw framebuffer does not match.");
2543 return false;
2544 }
Martin Radev7e69f762017-07-27 14:54:13 +03002545
2546 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2547 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2548 framebufferNumViews > 1)
2549 {
2550 context->handleError(InvalidOperation()
2551 << "There is an active transform feedback object "
2552 "when the number of views in the active draw "
2553 "framebuffer is greater than 1.");
2554 return false;
2555 }
Martin Radevffe754b2017-07-31 10:38:07 +03002556
2557 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2558 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2559 {
2560 context->handleError(InvalidOperation() << "There is an active query for target "
2561 "GL_TIME_ELAPSED_EXT when the number of "
2562 "views in the active draw framebuffer is "
2563 "greater than 1.");
2564 return false;
2565 }
Martin Radev7cf61662017-07-26 17:10:53 +03002566 }
2567
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002568 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002569 for (unsigned int uniformBlockIndex = 0;
2570 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002571 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002572 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002573 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002574 const OffsetBindingPointer<Buffer> &uniformBuffer =
2575 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002576
Geoff Lang5d124a62015-09-15 13:03:27 -04002577 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002578 {
2579 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002580 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002581 InvalidOperation()
2582 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002583 return false;
2584 }
2585
Geoff Lang5d124a62015-09-15 13:03:27 -04002586 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002587 if (uniformBufferSize == 0)
2588 {
2589 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002590 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002591 }
2592
Jamie Madill62d31cb2015-09-11 13:25:51 -04002593 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002594 {
2595 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002596 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002597 InvalidOperation()
2598 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002599 return false;
2600 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002601
2602 if (extensions.webglCompatibility &&
2603 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2604 {
2605 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2606 UniformBufferBoundForTransformFeedback);
2607 return false;
2608 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002609 }
2610
Geoff Lange0cff192017-05-30 13:04:56 -04002611 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002612 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002613 {
James Darpiniane8a93c62018-01-04 18:02:24 -08002614 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2615 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2616 transformFeedbackObject->buffersBoundForOtherUse())
2617 {
2618 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferDoubleBound);
2619 return false;
2620 }
Geoff Lange0cff192017-05-30 13:04:56 -04002621 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002622 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2623 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002624 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002625 return false;
2626 }
Geoff Lange0cff192017-05-30 13:04:56 -04002627
Geoff Lang9ab5b822017-05-30 16:19:23 -04002628 // Detect that the vertex shader input types match the attribute types
2629 if (!ValidateVertexShaderAttributeTypeMatch(context))
2630 {
2631 return false;
2632 }
2633
Geoff Lange0cff192017-05-30 13:04:56 -04002634 // Detect that the color buffer types match the fragment shader output types
2635 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2636 {
2637 return false;
2638 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002639 }
2640
Jamie Madill9fdaa492018-02-16 10:52:11 -05002641 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002642}
2643
Jamie Madill5b772312018-03-08 20:28:32 -05002644bool ValidateDrawArraysCommon(Context *context,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002645 GLenum mode,
2646 GLint first,
2647 GLsizei count,
2648 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002649{
Jamie Madillfd716582014-06-06 17:09:04 -04002650 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002651 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002652 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002653 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002654 }
2655
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002656 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002657 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002658 if (curTransformFeedback && curTransformFeedback->isActive() &&
2659 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002660 {
2661 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002662 // that does not match the current transform feedback object's draw mode (if transform
2663 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002664 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002665 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002666 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002667 }
2668
Jiajia Qind9671222016-11-29 16:30:31 +08002669 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002670 {
2671 return false;
2672 }
2673
Corentin Wallez71168a02016-12-19 15:11:18 -08002674 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002675 // - first < 0 has been checked as an error condition.
2676 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002677 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002678 ASSERT(first >= 0);
2679 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002680 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002681 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2682 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2683 {
2684 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2685 return false;
2686 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002687
Jamie Madill9fdaa492018-02-16 10:52:11 -05002688 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2689 {
2690 return false;
2691 }
Jamie Madillfd716582014-06-06 17:09:04 -04002692 }
2693
2694 return true;
2695}
2696
He Yunchaoced53ae2016-11-29 15:00:51 +08002697bool ValidateDrawArraysInstancedANGLE(Context *context,
2698 GLenum mode,
2699 GLint first,
2700 GLsizei count,
2701 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002702{
Geoff Lang63c5a592017-09-27 14:08:16 -04002703 if (!context->getExtensions().instancedArrays)
2704 {
2705 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2706 return false;
2707 }
2708
Corentin Wallez170efbf2017-05-02 13:45:01 -04002709 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002710 {
2711 return false;
2712 }
2713
Corentin Wallez0dc97812017-06-22 14:38:44 -04002714 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002715}
2716
Jamie Madill5b772312018-03-08 20:28:32 -05002717bool ValidateDrawElementsBase(Context *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002718{
Jamie Madill250d33f2014-06-06 17:09:03 -04002719 switch (type)
2720 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002721 case GL_UNSIGNED_BYTE:
2722 case GL_UNSIGNED_SHORT:
2723 break;
2724 case GL_UNSIGNED_INT:
2725 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2726 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002727 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002728 return false;
2729 }
2730 break;
2731 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002732 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002733 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002734 }
2735
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002736 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002737
2738 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002739 if (curTransformFeedback && curTransformFeedback->isActive() &&
2740 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002741 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002742 // It is an invalid operation to call DrawElements, DrawRangeElements or
2743 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002744 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002745 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002746 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002747 }
2748
Jiajia Qind9671222016-11-29 16:30:31 +08002749 return true;
2750}
2751
Jamie Madill5b772312018-03-08 20:28:32 -05002752bool ValidateDrawElementsCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002753 GLenum mode,
2754 GLsizei count,
2755 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002756 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002757 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002758{
2759 if (!ValidateDrawElementsBase(context, type))
2760 return false;
2761
2762 const State &state = context->getGLState();
2763
Corentin Wallez170efbf2017-05-02 13:45:01 -04002764 if (!ValidateDrawBase(context, mode, count))
2765 {
2766 return false;
2767 }
2768
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002769 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2770 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2771 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2772 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002773 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002774 // Check for mapped buffers
2775 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002776 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002777 {
2778 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2779 return false;
2780 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002781 }
2782
He Yunchaoced53ae2016-11-29 15:00:51 +08002783 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002784 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002785
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002786 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2787
2788 if (context->getExtensions().webglCompatibility)
2789 {
2790 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2791 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2792 {
2793 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2794 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2795 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002796 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002797 return false;
2798 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002799
2800 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2801 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2802 // error is generated.
2803 if (reinterpret_cast<intptr_t>(indices) < 0)
2804 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002805 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002806 return false;
2807 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002808 }
2809
2810 if (context->getExtensions().webglCompatibility ||
2811 !context->getGLState().areClientArraysEnabled())
2812 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002813 if (!elementArrayBuffer && count > 0)
2814 {
2815 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2816 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2817 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002818 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002819 return false;
2820 }
2821 }
2822
Jamie Madill9fdaa492018-02-16 10:52:11 -05002823 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04002824 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002825 // This is an application error that would normally result in a crash, but we catch it and
2826 // return an error
2827 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
2828 return false;
2829 }
2830
2831 if (count > 0 && elementArrayBuffer)
2832 {
2833 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2834 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2835 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2836 constexpr uint64_t kMaxTypeSize = 8;
2837 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2838 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2839 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
2840
2841 uint64_t typeSize = typeBytes;
2842 uint64_t elementCount = static_cast<uint64_t>(count);
2843 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2844
2845 // Doing the multiplication here is overflow-safe
2846 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2847
2848 // The offset can be any value, check for overflows
2849 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2850 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04002851 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002852 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2853 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002854 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05002855
2856 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2857 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002858 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002859 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
2860 return false;
2861 }
2862
2863 ASSERT(isPow2(typeSize) && typeSize > 0);
2864 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
2865 {
2866 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04002867 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002868 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002869
2870 if (context->getExtensions().webglCompatibility &&
2871 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
2872 {
2873 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2874 ElementArrayBufferBoundForTransformFeedback);
2875 return false;
2876 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002877 }
2878
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002879 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002880 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002881 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2882 // access is enabled.
2883 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2884 {
2885 return false;
2886 }
2887 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05002888 else if (count == 0)
2889 {
2890 // ValidateDrawAttribs also does some extra validation that is independent of the vertex
2891 // count.
2892 if (!ValidateDrawAttribs(context, 0, 0, 0))
2893 {
2894 return false;
2895 }
2896 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002897 else
2898 {
2899 // Use the parameter buffer to retrieve and cache the index range.
2900 const auto &params = context->getParams<HasIndexRange>();
2901 const auto &indexRangeOpt = params.getIndexRange();
2902 if (!indexRangeOpt.valid())
2903 {
2904 // Unexpected error.
2905 return false;
2906 }
2907
2908 // If we use an index greater than our maximum supported index range, return an error.
2909 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2910 // return an error if possible here.
2911 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2912 {
2913 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2914 return false;
2915 }
2916
2917 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2918 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2919 {
2920 return false;
2921 }
2922
2923 // No op if there are no real indices in the index data (all are primitive restart).
2924 return (indexRangeOpt.value().vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002925 }
2926
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002927 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002928}
2929
Jamie Madill5b772312018-03-08 20:28:32 -05002930bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002931 GLenum mode,
2932 GLsizei count,
2933 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002934 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002935 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002936{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002937 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002938}
2939
Geoff Lang3edfe032015-09-04 16:38:24 -04002940bool ValidateDrawElementsInstancedANGLE(Context *context,
2941 GLenum mode,
2942 GLsizei count,
2943 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002944 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002945 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002946{
Geoff Lang63c5a592017-09-27 14:08:16 -04002947 if (!context->getExtensions().instancedArrays)
2948 {
2949 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2950 return false;
2951 }
2952
Corentin Wallez170efbf2017-05-02 13:45:01 -04002953 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002954 {
2955 return false;
2956 }
2957
Corentin Wallez0dc97812017-06-22 14:38:44 -04002958 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002959}
2960
He Yunchaoced53ae2016-11-29 15:00:51 +08002961bool ValidateFramebufferTextureBase(Context *context,
2962 GLenum target,
2963 GLenum attachment,
2964 GLuint texture,
2965 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002966{
Geoff Lange8afa902017-09-27 15:00:43 -04002967 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002968 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002969 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002970 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002971 }
2972
2973 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002974 {
2975 return false;
2976 }
2977
Jamie Madill55ec3b12014-07-03 10:38:57 -04002978 if (texture != 0)
2979 {
2980 gl::Texture *tex = context->getTexture(texture);
2981
Luc Ferronadcf0ae2018-01-24 08:27:37 -05002982 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002983 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002984 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002985 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002986 }
2987
2988 if (level < 0)
2989 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002990 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002991 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002992 }
2993 }
2994
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002995 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002996 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002997
Jamie Madill84115c92015-04-23 15:00:07 -04002998 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002999 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003000 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003001 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003002 }
3003
3004 return true;
3005}
3006
Geoff Langb1196682014-07-23 13:47:29 -04003007bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003008{
3009 if (program == 0)
3010 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003011 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003012 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003013 }
3014
Dian Xiang769769a2015-09-09 15:20:08 -07003015 gl::Program *programObject = GetValidProgram(context, program);
3016 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003017 {
3018 return false;
3019 }
3020
Jamie Madill0063c512014-08-25 15:47:53 -04003021 if (!programObject || !programObject->isLinked())
3022 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003023 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003024 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003025 }
3026
Geoff Lang7dd2e102014-11-10 15:19:26 -05003027 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003028 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003029 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003030 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003031 }
3032
Jamie Madill0063c512014-08-25 15:47:53 -04003033 return true;
3034}
3035
Geoff Langf41d0ee2016-10-07 13:04:23 -04003036static bool ValidateSizedGetUniform(Context *context,
3037 GLuint program,
3038 GLint location,
3039 GLsizei bufSize,
3040 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003041{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003042 if (length)
3043 {
3044 *length = 0;
3045 }
3046
Jamie Madill78f41802014-08-25 15:47:55 -04003047 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003048 {
Jamie Madill78f41802014-08-25 15:47:55 -04003049 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003050 }
3051
Geoff Langf41d0ee2016-10-07 13:04:23 -04003052 if (bufSize < 0)
3053 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003054 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003055 return false;
3056 }
3057
Jamie Madilla502c742014-08-28 17:19:13 -04003058 gl::Program *programObject = context->getProgram(program);
3059 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003060
Jamie Madill78f41802014-08-25 15:47:55 -04003061 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003062 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003063 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003064 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003065 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003066 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003067 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003068 }
3069
Geoff Langf41d0ee2016-10-07 13:04:23 -04003070 if (length)
3071 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003072 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003073 }
3074
Jamie Madill0063c512014-08-25 15:47:53 -04003075 return true;
3076}
3077
He Yunchaoced53ae2016-11-29 15:00:51 +08003078bool ValidateGetnUniformfvEXT(Context *context,
3079 GLuint program,
3080 GLint location,
3081 GLsizei bufSize,
3082 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003083{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003084 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003085}
3086
He Yunchaoced53ae2016-11-29 15:00:51 +08003087bool ValidateGetnUniformivEXT(Context *context,
3088 GLuint program,
3089 GLint location,
3090 GLsizei bufSize,
3091 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003092{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003093 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3094}
3095
3096bool ValidateGetUniformfvRobustANGLE(Context *context,
3097 GLuint program,
3098 GLint location,
3099 GLsizei bufSize,
3100 GLsizei *length,
3101 GLfloat *params)
3102{
3103 if (!ValidateRobustEntryPoint(context, bufSize))
3104 {
3105 return false;
3106 }
3107
3108 // bufSize is validated in ValidateSizedGetUniform
3109 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3110}
3111
3112bool ValidateGetUniformivRobustANGLE(Context *context,
3113 GLuint program,
3114 GLint location,
3115 GLsizei bufSize,
3116 GLsizei *length,
3117 GLint *params)
3118{
3119 if (!ValidateRobustEntryPoint(context, bufSize))
3120 {
3121 return false;
3122 }
3123
3124 // bufSize is validated in ValidateSizedGetUniform
3125 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3126}
3127
3128bool ValidateGetUniformuivRobustANGLE(Context *context,
3129 GLuint program,
3130 GLint location,
3131 GLsizei bufSize,
3132 GLsizei *length,
3133 GLuint *params)
3134{
3135 if (!ValidateRobustEntryPoint(context, bufSize))
3136 {
3137 return false;
3138 }
3139
3140 if (context->getClientMajorVersion() < 3)
3141 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003142 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003143 return false;
3144 }
3145
3146 // bufSize is validated in ValidateSizedGetUniform
3147 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003148}
3149
He Yunchaoced53ae2016-11-29 15:00:51 +08003150bool ValidateDiscardFramebufferBase(Context *context,
3151 GLenum target,
3152 GLsizei numAttachments,
3153 const GLenum *attachments,
3154 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003155{
3156 if (numAttachments < 0)
3157 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003158 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003159 return false;
3160 }
3161
3162 for (GLsizei i = 0; i < numAttachments; ++i)
3163 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003164 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003165 {
3166 if (defaultFramebuffer)
3167 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003168 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003169 return false;
3170 }
3171
3172 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3173 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003174 context->handleError(InvalidOperation() << "Requested color attachment is "
3175 "greater than the maximum supported "
3176 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003177 return false;
3178 }
3179 }
3180 else
3181 {
3182 switch (attachments[i])
3183 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003184 case GL_DEPTH_ATTACHMENT:
3185 case GL_STENCIL_ATTACHMENT:
3186 case GL_DEPTH_STENCIL_ATTACHMENT:
3187 if (defaultFramebuffer)
3188 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003189 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3190 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003191 return false;
3192 }
3193 break;
3194 case GL_COLOR:
3195 case GL_DEPTH:
3196 case GL_STENCIL:
3197 if (!defaultFramebuffer)
3198 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003199 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3200 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003201 return false;
3202 }
3203 break;
3204 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003205 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003206 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003207 }
3208 }
3209 }
3210
3211 return true;
3212}
3213
Austin Kinross6ee1e782015-05-29 17:05:37 -07003214bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3215{
Jamie Madill007530e2017-12-28 14:27:04 -05003216 if (!context->getExtensions().debugMarker)
3217 {
3218 // The debug marker calls should not set error state
3219 // However, it seems reasonable to set an error state if the extension is not enabled
3220 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3221 return false;
3222 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003223
Jamie Madill007530e2017-12-28 14:27:04 -05003224 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003225 if (length < 0)
3226 {
3227 return false;
3228 }
3229
3230 if (marker == nullptr)
3231 {
3232 return false;
3233 }
3234
3235 return true;
3236}
3237
3238bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3239{
Jamie Madill007530e2017-12-28 14:27:04 -05003240 if (!context->getExtensions().debugMarker)
3241 {
3242 // The debug marker calls should not set error state
3243 // However, it seems reasonable to set an error state if the extension is not enabled
3244 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3245 return false;
3246 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003247
Jamie Madill007530e2017-12-28 14:27:04 -05003248 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003249 if (length < 0)
3250 {
3251 return false;
3252 }
3253
3254 if (length > 0 && marker == nullptr)
3255 {
3256 return false;
3257 }
3258
3259 return true;
3260}
3261
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003262bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003263{
Geoff Langa8406172015-07-21 16:53:39 -04003264 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3265 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003266 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003267 return false;
3268 }
3269
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003270 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003271 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003272 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003273 if (!context->getExtensions().eglImage)
3274 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003275 context->handleError(InvalidEnum()
3276 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003277 }
3278 break;
3279
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003280 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003281 if (!context->getExtensions().eglImageExternal)
3282 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003283 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3284 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003285 }
Geoff Langa8406172015-07-21 16:53:39 -04003286 break;
3287
3288 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003289 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003290 return false;
3291 }
3292
Jamie Madill007530e2017-12-28 14:27:04 -05003293 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3294
Jamie Madill61e16b42017-06-19 11:13:23 -04003295 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003296 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003297 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003298 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003299 return false;
3300 }
3301
Jamie Madill007530e2017-12-28 14:27:04 -05003302 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003303 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003304 context->handleError(InvalidOperation()
3305 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003306 return false;
3307 }
3308
Geoff Langca271392017-04-05 12:30:00 -04003309 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003310 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003311 if (!textureCaps.texturable)
3312 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003313 context->handleError(InvalidOperation()
3314 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003315 return false;
3316 }
3317
Geoff Langdcab33b2015-07-21 13:03:16 -04003318 return true;
3319}
3320
3321bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003322 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003323 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003324{
Geoff Langa8406172015-07-21 16:53:39 -04003325 if (!context->getExtensions().eglImage)
3326 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003327 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003328 return false;
3329 }
3330
3331 switch (target)
3332 {
3333 case GL_RENDERBUFFER:
3334 break;
3335
3336 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003337 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003338 return false;
3339 }
3340
Jamie Madill007530e2017-12-28 14:27:04 -05003341 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3342
Jamie Madill61e16b42017-06-19 11:13:23 -04003343 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003344 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003345 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003346 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003347 return false;
3348 }
3349
Geoff Langca271392017-04-05 12:30:00 -04003350 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003351 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003352 if (!textureCaps.renderable)
3353 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003354 context->handleError(InvalidOperation()
3355 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003356 return false;
3357 }
3358
Geoff Langdcab33b2015-07-21 13:03:16 -04003359 return true;
3360}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003361
3362bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3363{
Geoff Lang36167ab2015-12-07 10:27:14 -05003364 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003365 {
3366 // The default VAO should always exist
3367 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003368 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003369 return false;
3370 }
3371
3372 return true;
3373}
3374
Geoff Langc5629752015-12-07 16:29:04 -05003375bool ValidateProgramBinaryBase(Context *context,
3376 GLuint program,
3377 GLenum binaryFormat,
3378 const void *binary,
3379 GLint length)
3380{
3381 Program *programObject = GetValidProgram(context, program);
3382 if (programObject == nullptr)
3383 {
3384 return false;
3385 }
3386
3387 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3388 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3389 programBinaryFormats.end())
3390 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003391 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003392 return false;
3393 }
3394
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003395 if (context->hasActiveTransformFeedback(program))
3396 {
3397 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003398 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3399 "is associated with an active transform "
3400 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003401 return false;
3402 }
3403
Geoff Langc5629752015-12-07 16:29:04 -05003404 return true;
3405}
3406
3407bool ValidateGetProgramBinaryBase(Context *context,
3408 GLuint program,
3409 GLsizei bufSize,
3410 GLsizei *length,
3411 GLenum *binaryFormat,
3412 void *binary)
3413{
3414 Program *programObject = GetValidProgram(context, program);
3415 if (programObject == nullptr)
3416 {
3417 return false;
3418 }
3419
3420 if (!programObject->isLinked())
3421 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003422 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003423 return false;
3424 }
3425
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003426 if (context->getCaps().programBinaryFormats.empty())
3427 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003428 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003429 return false;
3430 }
3431
Geoff Langc5629752015-12-07 16:29:04 -05003432 return true;
3433}
Jamie Madillc29968b2016-01-20 11:17:23 -05003434
Jamie Madill5b772312018-03-08 20:28:32 -05003435bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003436{
3437 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003438 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003439 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003440 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3441 return false;
3442 }
3443 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3444 {
3445 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003446 return false;
3447 }
3448
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003449 ASSERT(context->getGLState().getDrawFramebuffer());
3450 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003451 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3452
3453 // This should come first before the check for the default frame buffer
3454 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3455 // rather than INVALID_OPERATION
3456 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3457 {
3458 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3459
3460 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003461 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3462 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003463 {
3464 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003465 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3466 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3467 // 3.1 is still a bit ambiguous about the error, but future specs are
3468 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003469 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003470 return false;
3471 }
3472 else if (bufs[colorAttachment] >= maxColorAttachment)
3473 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003474 context->handleError(InvalidOperation()
3475 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003476 return false;
3477 }
3478 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3479 frameBufferId != 0)
3480 {
3481 // INVALID_OPERATION-GL is bound to buffer and ith argument
3482 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003483 context->handleError(InvalidOperation()
3484 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003485 return false;
3486 }
3487 }
3488
3489 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3490 // and n is not 1 or bufs is bound to value other than BACK and NONE
3491 if (frameBufferId == 0)
3492 {
3493 if (n != 1)
3494 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003495 context->handleError(InvalidOperation()
3496 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003497 return false;
3498 }
3499
3500 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3501 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003502 context->handleError(
3503 InvalidOperation()
3504 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003505 return false;
3506 }
3507 }
3508
3509 return true;
3510}
3511
Geoff Lang496c02d2016-10-20 11:38:11 -07003512bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003513 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003514 GLenum pname,
3515 GLsizei *length,
3516 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003517{
Geoff Lang496c02d2016-10-20 11:38:11 -07003518 if (length)
3519 {
3520 *length = 0;
3521 }
3522
3523 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3524 {
3525 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003526 InvalidOperation()
3527 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003528 return false;
3529 }
3530
Corentin Walleze4477002017-12-01 14:39:58 -05003531 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003532 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003533 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003534 return false;
3535 }
3536
Geoff Lang496c02d2016-10-20 11:38:11 -07003537 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003538 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003539 case GL_BUFFER_MAP_POINTER:
3540 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003541
Geoff Lang496c02d2016-10-20 11:38:11 -07003542 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003543 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003544 return false;
3545 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003546
3547 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3548 // target bound to zero generate an INVALID_OPERATION error."
3549 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003550 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003551 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003552 context->handleError(InvalidOperation()
3553 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003554 return false;
3555 }
3556
Geoff Lang496c02d2016-10-20 11:38:11 -07003557 if (length)
3558 {
3559 *length = 1;
3560 }
3561
Olli Etuaho4f667482016-03-30 15:56:35 +03003562 return true;
3563}
3564
Corentin Wallez336129f2017-10-17 15:55:40 -04003565bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003566{
Corentin Walleze4477002017-12-01 14:39:58 -05003567 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003568 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003569 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003570 return false;
3571 }
3572
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003573 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003574
3575 if (buffer == nullptr || !buffer->isMapped())
3576 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003577 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003578 return false;
3579 }
3580
3581 return true;
3582}
3583
3584bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003585 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003586 GLintptr offset,
3587 GLsizeiptr length,
3588 GLbitfield access)
3589{
Corentin Walleze4477002017-12-01 14:39:58 -05003590 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003591 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003592 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003593 return false;
3594 }
3595
Brandon Jones6cad5662017-06-14 13:25:13 -07003596 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003597 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003598 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3599 return false;
3600 }
3601
3602 if (length < 0)
3603 {
3604 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003605 return false;
3606 }
3607
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003608 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003609
3610 if (!buffer)
3611 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003612 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003613 return false;
3614 }
3615
3616 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003617 CheckedNumeric<size_t> checkedOffset(offset);
3618 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003619
Jamie Madille2e406c2016-06-02 13:04:10 -04003620 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003621 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003622 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003623 return false;
3624 }
3625
3626 // Check for invalid bits in the mask
3627 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3628 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3629 GL_MAP_UNSYNCHRONIZED_BIT;
3630
3631 if (access & ~(allAccessBits))
3632 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003633 context->handleError(InvalidValue()
3634 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003635 return false;
3636 }
3637
3638 if (length == 0)
3639 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003640 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003641 return false;
3642 }
3643
3644 if (buffer->isMapped())
3645 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003646 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003647 return false;
3648 }
3649
3650 // Check for invalid bit combinations
3651 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3652 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003653 context->handleError(InvalidOperation()
3654 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003655 return false;
3656 }
3657
3658 GLbitfield writeOnlyBits =
3659 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3660
3661 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3662 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003663 context->handleError(InvalidOperation()
3664 << "Invalid access bits when mapping buffer for reading: 0x"
3665 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003666 return false;
3667 }
3668
3669 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3670 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003671 context->handleError(
3672 InvalidOperation()
3673 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003674 return false;
3675 }
Geoff Lang79f71042017-08-14 16:43:43 -04003676
3677 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003678}
3679
3680bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003681 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003682 GLintptr offset,
3683 GLsizeiptr length)
3684{
Brandon Jones6cad5662017-06-14 13:25:13 -07003685 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003686 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003687 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3688 return false;
3689 }
3690
3691 if (length < 0)
3692 {
3693 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003694 return false;
3695 }
3696
Corentin Walleze4477002017-12-01 14:39:58 -05003697 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003698 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003699 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003700 return false;
3701 }
3702
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003703 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003704
3705 if (buffer == nullptr)
3706 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003707 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003708 return false;
3709 }
3710
3711 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3712 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003713 context->handleError(InvalidOperation()
3714 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003715 return false;
3716 }
3717
3718 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003719 CheckedNumeric<size_t> checkedOffset(offset);
3720 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003721
Jamie Madille2e406c2016-06-02 13:04:10 -04003722 if (!checkedSize.IsValid() ||
3723 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003724 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003725 context->handleError(InvalidValue()
3726 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003727 return false;
3728 }
3729
3730 return true;
3731}
3732
Olli Etuaho41997e72016-03-10 13:38:39 +02003733bool ValidateGenOrDelete(Context *context, GLint n)
3734{
3735 if (n < 0)
3736 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003737 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003738 return false;
3739 }
3740 return true;
3741}
3742
Jamie Madill5b772312018-03-08 20:28:32 -05003743bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003744{
3745 if (!context->getExtensions().robustClientMemory)
3746 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003747 context->handleError(InvalidOperation()
3748 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003749 return false;
3750 }
3751
3752 if (bufSize < 0)
3753 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003754 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003755 return false;
3756 }
3757
3758 return true;
3759}
3760
Jamie Madill5b772312018-03-08 20:28:32 -05003761bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003762{
3763 if (bufSize < numParams)
3764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003765 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3766 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003767 return false;
3768 }
3769
3770 return true;
3771}
3772
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003773bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04003774 GLenum target,
3775 GLenum attachment,
3776 GLenum pname,
3777 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003778{
Geoff Lange8afa902017-09-27 15:00:43 -04003779 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003780 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003781 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003782 return false;
3783 }
3784
3785 int clientVersion = context->getClientMajorVersion();
3786
3787 switch (pname)
3788 {
3789 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3790 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3791 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3792 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3793 break;
3794
Martin Radeve5285d22017-07-14 16:23:53 +03003795 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3796 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3797 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3798 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3799 if (clientVersion < 3 || !context->getExtensions().multiview)
3800 {
3801 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3802 return false;
3803 }
3804 break;
3805
Geoff Langff5b2d52016-09-07 11:32:23 -04003806 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3807 if (clientVersion < 3 && !context->getExtensions().sRGB)
3808 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003809 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003810 return false;
3811 }
3812 break;
3813
3814 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3815 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3816 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3817 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3818 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3819 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3820 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3821 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3822 if (clientVersion < 3)
3823 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003824 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003825 return false;
3826 }
3827 break;
3828
3829 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003830 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003831 return false;
3832 }
3833
3834 // Determine if the attachment is a valid enum
3835 switch (attachment)
3836 {
3837 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04003838 case GL_DEPTH:
3839 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04003840 if (clientVersion < 3)
3841 {
Geoff Langfa125c92017-10-24 13:01:46 -04003842 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003843 return false;
3844 }
3845 break;
3846
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003847 case GL_DEPTH_STENCIL_ATTACHMENT:
3848 if (clientVersion < 3 && !context->isWebGL1())
3849 {
3850 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3851 return false;
3852 }
3853 break;
3854
Geoff Langfa125c92017-10-24 13:01:46 -04003855 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003856 case GL_DEPTH_ATTACHMENT:
3857 case GL_STENCIL_ATTACHMENT:
3858 break;
3859
3860 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003861 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3862 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003863 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3864 {
Geoff Langfa125c92017-10-24 13:01:46 -04003865 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003866 return false;
3867 }
3868 break;
3869 }
3870
3871 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3872 ASSERT(framebuffer);
3873
3874 if (framebuffer->id() == 0)
3875 {
3876 if (clientVersion < 3)
3877 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003878 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003879 return false;
3880 }
3881
3882 switch (attachment)
3883 {
3884 case GL_BACK:
3885 case GL_DEPTH:
3886 case GL_STENCIL:
3887 break;
3888
3889 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003890 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003891 return false;
3892 }
3893 }
3894 else
3895 {
3896 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3897 {
3898 // Valid attachment query
3899 }
3900 else
3901 {
3902 switch (attachment)
3903 {
3904 case GL_DEPTH_ATTACHMENT:
3905 case GL_STENCIL_ATTACHMENT:
3906 break;
3907
3908 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003909 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04003910 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003911 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003912 return false;
3913 }
3914 break;
3915
3916 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003917 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003918 return false;
3919 }
3920 }
3921 }
3922
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003923 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003924 if (attachmentObject)
3925 {
3926 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3927 attachmentObject->type() == GL_TEXTURE ||
3928 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3929
3930 switch (pname)
3931 {
3932 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3933 if (attachmentObject->type() != GL_RENDERBUFFER &&
3934 attachmentObject->type() != GL_TEXTURE)
3935 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003936 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003937 return false;
3938 }
3939 break;
3940
3941 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3942 if (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_CUBE_MAP_FACE:
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_COMPONENT_TYPE:
3958 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3959 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003960 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003961 return false;
3962 }
3963 break;
3964
3965 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3966 if (attachmentObject->type() != GL_TEXTURE)
3967 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003968 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003969 return false;
3970 }
3971 break;
3972
3973 default:
3974 break;
3975 }
3976 }
3977 else
3978 {
3979 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3980 // is NONE, then querying any other pname will generate INVALID_ENUM.
3981
3982 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3983 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3984 // INVALID_OPERATION for all other pnames
3985
3986 switch (pname)
3987 {
3988 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3989 break;
3990
3991 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3992 if (clientVersion < 3)
3993 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003994 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003995 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003996 return false;
3997 }
3998 break;
3999
4000 default:
4001 if (clientVersion < 3)
4002 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004003 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004004 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004005 return false;
4006 }
4007 else
4008 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004009 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004010 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004011 return false;
4012 }
4013 }
4014 }
4015
Martin Radeve5285d22017-07-14 16:23:53 +03004016 if (numParams)
4017 {
4018 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4019 {
4020 // Only when the viewport offsets are queried we can have a varying number of output
4021 // parameters.
4022 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4023 *numParams = numViews * 2;
4024 }
4025 else
4026 {
4027 // For all other queries we can have only one output parameter.
4028 *numParams = 1;
4029 }
4030 }
4031
Geoff Langff5b2d52016-09-07 11:32:23 -04004032 return true;
4033}
4034
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004035bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004036 GLenum target,
4037 GLenum attachment,
4038 GLenum pname,
4039 GLsizei bufSize,
4040 GLsizei *numParams)
4041{
4042 if (!ValidateRobustEntryPoint(context, bufSize))
4043 {
4044 return false;
4045 }
4046
Jamie Madillbe849e42017-05-02 15:49:00 -04004047 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4048 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004049 {
4050 return false;
4051 }
4052
4053 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4054 {
4055 return false;
4056 }
4057
4058 return true;
4059}
4060
Jamie Madill5b772312018-03-08 20:28:32 -05004061bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004062 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004063 GLenum pname,
4064 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004065 GLsizei *length,
4066 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004067{
4068 if (!ValidateRobustEntryPoint(context, bufSize))
4069 {
4070 return false;
4071 }
4072
Geoff Langebebe1c2016-10-14 12:01:31 -04004073 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004074 {
4075 return false;
4076 }
4077
Geoff Langebebe1c2016-10-14 12:01:31 -04004078 if (!ValidateRobustBufferSize(context, bufSize, *length))
4079 {
4080 return false;
4081 }
4082
4083 return true;
4084}
4085
Jamie Madill5b772312018-03-08 20:28:32 -05004086bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004087 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004088 GLenum pname,
4089 GLsizei bufSize,
4090 GLsizei *length,
4091 GLint64 *params)
4092{
4093 if (!ValidateRobustEntryPoint(context, bufSize))
4094 {
4095 return false;
4096 }
4097
4098 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4099 {
4100 return false;
4101 }
4102
4103 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004104 {
4105 return false;
4106 }
4107
4108 return true;
4109}
4110
Jamie Madill5b772312018-03-08 20:28:32 -05004111bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004112{
4113 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004114 if (numParams)
4115 {
4116 *numParams = 1;
4117 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004118
4119 Program *programObject = GetValidProgram(context, program);
4120 if (!programObject)
4121 {
4122 return false;
4123 }
4124
4125 switch (pname)
4126 {
4127 case GL_DELETE_STATUS:
4128 case GL_LINK_STATUS:
4129 case GL_VALIDATE_STATUS:
4130 case GL_INFO_LOG_LENGTH:
4131 case GL_ATTACHED_SHADERS:
4132 case GL_ACTIVE_ATTRIBUTES:
4133 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4134 case GL_ACTIVE_UNIFORMS:
4135 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4136 break;
4137
4138 case GL_PROGRAM_BINARY_LENGTH:
4139 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4140 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004141 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4142 "requires GL_OES_get_program_binary or "
4143 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004144 return false;
4145 }
4146 break;
4147
4148 case GL_ACTIVE_UNIFORM_BLOCKS:
4149 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4150 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4151 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4152 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4153 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4154 if (context->getClientMajorVersion() < 3)
4155 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004156 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004157 return false;
4158 }
4159 break;
4160
Yunchao He61afff12017-03-14 15:34:03 +08004161 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004162 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004163 if (context->getClientVersion() < Version(3, 1))
4164 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004165 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004166 return false;
4167 }
4168 break;
4169
Jiawei Shao6ae51612018-02-23 14:03:25 +08004170 case GL_COMPUTE_WORK_GROUP_SIZE:
4171 if (context->getClientVersion() < Version(3, 1))
4172 {
4173 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4174 return false;
4175 }
4176
4177 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4178 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4179 // program which has not been linked successfully, or which does not contain objects to
4180 // form a compute shader.
4181 if (!programObject->isLinked())
4182 {
4183 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4184 return false;
4185 }
4186 if (!programObject->hasLinkedComputeShader())
4187 {
4188 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4189 return false;
4190 }
4191 break;
4192
Geoff Langff5b2d52016-09-07 11:32:23 -04004193 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004194 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004195 return false;
4196 }
4197
4198 return true;
4199}
4200
4201bool ValidateGetProgramivRobustANGLE(Context *context,
4202 GLuint program,
4203 GLenum pname,
4204 GLsizei bufSize,
4205 GLsizei *numParams)
4206{
4207 if (!ValidateRobustEntryPoint(context, bufSize))
4208 {
4209 return false;
4210 }
4211
Jamie Madillbe849e42017-05-02 15:49:00 -04004212 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004213 {
4214 return false;
4215 }
4216
4217 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4218 {
4219 return false;
4220 }
4221
4222 return true;
4223}
4224
Geoff Lang740d9022016-10-07 11:20:52 -04004225bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4226 GLenum target,
4227 GLenum pname,
4228 GLsizei bufSize,
4229 GLsizei *length,
4230 GLint *params)
4231{
4232 if (!ValidateRobustEntryPoint(context, bufSize))
4233 {
4234 return false;
4235 }
4236
4237 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4238 {
4239 return false;
4240 }
4241
4242 if (!ValidateRobustBufferSize(context, bufSize, *length))
4243 {
4244 return false;
4245 }
4246
4247 return true;
4248}
4249
Geoff Langd7d0ed32016-10-07 11:33:51 -04004250bool ValidateGetShaderivRobustANGLE(Context *context,
4251 GLuint shader,
4252 GLenum pname,
4253 GLsizei bufSize,
4254 GLsizei *length,
4255 GLint *params)
4256{
4257 if (!ValidateRobustEntryPoint(context, bufSize))
4258 {
4259 return false;
4260 }
4261
4262 if (!ValidateGetShaderivBase(context, shader, pname, length))
4263 {
4264 return false;
4265 }
4266
4267 if (!ValidateRobustBufferSize(context, bufSize, *length))
4268 {
4269 return false;
4270 }
4271
4272 return true;
4273}
4274
Geoff Langc1984ed2016-10-07 12:41:00 -04004275bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004276 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004277 GLenum pname,
4278 GLsizei bufSize,
4279 GLsizei *length,
4280 GLfloat *params)
4281{
4282 if (!ValidateRobustEntryPoint(context, bufSize))
4283 {
4284 return false;
4285 }
4286
4287 if (!ValidateGetTexParameterBase(context, target, pname, length))
4288 {
4289 return false;
4290 }
4291
4292 if (!ValidateRobustBufferSize(context, bufSize, *length))
4293 {
4294 return false;
4295 }
4296
4297 return true;
4298}
4299
Geoff Langc1984ed2016-10-07 12:41:00 -04004300bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004301 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004302 GLenum pname,
4303 GLsizei bufSize,
4304 GLsizei *length,
4305 GLint *params)
4306{
4307 if (!ValidateRobustEntryPoint(context, bufSize))
4308 {
4309 return false;
4310 }
4311
4312 if (!ValidateGetTexParameterBase(context, target, pname, length))
4313 {
4314 return false;
4315 }
4316
4317 if (!ValidateRobustBufferSize(context, bufSize, *length))
4318 {
4319 return false;
4320 }
4321
4322 return true;
4323}
4324
Geoff Langc1984ed2016-10-07 12:41:00 -04004325bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004326 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004327 GLenum pname,
4328 GLsizei bufSize,
4329 const GLfloat *params)
4330{
4331 if (!ValidateRobustEntryPoint(context, bufSize))
4332 {
4333 return false;
4334 }
4335
4336 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4337}
4338
Geoff Langc1984ed2016-10-07 12:41:00 -04004339bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004340 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004341 GLenum pname,
4342 GLsizei bufSize,
4343 const GLint *params)
4344{
4345 if (!ValidateRobustEntryPoint(context, bufSize))
4346 {
4347 return false;
4348 }
4349
4350 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4351}
4352
Geoff Langc1984ed2016-10-07 12:41:00 -04004353bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4354 GLuint sampler,
4355 GLenum pname,
4356 GLuint bufSize,
4357 GLsizei *length,
4358 GLfloat *params)
4359{
4360 if (!ValidateRobustEntryPoint(context, bufSize))
4361 {
4362 return false;
4363 }
4364
4365 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4366 {
4367 return false;
4368 }
4369
4370 if (!ValidateRobustBufferSize(context, bufSize, *length))
4371 {
4372 return false;
4373 }
4374
4375 return true;
4376}
4377
Geoff Langc1984ed2016-10-07 12:41:00 -04004378bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4379 GLuint sampler,
4380 GLenum pname,
4381 GLuint bufSize,
4382 GLsizei *length,
4383 GLint *params)
4384{
4385 if (!ValidateRobustEntryPoint(context, bufSize))
4386 {
4387 return false;
4388 }
4389
4390 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4391 {
4392 return false;
4393 }
4394
4395 if (!ValidateRobustBufferSize(context, bufSize, *length))
4396 {
4397 return false;
4398 }
4399
4400 return true;
4401}
4402
Geoff Langc1984ed2016-10-07 12:41:00 -04004403bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4404 GLuint sampler,
4405 GLenum pname,
4406 GLsizei bufSize,
4407 const GLfloat *params)
4408{
4409 if (!ValidateRobustEntryPoint(context, bufSize))
4410 {
4411 return false;
4412 }
4413
4414 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4415}
4416
Geoff Langc1984ed2016-10-07 12:41:00 -04004417bool ValidateSamplerParameterivRobustANGLE(Context *context,
4418 GLuint sampler,
4419 GLenum pname,
4420 GLsizei bufSize,
4421 const GLint *params)
4422{
4423 if (!ValidateRobustEntryPoint(context, bufSize))
4424 {
4425 return false;
4426 }
4427
4428 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4429}
4430
Geoff Lang0b031062016-10-13 14:30:04 -04004431bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4432 GLuint index,
4433 GLenum pname,
4434 GLsizei bufSize,
4435 GLsizei *length,
4436 GLfloat *params)
4437{
4438 if (!ValidateRobustEntryPoint(context, bufSize))
4439 {
4440 return false;
4441 }
4442
4443 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4444 {
4445 return false;
4446 }
4447
4448 if (!ValidateRobustBufferSize(context, bufSize, *length))
4449 {
4450 return false;
4451 }
4452
4453 return true;
4454}
4455
Geoff Lang0b031062016-10-13 14:30:04 -04004456bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4457 GLuint index,
4458 GLenum pname,
4459 GLsizei bufSize,
4460 GLsizei *length,
4461 GLint *params)
4462{
4463 if (!ValidateRobustEntryPoint(context, bufSize))
4464 {
4465 return false;
4466 }
4467
4468 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4469 {
4470 return false;
4471 }
4472
4473 if (!ValidateRobustBufferSize(context, bufSize, *length))
4474 {
4475 return false;
4476 }
4477
4478 return true;
4479}
4480
Geoff Lang0b031062016-10-13 14:30:04 -04004481bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4482 GLuint index,
4483 GLenum pname,
4484 GLsizei bufSize,
4485 GLsizei *length,
4486 void **pointer)
4487{
4488 if (!ValidateRobustEntryPoint(context, bufSize))
4489 {
4490 return false;
4491 }
4492
4493 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4494 {
4495 return false;
4496 }
4497
4498 if (!ValidateRobustBufferSize(context, bufSize, *length))
4499 {
4500 return false;
4501 }
4502
4503 return true;
4504}
4505
Geoff Lang0b031062016-10-13 14:30:04 -04004506bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4507 GLuint index,
4508 GLenum pname,
4509 GLsizei bufSize,
4510 GLsizei *length,
4511 GLint *params)
4512{
4513 if (!ValidateRobustEntryPoint(context, bufSize))
4514 {
4515 return false;
4516 }
4517
4518 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4519 {
4520 return false;
4521 }
4522
4523 if (!ValidateRobustBufferSize(context, bufSize, *length))
4524 {
4525 return false;
4526 }
4527
4528 return true;
4529}
4530
Geoff Lang0b031062016-10-13 14:30:04 -04004531bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4532 GLuint index,
4533 GLenum pname,
4534 GLsizei bufSize,
4535 GLsizei *length,
4536 GLuint *params)
4537{
4538 if (!ValidateRobustEntryPoint(context, bufSize))
4539 {
4540 return false;
4541 }
4542
4543 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4544 {
4545 return false;
4546 }
4547
4548 if (!ValidateRobustBufferSize(context, bufSize, *length))
4549 {
4550 return false;
4551 }
4552
4553 return true;
4554}
4555
Geoff Lang6899b872016-10-14 11:30:13 -04004556bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4557 GLuint program,
4558 GLuint uniformBlockIndex,
4559 GLenum pname,
4560 GLsizei bufSize,
4561 GLsizei *length,
4562 GLint *params)
4563{
4564 if (!ValidateRobustEntryPoint(context, bufSize))
4565 {
4566 return false;
4567 }
4568
4569 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4570 {
4571 return false;
4572 }
4573
4574 if (!ValidateRobustBufferSize(context, bufSize, *length))
4575 {
4576 return false;
4577 }
4578
4579 return true;
4580}
4581
Geoff Lang0a9661f2016-10-20 10:59:20 -07004582bool ValidateGetInternalFormativRobustANGLE(Context *context,
4583 GLenum target,
4584 GLenum internalformat,
4585 GLenum pname,
4586 GLsizei bufSize,
4587 GLsizei *length,
4588 GLint *params)
4589{
4590 if (!ValidateRobustEntryPoint(context, bufSize))
4591 {
4592 return false;
4593 }
4594
4595 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4596 {
4597 return false;
4598 }
4599
4600 if (!ValidateRobustBufferSize(context, bufSize, *length))
4601 {
4602 return false;
4603 }
4604
4605 return true;
4606}
4607
Jamie Madill5b772312018-03-08 20:28:32 -05004608bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08004609 GLuint attribIndex,
4610 GLint size,
4611 GLenum type,
4612 GLboolean pureInteger)
4613{
4614 const Caps &caps = context->getCaps();
4615 if (attribIndex >= caps.maxVertexAttributes)
4616 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004617 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004618 return false;
4619 }
4620
4621 if (size < 1 || size > 4)
4622 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004623 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004624 return false;
Shao80957d92017-02-20 21:25:59 +08004625 }
4626
4627 switch (type)
4628 {
4629 case GL_BYTE:
4630 case GL_UNSIGNED_BYTE:
4631 case GL_SHORT:
4632 case GL_UNSIGNED_SHORT:
4633 break;
4634
4635 case GL_INT:
4636 case GL_UNSIGNED_INT:
4637 if (context->getClientMajorVersion() < 3)
4638 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004639 context->handleError(InvalidEnum()
4640 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004641 return false;
4642 }
4643 break;
4644
4645 case GL_FIXED:
4646 case GL_FLOAT:
4647 if (pureInteger)
4648 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004649 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004650 return false;
4651 }
4652 break;
4653
4654 case GL_HALF_FLOAT:
4655 if (context->getClientMajorVersion() < 3)
4656 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004657 context->handleError(InvalidEnum()
4658 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004659 return false;
4660 }
4661 if (pureInteger)
4662 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004663 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004664 return false;
4665 }
4666 break;
4667
4668 case GL_INT_2_10_10_10_REV:
4669 case GL_UNSIGNED_INT_2_10_10_10_REV:
4670 if (context->getClientMajorVersion() < 3)
4671 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004672 context->handleError(InvalidEnum()
4673 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004674 return false;
4675 }
4676 if (pureInteger)
4677 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004678 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004679 return false;
4680 }
4681 if (size != 4)
4682 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004683 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4684 "UNSIGNED_INT_2_10_10_10_REV and "
4685 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004686 return false;
4687 }
4688 break;
4689
4690 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004691 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004692 return false;
4693 }
4694
4695 return true;
4696}
4697
Geoff Lang76e65652017-03-27 14:58:02 -04004698// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4699// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4700// specified clear value and the type of a buffer that is being cleared generates an
4701// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05004702bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04004703 GLint drawbuffer,
4704 const GLenum *validComponentTypes,
4705 size_t validComponentTypeCount)
4706{
4707 const FramebufferAttachment *attachment =
4708 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4709 if (attachment)
4710 {
4711 GLenum componentType = attachment->getFormat().info->componentType;
4712 const GLenum *end = validComponentTypes + validComponentTypeCount;
4713 if (std::find(validComponentTypes, end, componentType) == end)
4714 {
4715 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004716 InvalidOperation()
4717 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004718 return false;
4719 }
4720 }
4721
4722 return true;
4723}
4724
Jamie Madill5b772312018-03-08 20:28:32 -05004725bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04004726{
4727 if (!ValidateRobustEntryPoint(context, dataSize))
4728 {
4729 return false;
4730 }
4731
Corentin Wallez336129f2017-10-17 15:55:40 -04004732 gl::Buffer *pixelUnpackBuffer =
4733 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004734 if (pixelUnpackBuffer == nullptr)
4735 {
4736 if (dataSize < imageSize)
4737 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004738 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004739 }
4740 }
4741 return true;
4742}
4743
Jamie Madill5b772312018-03-08 20:28:32 -05004744bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004745 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004746 GLenum pname,
4747 bool pointerVersion,
4748 GLsizei *numParams)
4749{
4750 if (numParams)
4751 {
4752 *numParams = 0;
4753 }
4754
Corentin Walleze4477002017-12-01 14:39:58 -05004755 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004756 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004757 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004758 return false;
4759 }
4760
4761 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4762 if (!buffer)
4763 {
4764 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004765 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004766 return false;
4767 }
4768
4769 const Extensions &extensions = context->getExtensions();
4770
4771 switch (pname)
4772 {
4773 case GL_BUFFER_USAGE:
4774 case GL_BUFFER_SIZE:
4775 break;
4776
4777 case GL_BUFFER_ACCESS_OES:
4778 if (!extensions.mapBuffer)
4779 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004780 context->handleError(InvalidEnum()
4781 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004782 return false;
4783 }
4784 break;
4785
4786 case GL_BUFFER_MAPPED:
4787 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4788 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4789 !extensions.mapBufferRange)
4790 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004791 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4792 "GL_OES_mapbuffer or "
4793 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004794 return false;
4795 }
4796 break;
4797
4798 case GL_BUFFER_MAP_POINTER:
4799 if (!pointerVersion)
4800 {
4801 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004802 InvalidEnum()
4803 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004804 return false;
4805 }
4806 break;
4807
4808 case GL_BUFFER_ACCESS_FLAGS:
4809 case GL_BUFFER_MAP_OFFSET:
4810 case GL_BUFFER_MAP_LENGTH:
4811 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4812 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004813 context->handleError(InvalidEnum()
4814 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004815 return false;
4816 }
4817 break;
4818
4819 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004820 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004821 return false;
4822 }
4823
4824 // All buffer parameter queries return one value.
4825 if (numParams)
4826 {
4827 *numParams = 1;
4828 }
4829
4830 return true;
4831}
4832
4833bool ValidateGetRenderbufferParameterivBase(Context *context,
4834 GLenum target,
4835 GLenum pname,
4836 GLsizei *length)
4837{
4838 if (length)
4839 {
4840 *length = 0;
4841 }
4842
4843 if (target != GL_RENDERBUFFER)
4844 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004845 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004846 return false;
4847 }
4848
4849 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4850 if (renderbuffer == nullptr)
4851 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004852 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004853 return false;
4854 }
4855
4856 switch (pname)
4857 {
4858 case GL_RENDERBUFFER_WIDTH:
4859 case GL_RENDERBUFFER_HEIGHT:
4860 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4861 case GL_RENDERBUFFER_RED_SIZE:
4862 case GL_RENDERBUFFER_GREEN_SIZE:
4863 case GL_RENDERBUFFER_BLUE_SIZE:
4864 case GL_RENDERBUFFER_ALPHA_SIZE:
4865 case GL_RENDERBUFFER_DEPTH_SIZE:
4866 case GL_RENDERBUFFER_STENCIL_SIZE:
4867 break;
4868
4869 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4870 if (!context->getExtensions().framebufferMultisample)
4871 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004872 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004873 return false;
4874 }
4875 break;
4876
4877 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004878 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004879 return false;
4880 }
4881
4882 if (length)
4883 {
4884 *length = 1;
4885 }
4886 return true;
4887}
4888
4889bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4890{
4891 if (length)
4892 {
4893 *length = 0;
4894 }
4895
4896 if (GetValidShader(context, shader) == nullptr)
4897 {
4898 return false;
4899 }
4900
4901 switch (pname)
4902 {
4903 case GL_SHADER_TYPE:
4904 case GL_DELETE_STATUS:
4905 case GL_COMPILE_STATUS:
4906 case GL_INFO_LOG_LENGTH:
4907 case GL_SHADER_SOURCE_LENGTH:
4908 break;
4909
4910 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4911 if (!context->getExtensions().translatedShaderSource)
4912 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004913 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004914 return false;
4915 }
4916 break;
4917
4918 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004919 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004920 return false;
4921 }
4922
4923 if (length)
4924 {
4925 *length = 1;
4926 }
4927 return true;
4928}
4929
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004930bool ValidateGetTexParameterBase(Context *context,
4931 TextureType target,
4932 GLenum pname,
4933 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04004934{
4935 if (length)
4936 {
4937 *length = 0;
4938 }
4939
4940 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4941 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004942 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004943 return false;
4944 }
4945
4946 if (context->getTargetTexture(target) == nullptr)
4947 {
4948 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004949 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004950 return false;
4951 }
4952
4953 switch (pname)
4954 {
4955 case GL_TEXTURE_MAG_FILTER:
4956 case GL_TEXTURE_MIN_FILTER:
4957 case GL_TEXTURE_WRAP_S:
4958 case GL_TEXTURE_WRAP_T:
4959 break;
4960
4961 case GL_TEXTURE_USAGE_ANGLE:
4962 if (!context->getExtensions().textureUsage)
4963 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004964 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004965 return false;
4966 }
4967 break;
4968
4969 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05004970 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04004971 {
Jamie Madillbe849e42017-05-02 15:49:00 -04004972 return false;
4973 }
4974 break;
4975
4976 case GL_TEXTURE_IMMUTABLE_FORMAT:
4977 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4978 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004979 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004980 return false;
4981 }
4982 break;
4983
4984 case GL_TEXTURE_WRAP_R:
4985 case GL_TEXTURE_IMMUTABLE_LEVELS:
4986 case GL_TEXTURE_SWIZZLE_R:
4987 case GL_TEXTURE_SWIZZLE_G:
4988 case GL_TEXTURE_SWIZZLE_B:
4989 case GL_TEXTURE_SWIZZLE_A:
4990 case GL_TEXTURE_BASE_LEVEL:
4991 case GL_TEXTURE_MAX_LEVEL:
4992 case GL_TEXTURE_MIN_LOD:
4993 case GL_TEXTURE_MAX_LOD:
4994 case GL_TEXTURE_COMPARE_MODE:
4995 case GL_TEXTURE_COMPARE_FUNC:
4996 if (context->getClientMajorVersion() < 3)
4997 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004998 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004999 return false;
5000 }
5001 break;
5002
5003 case GL_TEXTURE_SRGB_DECODE_EXT:
5004 if (!context->getExtensions().textureSRGBDecode)
5005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005006 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005007 return false;
5008 }
5009 break;
5010
Yunchao Hebacaa712018-01-30 14:01:39 +08005011 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5012 if (context->getClientVersion() < Version(3, 1))
5013 {
5014 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5015 return false;
5016 }
5017 break;
5018
Jamie Madillbe849e42017-05-02 15:49:00 -04005019 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005020 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005021 return false;
5022 }
5023
5024 if (length)
5025 {
5026 *length = 1;
5027 }
5028 return true;
5029}
5030
5031bool ValidateGetVertexAttribBase(Context *context,
5032 GLuint index,
5033 GLenum pname,
5034 GLsizei *length,
5035 bool pointer,
5036 bool pureIntegerEntryPoint)
5037{
5038 if (length)
5039 {
5040 *length = 0;
5041 }
5042
5043 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5044 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005045 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005046 return false;
5047 }
5048
5049 if (index >= context->getCaps().maxVertexAttributes)
5050 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005051 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005052 return false;
5053 }
5054
5055 if (pointer)
5056 {
5057 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5058 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005059 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005060 return false;
5061 }
5062 }
5063 else
5064 {
5065 switch (pname)
5066 {
5067 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5068 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5069 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5070 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5071 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5072 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5073 case GL_CURRENT_VERTEX_ATTRIB:
5074 break;
5075
5076 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5077 static_assert(
5078 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5079 "ANGLE extension enums not equal to GL enums.");
5080 if (context->getClientMajorVersion() < 3 &&
5081 !context->getExtensions().instancedArrays)
5082 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005083 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5084 "requires OpenGL ES 3.0 or "
5085 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005086 return false;
5087 }
5088 break;
5089
5090 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5091 if (context->getClientMajorVersion() < 3)
5092 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005093 context->handleError(
5094 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005095 return false;
5096 }
5097 break;
5098
5099 case GL_VERTEX_ATTRIB_BINDING:
5100 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5101 if (context->getClientVersion() < ES_3_1)
5102 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005103 context->handleError(InvalidEnum()
5104 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005105 return false;
5106 }
5107 break;
5108
5109 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005110 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005111 return false;
5112 }
5113 }
5114
5115 if (length)
5116 {
5117 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5118 {
5119 *length = 4;
5120 }
5121 else
5122 {
5123 *length = 1;
5124 }
5125 }
5126
5127 return true;
5128}
5129
Jamie Madill4928b7c2017-06-20 12:57:39 -04005130bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005131 GLint x,
5132 GLint y,
5133 GLsizei width,
5134 GLsizei height,
5135 GLenum format,
5136 GLenum type,
5137 GLsizei bufSize,
5138 GLsizei *length,
5139 GLsizei *columns,
5140 GLsizei *rows,
5141 void *pixels)
5142{
5143 if (length != nullptr)
5144 {
5145 *length = 0;
5146 }
5147 if (rows != nullptr)
5148 {
5149 *rows = 0;
5150 }
5151 if (columns != nullptr)
5152 {
5153 *columns = 0;
5154 }
5155
5156 if (width < 0 || height < 0)
5157 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005158 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005159 return false;
5160 }
5161
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005162 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005163
Jamie Madille98b1b52018-03-08 09:47:23 -05005164 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madillbe849e42017-05-02 15:49:00 -04005165 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005166 return false;
5167 }
5168
Jamie Madille98b1b52018-03-08 09:47:23 -05005169 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005170 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005171 return false;
5172 }
5173
5174 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5175 ASSERT(framebuffer);
5176
5177 if (framebuffer->getReadBufferState() == GL_NONE)
5178 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005179 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005180 return false;
5181 }
5182
5183 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5184 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5185 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5186 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5187 // situation is an application error that would lead to a crash in ANGLE.
5188 if (readBuffer == nullptr)
5189 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005190 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005191 return false;
5192 }
5193
Martin Radev28031682017-07-28 14:47:56 +03005194 // ANGLE_multiview, Revision 1:
5195 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5196 // current read framebuffer is not NONE.
5197 if (readBuffer->getMultiviewLayout() != GL_NONE)
5198 {
5199 context->handleError(InvalidFramebufferOperation()
5200 << "Attempting to read from a multi-view framebuffer.");
5201 return false;
5202 }
5203
Geoff Lang280ba992017-04-18 16:30:58 -04005204 if (context->getExtensions().webglCompatibility)
5205 {
5206 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5207 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5208 // and type before validating the combination of format and type. However, the
5209 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5210 // verifies that GL_INVALID_OPERATION is generated.
5211 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5212 // dEQP/WebGL.
5213 if (!ValidReadPixelsFormatEnum(context, format))
5214 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005215 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005216 return false;
5217 }
5218
5219 if (!ValidReadPixelsTypeEnum(context, type))
5220 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005221 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005222 return false;
5223 }
5224 }
5225
Jamie Madill4928b7c2017-06-20 12:57:39 -04005226 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5227 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005228 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5229
5230 bool validFormatTypeCombination =
5231 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5232
5233 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5234 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005235 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005236 return false;
5237 }
5238
5239 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005240 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005241 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5242 {
5243 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005244 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005245 return false;
5246 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005247 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5248 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5249 {
5250 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5251 return false;
5252 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005253
5254 // .. the data would be packed to the buffer object such that the memory writes required
5255 // would exceed the data store size.
5256 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5257 const gl::Extents size(width, height, 1);
5258 const auto &pack = context->getGLState().getPackState();
5259
5260 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5261 if (endByteOrErr.isError())
5262 {
5263 context->handleError(endByteOrErr.getError());
5264 return false;
5265 }
5266
5267 size_t endByte = endByteOrErr.getResult();
5268 if (bufSize >= 0)
5269 {
5270 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5271 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005272 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005273 return false;
5274 }
5275 }
5276
5277 if (pixelPackBuffer != nullptr)
5278 {
5279 CheckedNumeric<size_t> checkedEndByte(endByte);
5280 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5281 checkedEndByte += checkedOffset;
5282
5283 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5284 {
5285 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005286 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005287 return false;
5288 }
5289 }
5290
5291 if (pixelPackBuffer == nullptr && length != nullptr)
5292 {
5293 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5294 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005295 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005296 return false;
5297 }
5298
5299 *length = static_cast<GLsizei>(endByte);
5300 }
5301
Geoff Langa953b522018-02-21 16:56:23 -05005302 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005303 angle::CheckedNumeric<int> clippedExtent(length);
5304 if (start < 0)
5305 {
5306 // "subtract" the area that is less than 0
5307 clippedExtent += start;
5308 }
5309
Geoff Langa953b522018-02-21 16:56:23 -05005310 angle::CheckedNumeric<int> readExtent = start;
5311 readExtent += length;
5312 if (!readExtent.IsValid())
5313 {
5314 return false;
5315 }
5316
5317 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005318 {
5319 // Subtract the region to the right of the read buffer
5320 clippedExtent -= (readExtent - bufferSize);
5321 }
5322
5323 if (!clippedExtent.IsValid())
5324 {
Geoff Langa953b522018-02-21 16:56:23 -05005325 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005326 }
5327
Geoff Langa953b522018-02-21 16:56:23 -05005328 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5329 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005330 };
5331
Geoff Langa953b522018-02-21 16:56:23 -05005332 GLsizei writtenColumns = 0;
5333 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5334 {
5335 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5336 return false;
5337 }
5338
5339 GLsizei writtenRows = 0;
5340 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5341 {
5342 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5343 return false;
5344 }
5345
Jamie Madillbe849e42017-05-02 15:49:00 -04005346 if (columns != nullptr)
5347 {
Geoff Langa953b522018-02-21 16:56:23 -05005348 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005349 }
5350
5351 if (rows != nullptr)
5352 {
Geoff Langa953b522018-02-21 16:56:23 -05005353 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005354 }
5355
5356 return true;
5357}
5358
5359template <typename ParamType>
5360bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005361 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005362 GLenum pname,
5363 GLsizei bufSize,
5364 const ParamType *params)
5365{
5366 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5367 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005368 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005369 return false;
5370 }
5371
5372 if (context->getTargetTexture(target) == nullptr)
5373 {
5374 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005375 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005376 return false;
5377 }
5378
5379 const GLsizei minBufSize = 1;
5380 if (bufSize >= 0 && bufSize < minBufSize)
5381 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005382 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005383 return false;
5384 }
5385
5386 switch (pname)
5387 {
5388 case GL_TEXTURE_WRAP_R:
5389 case GL_TEXTURE_SWIZZLE_R:
5390 case GL_TEXTURE_SWIZZLE_G:
5391 case GL_TEXTURE_SWIZZLE_B:
5392 case GL_TEXTURE_SWIZZLE_A:
5393 case GL_TEXTURE_BASE_LEVEL:
5394 case GL_TEXTURE_MAX_LEVEL:
5395 case GL_TEXTURE_COMPARE_MODE:
5396 case GL_TEXTURE_COMPARE_FUNC:
5397 case GL_TEXTURE_MIN_LOD:
5398 case GL_TEXTURE_MAX_LOD:
5399 if (context->getClientMajorVersion() < 3)
5400 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005401 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005402 return false;
5403 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005404 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005406 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5407 "available without "
5408 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005409 return false;
5410 }
5411 break;
5412
5413 default:
5414 break;
5415 }
5416
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005417 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005418 {
5419 switch (pname)
5420 {
5421 case GL_TEXTURE_MIN_FILTER:
5422 case GL_TEXTURE_MAG_FILTER:
5423 case GL_TEXTURE_WRAP_S:
5424 case GL_TEXTURE_WRAP_T:
5425 case GL_TEXTURE_WRAP_R:
5426 case GL_TEXTURE_MIN_LOD:
5427 case GL_TEXTURE_MAX_LOD:
5428 case GL_TEXTURE_COMPARE_MODE:
5429 case GL_TEXTURE_COMPARE_FUNC:
5430 context->handleError(InvalidEnum()
5431 << "Invalid parameter for 2D multisampled textures.");
5432 return false;
5433 }
5434 }
5435
Jamie Madillbe849e42017-05-02 15:49:00 -04005436 switch (pname)
5437 {
5438 case GL_TEXTURE_WRAP_S:
5439 case GL_TEXTURE_WRAP_T:
5440 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005441 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005442 bool restrictedWrapModes =
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005443 target == TextureType::External || target == TextureType::Rectangle;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005444 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5445 {
5446 return false;
5447 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005448 }
5449 break;
5450
5451 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005452 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005453 bool restrictedMinFilter =
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005454 target == TextureType::External || target == TextureType::Rectangle;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005455 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5456 {
5457 return false;
5458 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005459 }
5460 break;
5461
5462 case GL_TEXTURE_MAG_FILTER:
5463 if (!ValidateTextureMagFilterValue(context, params))
5464 {
5465 return false;
5466 }
5467 break;
5468
5469 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005470 if (!context->getExtensions().textureUsage)
5471 {
5472 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5473 return false;
5474 }
5475
Jamie Madillbe849e42017-05-02 15:49:00 -04005476 switch (ConvertToGLenum(params[0]))
5477 {
5478 case GL_NONE:
5479 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5480 break;
5481
5482 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005483 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005484 return false;
5485 }
5486 break;
5487
5488 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Jamie Madillbe849e42017-05-02 15:49:00 -04005489 {
Luc Ferron1b1a8642018-01-23 15:12:01 -05005490 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5491 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5492 {
5493 return false;
5494 }
5495 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
Jamie Madillbe849e42017-05-02 15:49:00 -04005496 }
5497 break;
5498
5499 case GL_TEXTURE_MIN_LOD:
5500 case GL_TEXTURE_MAX_LOD:
5501 // any value is permissible
5502 break;
5503
5504 case GL_TEXTURE_COMPARE_MODE:
5505 if (!ValidateTextureCompareModeValue(context, params))
5506 {
5507 return false;
5508 }
5509 break;
5510
5511 case GL_TEXTURE_COMPARE_FUNC:
5512 if (!ValidateTextureCompareFuncValue(context, params))
5513 {
5514 return false;
5515 }
5516 break;
5517
5518 case GL_TEXTURE_SWIZZLE_R:
5519 case GL_TEXTURE_SWIZZLE_G:
5520 case GL_TEXTURE_SWIZZLE_B:
5521 case GL_TEXTURE_SWIZZLE_A:
5522 switch (ConvertToGLenum(params[0]))
5523 {
5524 case GL_RED:
5525 case GL_GREEN:
5526 case GL_BLUE:
5527 case GL_ALPHA:
5528 case GL_ZERO:
5529 case GL_ONE:
5530 break;
5531
5532 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005533 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005534 return false;
5535 }
5536 break;
5537
5538 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005539 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005540 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005541 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005542 return false;
5543 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005544 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005545 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005546 context->handleError(InvalidOperation()
5547 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005548 return false;
5549 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005550 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005551 {
5552 context->handleError(InvalidOperation()
5553 << "Base level must be 0 for multisampled textures.");
5554 return false;
5555 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005556 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005557 {
5558 context->handleError(InvalidOperation()
5559 << "Base level must be 0 for rectangle textures.");
5560 return false;
5561 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005562 break;
5563
5564 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005565 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005566 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005567 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005568 return false;
5569 }
5570 break;
5571
5572 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5573 if (context->getClientVersion() < Version(3, 1))
5574 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005575 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005576 return false;
5577 }
5578 switch (ConvertToGLenum(params[0]))
5579 {
5580 case GL_DEPTH_COMPONENT:
5581 case GL_STENCIL_INDEX:
5582 break;
5583
5584 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005585 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005586 return false;
5587 }
5588 break;
5589
5590 case GL_TEXTURE_SRGB_DECODE_EXT:
5591 if (!ValidateTextureSRGBDecodeValue(context, params))
5592 {
5593 return false;
5594 }
5595 break;
5596
5597 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005598 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005599 return false;
5600 }
5601
5602 return true;
5603}
5604
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005605template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
5606template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04005607
Jamie Madill5b772312018-03-08 20:28:32 -05005608bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04005609{
5610 if (index >= MAX_VERTEX_ATTRIBS)
5611 {
5612 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5613 return false;
5614 }
5615
5616 return true;
5617}
5618
5619bool ValidateGetActiveUniformBlockivBase(Context *context,
5620 GLuint program,
5621 GLuint uniformBlockIndex,
5622 GLenum pname,
5623 GLsizei *length)
5624{
5625 if (length)
5626 {
5627 *length = 0;
5628 }
5629
5630 if (context->getClientMajorVersion() < 3)
5631 {
5632 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5633 return false;
5634 }
5635
5636 Program *programObject = GetValidProgram(context, program);
5637 if (!programObject)
5638 {
5639 return false;
5640 }
5641
5642 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5643 {
5644 context->handleError(InvalidValue()
5645 << "uniformBlockIndex exceeds active uniform block count.");
5646 return false;
5647 }
5648
5649 switch (pname)
5650 {
5651 case GL_UNIFORM_BLOCK_BINDING:
5652 case GL_UNIFORM_BLOCK_DATA_SIZE:
5653 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5654 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5655 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5656 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5657 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5658 break;
5659
5660 default:
5661 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5662 return false;
5663 }
5664
5665 if (length)
5666 {
5667 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5668 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005669 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005670 programObject->getUniformBlockByIndex(uniformBlockIndex);
5671 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5672 }
5673 else
5674 {
5675 *length = 1;
5676 }
5677 }
5678
5679 return true;
5680}
5681
Jamie Madill9696d072017-08-26 23:19:57 -04005682template <typename ParamType>
5683bool ValidateSamplerParameterBase(Context *context,
5684 GLuint sampler,
5685 GLenum pname,
5686 GLsizei bufSize,
5687 ParamType *params)
5688{
5689 if (context->getClientMajorVersion() < 3)
5690 {
5691 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5692 return false;
5693 }
5694
5695 if (!context->isSampler(sampler))
5696 {
5697 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5698 return false;
5699 }
5700
5701 const GLsizei minBufSize = 1;
5702 if (bufSize >= 0 && bufSize < minBufSize)
5703 {
5704 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5705 return false;
5706 }
5707
5708 switch (pname)
5709 {
5710 case GL_TEXTURE_WRAP_S:
5711 case GL_TEXTURE_WRAP_T:
5712 case GL_TEXTURE_WRAP_R:
5713 if (!ValidateTextureWrapModeValue(context, params, false))
5714 {
5715 return false;
5716 }
5717 break;
5718
5719 case GL_TEXTURE_MIN_FILTER:
5720 if (!ValidateTextureMinFilterValue(context, params, false))
5721 {
5722 return false;
5723 }
5724 break;
5725
5726 case GL_TEXTURE_MAG_FILTER:
5727 if (!ValidateTextureMagFilterValue(context, params))
5728 {
5729 return false;
5730 }
5731 break;
5732
5733 case GL_TEXTURE_MIN_LOD:
5734 case GL_TEXTURE_MAX_LOD:
5735 // any value is permissible
5736 break;
5737
5738 case GL_TEXTURE_COMPARE_MODE:
5739 if (!ValidateTextureCompareModeValue(context, params))
5740 {
5741 return false;
5742 }
5743 break;
5744
5745 case GL_TEXTURE_COMPARE_FUNC:
5746 if (!ValidateTextureCompareFuncValue(context, params))
5747 {
5748 return false;
5749 }
5750 break;
5751
5752 case GL_TEXTURE_SRGB_DECODE_EXT:
5753 if (!ValidateTextureSRGBDecodeValue(context, params))
5754 {
5755 return false;
5756 }
5757 break;
5758
Luc Ferron1b1a8642018-01-23 15:12:01 -05005759 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5760 {
5761 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5762 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5763 {
5764 return false;
5765 }
5766 }
5767 break;
5768
Jamie Madill9696d072017-08-26 23:19:57 -04005769 default:
5770 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5771 return false;
5772 }
5773
5774 return true;
5775}
5776
5777template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5778template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5779
5780bool ValidateGetSamplerParameterBase(Context *context,
5781 GLuint sampler,
5782 GLenum pname,
5783 GLsizei *length)
5784{
5785 if (length)
5786 {
5787 *length = 0;
5788 }
5789
5790 if (context->getClientMajorVersion() < 3)
5791 {
5792 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5793 return false;
5794 }
5795
5796 if (!context->isSampler(sampler))
5797 {
5798 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5799 return false;
5800 }
5801
5802 switch (pname)
5803 {
5804 case GL_TEXTURE_WRAP_S:
5805 case GL_TEXTURE_WRAP_T:
5806 case GL_TEXTURE_WRAP_R:
5807 case GL_TEXTURE_MIN_FILTER:
5808 case GL_TEXTURE_MAG_FILTER:
5809 case GL_TEXTURE_MIN_LOD:
5810 case GL_TEXTURE_MAX_LOD:
5811 case GL_TEXTURE_COMPARE_MODE:
5812 case GL_TEXTURE_COMPARE_FUNC:
5813 break;
5814
Luc Ferron1b1a8642018-01-23 15:12:01 -05005815 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5816 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
5817 {
5818 return false;
5819 }
5820 break;
5821
Jamie Madill9696d072017-08-26 23:19:57 -04005822 case GL_TEXTURE_SRGB_DECODE_EXT:
5823 if (!context->getExtensions().textureSRGBDecode)
5824 {
5825 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5826 return false;
5827 }
5828 break;
5829
5830 default:
5831 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5832 return false;
5833 }
5834
5835 if (length)
5836 {
5837 *length = 1;
5838 }
5839 return true;
5840}
5841
5842bool ValidateGetInternalFormativBase(Context *context,
5843 GLenum target,
5844 GLenum internalformat,
5845 GLenum pname,
5846 GLsizei bufSize,
5847 GLsizei *numParams)
5848{
5849 if (numParams)
5850 {
5851 *numParams = 0;
5852 }
5853
5854 if (context->getClientMajorVersion() < 3)
5855 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005856 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005857 return false;
5858 }
5859
5860 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5861 if (!formatCaps.renderable)
5862 {
5863 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5864 return false;
5865 }
5866
5867 switch (target)
5868 {
5869 case GL_RENDERBUFFER:
5870 break;
5871
5872 case GL_TEXTURE_2D_MULTISAMPLE:
5873 if (context->getClientVersion() < ES_3_1)
5874 {
5875 context->handleError(InvalidOperation()
5876 << "Texture target requires at least OpenGL ES 3.1.");
5877 return false;
5878 }
5879 break;
5880
5881 default:
5882 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5883 return false;
5884 }
5885
5886 if (bufSize < 0)
5887 {
5888 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5889 return false;
5890 }
5891
5892 GLsizei maxWriteParams = 0;
5893 switch (pname)
5894 {
5895 case GL_NUM_SAMPLE_COUNTS:
5896 maxWriteParams = 1;
5897 break;
5898
5899 case GL_SAMPLES:
5900 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5901 break;
5902
5903 default:
5904 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5905 return false;
5906 }
5907
5908 if (numParams)
5909 {
5910 // glGetInternalFormativ will not overflow bufSize
5911 *numParams = std::min(bufSize, maxWriteParams);
5912 }
5913
5914 return true;
5915}
5916
Jamie Madille98b1b52018-03-08 09:47:23 -05005917// We should check with Khronos if returning INVALID_FRAMEBUFFER_OPERATION is OK when querying
5918// implementation format info for incomplete framebuffers. It seems like these queries are
5919// incongruent with the other errors.
5920bool ValidateFramebufferComplete(Context *context, Framebuffer *framebuffer, bool isFramebufferOp)
5921{
5922 bool complete = false;
5923 ANGLE_VALIDATION_TRY(framebuffer->isComplete(context, &complete));
5924 if (!complete)
5925 {
5926 if (isFramebufferOp)
5927 {
5928 context->handleError(InvalidFramebufferOperation());
5929 }
5930 else
5931 {
5932 context->handleError(InvalidOperation());
5933 }
5934 return false;
5935 }
5936 return true;
5937}
5938
5939bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
5940{
5941 GLint samples = 0;
5942 ANGLE_VALIDATION_TRY(framebuffer->getSamples(context, &samples));
5943 if (samples != 0)
5944 {
5945 context->handleError(InvalidOperation());
5946 return false;
5947 }
5948 return true;
5949}
5950
Jamie Madillc29968b2016-01-20 11:17:23 -05005951} // namespace gl