blob: a8d2fe3637dda7c82f9d11af811469f9ac571907 [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
Jiawei Shaofccebff2018-03-08 13:51:02 +0800500bool IsCompatibleDrawModeWithGeometryShader(GLenum drawMode,
501 GLenum geometryShaderInputPrimitiveType)
502{
503 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
504 switch (geometryShaderInputPrimitiveType)
505 {
506 case GL_POINTS:
507 return drawMode == GL_POINTS;
508 case GL_LINES:
509 return drawMode == GL_LINES || drawMode == GL_LINE_STRIP || drawMode == GL_LINE_LOOP;
510 case GL_LINES_ADJACENCY_EXT:
511 return drawMode == GL_LINES_ADJACENCY_EXT || drawMode == GL_LINE_STRIP_ADJACENCY_EXT;
512 case GL_TRIANGLES:
513 return drawMode == GL_TRIANGLES || drawMode == GL_TRIANGLE_FAN ||
514 drawMode == GL_TRIANGLE_STRIP;
515 case GL_TRIANGLES_ADJACENCY_EXT:
516 return drawMode == GL_TRIANGLES_ADJACENCY_EXT ||
517 drawMode == GL_TRIANGLE_STRIP_ADJACENCY_EXT;
518 default:
519 UNREACHABLE();
520 return false;
521 }
522}
523
Geoff Langf41a7152016-09-19 15:11:17 -0400524} // anonymous namespace
525
Brandon Jonesd1049182018-03-28 10:02:20 -0700526void SetRobustLengthParam(GLsizei *length, GLsizei value)
527{
528 if (length)
529 {
530 *length = value;
531 }
532}
533
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500534bool IsETC2EACFormat(const GLenum format)
535{
536 // ES 3.1, Table 8.19
537 switch (format)
538 {
539 case GL_COMPRESSED_R11_EAC:
540 case GL_COMPRESSED_SIGNED_R11_EAC:
541 case GL_COMPRESSED_RG11_EAC:
542 case GL_COMPRESSED_SIGNED_RG11_EAC:
543 case GL_COMPRESSED_RGB8_ETC2:
544 case GL_COMPRESSED_SRGB8_ETC2:
545 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
546 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
547 case GL_COMPRESSED_RGBA8_ETC2_EAC:
548 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
549 return true;
550
551 default:
552 return false;
553 }
554}
555
Jamie Madill5b772312018-03-08 20:28:32 -0500556bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400557{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800558 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400559 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800560 case TextureType::_2D:
561 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800562 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400563
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800564 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400565 return context->getExtensions().textureRectangle;
566
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800567 case TextureType::_3D:
568 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800569 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500570
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800571 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800572 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400573
He Yunchaoced53ae2016-11-29 15:00:51 +0800574 default:
575 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500576 }
Jamie Madill35d15012013-10-07 10:46:37 -0400577}
578
Jamie Madill5b772312018-03-08 20:28:32 -0500579bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500580{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800581 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500582 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800583 case TextureType::_2D:
584 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500585 return true;
586
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800587 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400588 return context->getExtensions().textureRectangle;
589
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500590 default:
591 return false;
592 }
593}
594
Jamie Madill5b772312018-03-08 20:28:32 -0500595bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500596{
597 switch (target)
598 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800599 case TextureType::_3D:
600 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300601 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500602
603 default:
604 return false;
605 }
606}
607
Ian Ewellbda75592016-04-18 17:25:54 -0400608// Most texture GL calls are not compatible with external textures, so we have a separate validation
609// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500610bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400611{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800612 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400613 (context->getExtensions().eglImageExternal ||
614 context->getExtensions().eglStreamConsumerExternal);
615}
616
Shannon Woods4dfed832014-03-17 20:03:39 -0400617// This function differs from ValidTextureTarget in that the target must be
618// usable as the destination of a 2D operation-- so a cube face is valid, but
619// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400620// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500621bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400622{
623 switch (target)
624 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800625 case TextureTarget::_2D:
626 case TextureTarget::CubeMapNegativeX:
627 case TextureTarget::CubeMapNegativeY:
628 case TextureTarget::CubeMapNegativeZ:
629 case TextureTarget::CubeMapPositiveX:
630 case TextureTarget::CubeMapPositiveY:
631 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800632 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800633 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400634 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800635 default:
636 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500637 }
638}
639
Jamie Madill5b772312018-03-08 20:28:32 -0500640bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -0400641 GLenum mode,
642 GLsizei count,
643 GLenum type,
644 const GLvoid *indices,
645 GLsizei primcount)
646{
647 if (primcount < 0)
648 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700649 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400650 return false;
651 }
652
653 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
654 {
655 return false;
656 }
657
Jamie Madill9fdaa492018-02-16 10:52:11 -0500658 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400659}
660
661bool ValidateDrawArraysInstancedBase(Context *context,
662 GLenum mode,
663 GLint first,
664 GLsizei count,
665 GLsizei primcount)
666{
667 if (primcount < 0)
668 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700669 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400670 return false;
671 }
672
673 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
674 {
675 return false;
676 }
677
Jamie Madill9fdaa492018-02-16 10:52:11 -0500678 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400679}
680
Jamie Madill5b772312018-03-08 20:28:32 -0500681bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400682{
683 // Verify there is at least one active attribute with a divisor of zero
684 const State &state = context->getGLState();
685
686 Program *program = state.getProgram();
687
688 const auto &attribs = state.getVertexArray()->getVertexAttributes();
689 const auto &bindings = state.getVertexArray()->getVertexBindings();
690 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
691 {
692 const VertexAttribute &attrib = attribs[attributeIndex];
693 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300694 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400695 {
696 return true;
697 }
698 }
699
Brandon Jonesafa75152017-07-21 13:11:29 -0700700 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400701 return false;
702}
703
Jamie Madill5b772312018-03-08 20:28:32 -0500704bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500705{
706 switch (target)
707 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800708 case TextureType::_3D:
709 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800710 return true;
711 default:
712 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400713 }
714}
715
Jamie Madill5b772312018-03-08 20:28:32 -0500716bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800717{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800718 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800719 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800720 case TextureType::_2D:
721 case TextureType::_2DArray:
722 case TextureType::_2DMultisample:
723 case TextureType::CubeMap:
724 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800725 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800726 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400727 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800728 default:
729 return false;
730 }
731}
732
Jamie Madill5b772312018-03-08 20:28:32 -0500733bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500734{
He Yunchaoced53ae2016-11-29 15:00:51 +0800735 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
736 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400737 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500738
739 switch (target)
740 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800741 case GL_FRAMEBUFFER:
742 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400743
He Yunchaoced53ae2016-11-29 15:00:51 +0800744 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800745 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400746 return (context->getExtensions().framebufferBlit ||
747 context->getClientMajorVersion() >= 3);
748
He Yunchaoced53ae2016-11-29 15:00:51 +0800749 default:
750 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500751 }
752}
753
Jamie Madill5b772312018-03-08 20:28:32 -0500754bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400755{
Jamie Madillc29968b2016-01-20 11:17:23 -0500756 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400757 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800758 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400759 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800760 case TextureType::_2D:
761 case TextureType::_2DArray:
762 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500763 maxDimension = caps.max2DTextureSize;
764 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800765 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800766 maxDimension = caps.maxCubeMapTextureSize;
767 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800768 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400769 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800770 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800771 maxDimension = caps.max3DTextureSize;
772 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800773 default:
774 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400775 }
776
Brandon Jones6cad5662017-06-14 13:25:13 -0700777 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400778}
779
Jamie Madill5b772312018-03-08 20:28:32 -0500780bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800781 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700782 GLint level,
783 GLsizei width,
784 GLsizei height,
785 GLsizei depth,
786 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400787{
Brandon Jones6cad5662017-06-14 13:25:13 -0700788 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400789 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700790 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400791 return false;
792 }
Austin Kinross08528e12015-10-07 16:24:40 -0700793 // TexSubImage parameters can be NPOT without textureNPOT extension,
794 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500795 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500796 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500797 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400798 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400799 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700800 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400801 return false;
802 }
803
804 if (!ValidMipLevel(context, target, level))
805 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700806 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400807 return false;
808 }
809
810 return true;
811}
812
Geoff Lang966c9402017-04-18 12:38:27 -0400813bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
814{
815 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
816 (size % blockSize == 0);
817}
818
Jamie Madill5b772312018-03-08 20:28:32 -0500819bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500820 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400821 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500822 GLsizei width,
823 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400824{
Geoff Langca271392017-04-05 12:30:00 -0400825 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400826 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400827 {
828 return false;
829 }
830
Geoff Lang966c9402017-04-18 12:38:27 -0400831 if (width < 0 || height < 0)
832 {
833 return false;
834 }
835
836 if (CompressedTextureFormatRequiresExactSize(internalFormat))
837 {
838 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
839 // block size for level 0 but WebGL disallows this.
840 bool smallerThanBlockSizeAllowed =
841 level > 0 || !context->getExtensions().webglCompatibility;
842
843 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
844 smallerThanBlockSizeAllowed) ||
845 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
846 smallerThanBlockSizeAllowed))
847 {
848 return false;
849 }
850 }
851
852 return true;
853}
854
Jamie Madill5b772312018-03-08 20:28:32 -0500855bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400856 GLenum internalFormat,
857 GLint xoffset,
858 GLint yoffset,
859 GLsizei width,
860 GLsizei height,
861 size_t textureWidth,
862 size_t textureHeight)
863{
864 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
865 if (!formatInfo.compressed)
866 {
867 return false;
868 }
869
Geoff Lang44ff5a72017-02-03 15:15:43 -0500870 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400871 {
872 return false;
873 }
874
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500875 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400876 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500877 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400878 yoffset % formatInfo.compressedBlockHeight != 0)
879 {
880 return false;
881 }
882
883 // Allowed to either have data that is a multiple of block size or is smaller than the block
884 // size but fills the entire mip
885 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
886 static_cast<size_t>(width) == textureWidth &&
887 static_cast<size_t>(height) == textureHeight;
888 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
889 (height % formatInfo.compressedBlockHeight) == 0;
890 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400891 {
892 return false;
893 }
894 }
895
Geoff Langd4f180b2013-09-24 13:57:44 -0400896 return true;
897}
898
Jamie Madill5b772312018-03-08 20:28:32 -0500899bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800900 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400901 GLsizei width,
902 GLsizei height,
903 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400904 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400905 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400906 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400907 GLsizei imageSize)
908{
Corentin Wallez336129f2017-10-17 15:55:40 -0400909 gl::Buffer *pixelUnpackBuffer =
910 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400911 if (pixelUnpackBuffer == nullptr && imageSize < 0)
912 {
913 // Checks are not required
914 return true;
915 }
916
917 // ...the data would be unpacked from the buffer object such that the memory reads required
918 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400919 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
920 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400921 const gl::Extents size(width, height, depth);
922 const auto &unpack = context->getGLState().getUnpackState();
923
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800924 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Geoff Langff5b2d52016-09-07 11:32:23 -0400925 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
926 if (endByteOrErr.isError())
927 {
928 context->handleError(endByteOrErr.getError());
929 return false;
930 }
931
932 GLuint endByte = endByteOrErr.getResult();
933
934 if (pixelUnpackBuffer)
935 {
936 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
937 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
938 checkedEndByte += checkedOffset;
939
940 if (!checkedEndByte.IsValid() ||
941 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
942 {
943 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500944 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -0400945 return false;
946 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800947 if (context->getExtensions().webglCompatibility &&
948 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
949 {
950 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
951 PixelUnpackBufferBoundForTransformFeedback);
952 return false;
953 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400954 }
955 else
956 {
957 ASSERT(imageSize >= 0);
958 if (pixels == nullptr && imageSize != 0)
959 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500960 context->handleError(InvalidOperation()
961 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400962 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400963 }
964
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400965 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400966 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500967 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400968 return false;
969 }
970 }
971
972 return true;
973}
974
Geoff Lang37dde692014-01-31 16:34:54 -0500975bool ValidQueryType(const Context *context, GLenum queryType)
976{
He Yunchaoced53ae2016-11-29 15:00:51 +0800977 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
978 "GL extension enums not equal.");
979 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
980 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -0500981
982 switch (queryType)
983 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800984 case GL_ANY_SAMPLES_PASSED:
985 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400986 return context->getClientMajorVersion() >= 3 ||
987 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +0800988 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
989 return (context->getClientMajorVersion() >= 3);
990 case GL_TIME_ELAPSED_EXT:
991 return context->getExtensions().disjointTimerQuery;
992 case GL_COMMANDS_COMPLETED_CHROMIUM:
993 return context->getExtensions().syncQuery;
Jiawei Shaod2fa07e2018-03-15 09:20:25 +0800994 case GL_PRIMITIVES_GENERATED_EXT:
995 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +0800996 default:
997 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500998 }
999}
1000
Jamie Madill5b772312018-03-08 20:28:32 -05001001bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001002 GLenum type,
1003 GLboolean normalized,
1004 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001005 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001006 bool pureInteger)
1007{
1008 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001009 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1010 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1011 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1012 // parameter exceeds 255.
1013 constexpr GLsizei kMaxWebGLStride = 255;
1014 if (stride > kMaxWebGLStride)
1015 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001016 context->handleError(InvalidValue()
1017 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001018 return false;
1019 }
1020
1021 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1022 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1023 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1024 // or an INVALID_OPERATION error is generated.
1025 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1026 size_t typeSize = GetVertexFormatTypeSize(internalType);
1027
1028 ASSERT(isPow2(typeSize) && typeSize > 0);
1029 size_t sizeMask = (typeSize - 1);
1030 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1031 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001032 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001033 return false;
1034 }
1035
1036 if ((stride & sizeMask) != 0)
1037 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001038 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001039 return false;
1040 }
1041
1042 return true;
1043}
1044
Jamie Madill5b772312018-03-08 20:28:32 -05001045Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001046{
He Yunchaoced53ae2016-11-29 15:00:51 +08001047 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1048 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1049 // or program object and INVALID_OPERATION if the provided name identifies an object
1050 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001051
Dian Xiang769769a2015-09-09 15:20:08 -07001052 Program *validProgram = context->getProgram(id);
1053
1054 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001055 {
Dian Xiang769769a2015-09-09 15:20:08 -07001056 if (context->getShader(id))
1057 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001058 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001059 }
1060 else
1061 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001062 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001063 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001064 }
Dian Xiang769769a2015-09-09 15:20:08 -07001065
1066 return validProgram;
1067}
1068
Jamie Madill5b772312018-03-08 20:28:32 -05001069Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001070{
1071 // See ValidProgram for spec details.
1072
1073 Shader *validShader = context->getShader(id);
1074
1075 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001076 {
Dian Xiang769769a2015-09-09 15:20:08 -07001077 if (context->getProgram(id))
1078 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001079 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001080 }
1081 else
1082 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001083 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001084 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001085 }
Dian Xiang769769a2015-09-09 15:20:08 -07001086
1087 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001088}
1089
Geoff Langb1196682014-07-23 13:47:29 -04001090bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001091{
Geoff Langfa125c92017-10-24 13:01:46 -04001092 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001093 {
Geoff Langfa125c92017-10-24 13:01:46 -04001094 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1095 {
1096 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1097 return false;
1098 }
Jamie Madillb4472272014-07-03 10:38:55 -04001099
Geoff Langfa125c92017-10-24 13:01:46 -04001100 // Color attachment 0 is validated below because it is always valid
1101 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001102 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001103 {
Geoff Langfa125c92017-10-24 13:01:46 -04001104 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001105 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001106 }
1107 }
1108 else
1109 {
1110 switch (attachment)
1111 {
Geoff Langfa125c92017-10-24 13:01:46 -04001112 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001113 case GL_DEPTH_ATTACHMENT:
1114 case GL_STENCIL_ATTACHMENT:
1115 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001116
He Yunchaoced53ae2016-11-29 15:00:51 +08001117 case GL_DEPTH_STENCIL_ATTACHMENT:
1118 if (!context->getExtensions().webglCompatibility &&
1119 context->getClientMajorVersion() < 3)
1120 {
Geoff Langfa125c92017-10-24 13:01:46 -04001121 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001122 return false;
1123 }
1124 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001125
He Yunchaoced53ae2016-11-29 15:00:51 +08001126 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001127 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001128 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001129 }
1130 }
1131
1132 return true;
1133}
1134
Jamie Madill5b772312018-03-08 20:28:32 -05001135bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001136 GLenum target,
1137 GLsizei samples,
1138 GLenum internalformat,
1139 GLsizei width,
1140 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001141{
1142 switch (target)
1143 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001144 case GL_RENDERBUFFER:
1145 break;
1146 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001147 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001148 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001149 }
1150
1151 if (width < 0 || height < 0 || samples < 0)
1152 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001153 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001154 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001155 }
1156
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001157 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1158 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1159
1160 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001161 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001162 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001163 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001164 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001165 }
1166
1167 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1168 // 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 -08001169 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001170 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1171 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001172 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001173 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001174 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001175 }
1176
Geoff Langaae65a42014-05-26 12:43:44 -04001177 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001178 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001179 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001180 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001181 }
1182
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001183 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001184 if (handle == 0)
1185 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001186 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001187 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001188 }
1189
1190 return true;
1191}
1192
He Yunchaoced53ae2016-11-29 15:00:51 +08001193bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1194 GLenum target,
1195 GLenum attachment,
1196 GLenum renderbuffertarget,
1197 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001198{
Geoff Lange8afa902017-09-27 15:00:43 -04001199 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001200 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001201 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001202 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001203 }
1204
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001205 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001206
Jamie Madill84115c92015-04-23 15:00:07 -04001207 ASSERT(framebuffer);
1208 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001209 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001210 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001211 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001212 }
1213
Jamie Madillb4472272014-07-03 10:38:55 -04001214 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001215 {
Jamie Madillb4472272014-07-03 10:38:55 -04001216 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001217 }
1218
Jamie Madillab9d82c2014-01-21 16:38:14 -05001219 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1220 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1221 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1222 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1223 if (renderbuffer != 0)
1224 {
1225 if (!context->getRenderbuffer(renderbuffer))
1226 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001227 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001228 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001229 }
1230 }
1231
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001232 return true;
1233}
1234
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001235bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001236 GLint srcX0,
1237 GLint srcY0,
1238 GLint srcX1,
1239 GLint srcY1,
1240 GLint dstX0,
1241 GLint dstY0,
1242 GLint dstX1,
1243 GLint dstY1,
1244 GLbitfield mask,
1245 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001246{
1247 switch (filter)
1248 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001249 case GL_NEAREST:
1250 break;
1251 case GL_LINEAR:
1252 break;
1253 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001254 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001255 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001256 }
1257
1258 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1259 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001260 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001261 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001262 }
1263
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001264 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1265 // color buffer, leaving only nearest being unfiltered from above
1266 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1267 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001268 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001269 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001270 }
1271
Jamie Madill51f40ec2016-06-15 14:06:00 -04001272 const auto &glState = context->getGLState();
1273 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1274 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001275
1276 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001277 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001278 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001279 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001280 }
1281
Jamie Madille98b1b52018-03-08 09:47:23 -05001282 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madill48faf802014-11-06 15:27:22 -05001283 {
Jamie Madill48faf802014-11-06 15:27:22 -05001284 return false;
1285 }
1286
Jamie Madille98b1b52018-03-08 09:47:23 -05001287 if (!ValidateFramebufferComplete(context, drawFramebuffer, true))
Jamie Madill48faf802014-11-06 15:27:22 -05001288 {
Jamie Madill48faf802014-11-06 15:27:22 -05001289 return false;
1290 }
1291
Qin Jiajiaaef92162018-02-27 13:51:44 +08001292 if (readFramebuffer->id() == drawFramebuffer->id())
1293 {
1294 context->handleError(InvalidOperation());
1295 return false;
1296 }
1297
Jamie Madille98b1b52018-03-08 09:47:23 -05001298 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001299 {
Geoff Langb1196682014-07-23 13:47:29 -04001300 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001301 }
1302
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001303 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1304
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001305 if (mask & GL_COLOR_BUFFER_BIT)
1306 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001307 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001308 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001309
He Yunchao66a41a22016-12-15 16:45:05 +08001310 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001311 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001312 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001313
Geoff Langa15472a2015-08-11 11:48:03 -04001314 for (size_t drawbufferIdx = 0;
1315 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001316 {
Geoff Langa15472a2015-08-11 11:48:03 -04001317 const FramebufferAttachment *attachment =
1318 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1319 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001320 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001321 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001322
Geoff Langb2f3d052013-08-13 12:49:27 -04001323 // The GL ES 3.0.2 spec (pg 193) states that:
1324 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001325 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1326 // as well
1327 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1328 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001329 // Changes with EXT_color_buffer_float:
1330 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001331 GLenum readComponentType = readFormat.info->componentType;
1332 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001333 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001334 readComponentType == GL_SIGNED_NORMALIZED);
1335 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1336 drawComponentType == GL_SIGNED_NORMALIZED);
1337
1338 if (extensions.colorBufferFloat)
1339 {
1340 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1341 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1342
1343 if (readFixedOrFloat != drawFixedOrFloat)
1344 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001345 context->handleError(InvalidOperation()
1346 << "If the read buffer contains fixed-point or "
1347 "floating-point values, the draw buffer must "
1348 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001349 return false;
1350 }
1351 }
1352 else if (readFixedPoint != drawFixedPoint)
1353 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001354 context->handleError(InvalidOperation()
1355 << "If the read buffer contains fixed-point values, "
1356 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001357 return false;
1358 }
1359
1360 if (readComponentType == GL_UNSIGNED_INT &&
1361 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001362 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001363 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001364 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001365 }
1366
Jamie Madill6163c752015-12-07 16:32:59 -05001367 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001368 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001369 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001370 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001371 }
1372
Jamie Madilla3944d42016-07-22 22:13:26 -04001373 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001374 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001375 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001376 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001377 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001378 }
Geoff Lange4915782017-04-12 15:19:07 -04001379
1380 if (context->getExtensions().webglCompatibility &&
1381 *readColorBuffer == *attachment)
1382 {
1383 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001384 InvalidOperation()
1385 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001386 return false;
1387 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001388 }
1389 }
1390
Jamie Madilla3944d42016-07-22 22:13:26 -04001391 if ((readFormat.info->componentType == GL_INT ||
1392 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1393 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001394 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001395 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001396 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001397 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001398 }
He Yunchao66a41a22016-12-15 16:45:05 +08001399 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1400 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1401 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1402 // situation is an application error that would lead to a crash in ANGLE.
1403 else if (drawFramebuffer->hasEnabledDrawBuffer())
1404 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001405 context->handleError(
1406 InvalidOperation()
1407 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001408 return false;
1409 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001410 }
1411
He Yunchaoced53ae2016-11-29 15:00:51 +08001412 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001413 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1414 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001415 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001416 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001417 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001418 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001419 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001420 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001421 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001422
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001423 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001424 {
Kenneth Russell69382852017-07-21 16:38:44 -04001425 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001427 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001428 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001429 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001430
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001431 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001432 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001433 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001434 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001435 }
Geoff Lange4915782017-04-12 15:19:07 -04001436
1437 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1438 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001439 context->handleError(
1440 InvalidOperation()
1441 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001442 return false;
1443 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001444 }
He Yunchao66a41a22016-12-15 16:45:05 +08001445 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1446 else if (drawBuffer)
1447 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001448 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1449 "depth/stencil attachment of a "
1450 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001451 return false;
1452 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001453 }
1454 }
1455
Martin Radeva3ed4572017-07-27 18:29:37 +03001456 // ANGLE_multiview, Revision 1:
1457 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1458 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1459 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1460 {
1461 context->handleError(InvalidFramebufferOperation()
1462 << "Attempt to read from a multi-view framebuffer.");
1463 return false;
1464 }
1465 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1466 {
1467 context->handleError(InvalidFramebufferOperation()
1468 << "Attempt to write to a multi-view framebuffer.");
1469 return false;
1470 }
1471
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001472 return true;
1473}
1474
Jamie Madill4928b7c2017-06-20 12:57:39 -04001475bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001476 GLint x,
1477 GLint y,
1478 GLsizei width,
1479 GLsizei height,
1480 GLenum format,
1481 GLenum type,
1482 GLsizei bufSize,
1483 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001484 GLsizei *columns,
1485 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001486 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001487{
1488 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001489 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001490 return false;
1491 }
1492
Brandon Jonesd1049182018-03-28 10:02:20 -07001493 GLsizei writeLength = 0;
1494 GLsizei writeColumns = 0;
1495 GLsizei writeRows = 0;
1496
1497 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1498 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001499 {
Geoff Langb1196682014-07-23 13:47:29 -04001500 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001501 }
1502
Brandon Jonesd1049182018-03-28 10:02:20 -07001503 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001504 {
Geoff Langb1196682014-07-23 13:47:29 -04001505 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001506 }
1507
Brandon Jonesd1049182018-03-28 10:02:20 -07001508 SetRobustLengthParam(length, writeLength);
1509 SetRobustLengthParam(columns, writeColumns);
1510 SetRobustLengthParam(rows, writeRows);
1511
Jamie Madillc29968b2016-01-20 11:17:23 -05001512 return true;
1513}
1514
1515bool ValidateReadnPixelsEXT(Context *context,
1516 GLint x,
1517 GLint y,
1518 GLsizei width,
1519 GLsizei height,
1520 GLenum format,
1521 GLenum type,
1522 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001523 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001524{
1525 if (bufSize < 0)
1526 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001527 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001528 return false;
1529 }
1530
Geoff Lang62fce5b2016-09-30 10:46:35 -04001531 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001532 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001533}
Jamie Madill26e91952014-03-05 15:01:27 -05001534
Jamie Madill4928b7c2017-06-20 12:57:39 -04001535bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001536 GLint x,
1537 GLint y,
1538 GLsizei width,
1539 GLsizei height,
1540 GLenum format,
1541 GLenum type,
1542 GLsizei bufSize,
1543 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001544 GLsizei *columns,
1545 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001546 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001547{
Brandon Jonesd1049182018-03-28 10:02:20 -07001548 GLsizei writeLength = 0;
1549 GLsizei writeColumns = 0;
1550 GLsizei writeRows = 0;
1551
Geoff Lang62fce5b2016-09-30 10:46:35 -04001552 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001553 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001554 return false;
1555 }
1556
Brandon Jonesd1049182018-03-28 10:02:20 -07001557 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1558 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001559 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001560 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001561 }
1562
Brandon Jonesd1049182018-03-28 10:02:20 -07001563 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001564 {
1565 return false;
1566 }
1567
Brandon Jonesd1049182018-03-28 10:02:20 -07001568 SetRobustLengthParam(length, writeLength);
1569 SetRobustLengthParam(columns, writeColumns);
1570 SetRobustLengthParam(rows, writeRows);
1571
Geoff Lang62fce5b2016-09-30 10:46:35 -04001572 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001573}
1574
Jamie Madillf0e04492017-08-26 15:28:42 -04001575bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001576{
1577 if (!context->getExtensions().occlusionQueryBoolean &&
1578 !context->getExtensions().disjointTimerQuery)
1579 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001580 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001581 return false;
1582 }
1583
Olli Etuaho41997e72016-03-10 13:38:39 +02001584 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001585}
1586
Jamie Madillf0e04492017-08-26 15:28:42 -04001587bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001588{
1589 if (!context->getExtensions().occlusionQueryBoolean &&
1590 !context->getExtensions().disjointTimerQuery)
1591 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001592 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001593 return false;
1594 }
1595
Olli Etuaho41997e72016-03-10 13:38:39 +02001596 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001597}
1598
Jamie Madillf0e04492017-08-26 15:28:42 -04001599bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1600{
1601 if (!context->getExtensions().occlusionQueryBoolean &&
1602 !context->getExtensions().disjointTimerQuery)
1603 {
1604 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1605 return false;
1606 }
1607
1608 return true;
1609}
1610
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001611bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001612{
1613 if (!ValidQueryType(context, target))
1614 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001615 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001616 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001617 }
1618
1619 if (id == 0)
1620 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001621 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001622 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001623 }
1624
1625 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1626 // of zero, if the active query object name for <target> is non-zero (for the
1627 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1628 // the active query for either target is non-zero), if <id> is the name of an
1629 // existing query object whose type does not match <target>, or if <id> is the
1630 // active query object name for any query type, the error INVALID_OPERATION is
1631 // generated.
1632
1633 // Ensure no other queries are active
1634 // NOTE: If other queries than occlusion are supported, we will need to check
1635 // separately that:
1636 // a) The query ID passed is not the current active query for any target/type
1637 // b) There are no active queries for the requested target (and in the case
1638 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1639 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001640
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001641 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001642 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001643 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001644 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001645 }
1646
1647 Query *queryObject = context->getQuery(id, true, target);
1648
1649 // check that name was obtained with glGenQueries
1650 if (!queryObject)
1651 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001652 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001653 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001654 }
1655
1656 // check for type mismatch
1657 if (queryObject->getType() != target)
1658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001659 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001660 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001661 }
1662
1663 return true;
1664}
1665
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001666bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1667{
1668 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001669 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001670 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001671 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001672 return false;
1673 }
1674
1675 return ValidateBeginQueryBase(context, target, id);
1676}
1677
1678bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001679{
1680 if (!ValidQueryType(context, target))
1681 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001682 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001683 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001684 }
1685
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001686 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001687
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001688 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001689 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001690 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001691 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001692 }
1693
Jamie Madill45c785d2014-05-13 14:09:34 -04001694 return true;
1695}
1696
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001697bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1698{
1699 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001700 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001701 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001702 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001703 return false;
1704 }
1705
1706 return ValidateEndQueryBase(context, target);
1707}
1708
1709bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1710{
1711 if (!context->getExtensions().disjointTimerQuery)
1712 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001713 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001714 return false;
1715 }
1716
1717 if (target != GL_TIMESTAMP_EXT)
1718 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001719 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001720 return false;
1721 }
1722
1723 Query *queryObject = context->getQuery(id, true, target);
1724 if (queryObject == nullptr)
1725 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001726 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001727 return false;
1728 }
1729
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001730 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001731 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001732 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001733 return false;
1734 }
1735
1736 return true;
1737}
1738
Geoff Lang2186c382016-10-14 10:54:54 -04001739bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001740{
Geoff Lang2186c382016-10-14 10:54:54 -04001741 if (numParams)
1742 {
1743 *numParams = 0;
1744 }
1745
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001746 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1747 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001748 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001749 return false;
1750 }
1751
1752 switch (pname)
1753 {
1754 case GL_CURRENT_QUERY_EXT:
1755 if (target == GL_TIMESTAMP_EXT)
1756 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001757 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001758 return false;
1759 }
1760 break;
1761 case GL_QUERY_COUNTER_BITS_EXT:
1762 if (!context->getExtensions().disjointTimerQuery ||
1763 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1764 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001765 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001766 return false;
1767 }
1768 break;
1769 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001770 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001771 return false;
1772 }
1773
Geoff Lang2186c382016-10-14 10:54:54 -04001774 if (numParams)
1775 {
1776 // All queries return only one value
1777 *numParams = 1;
1778 }
1779
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001780 return true;
1781}
1782
1783bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1784{
1785 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001786 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001787 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001788 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001789 return false;
1790 }
1791
Geoff Lang2186c382016-10-14 10:54:54 -04001792 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001793}
1794
Geoff Lang2186c382016-10-14 10:54:54 -04001795bool ValidateGetQueryivRobustANGLE(Context *context,
1796 GLenum target,
1797 GLenum pname,
1798 GLsizei bufSize,
1799 GLsizei *length,
1800 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001801{
Geoff Lang2186c382016-10-14 10:54:54 -04001802 if (!ValidateRobustEntryPoint(context, bufSize))
1803 {
1804 return false;
1805 }
1806
Brandon Jonesd1049182018-03-28 10:02:20 -07001807 GLsizei numParams = 0;
1808
1809 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001810 {
1811 return false;
1812 }
1813
Brandon Jonesd1049182018-03-28 10:02:20 -07001814 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001815 {
1816 return false;
1817 }
1818
Brandon Jonesd1049182018-03-28 10:02:20 -07001819 SetRobustLengthParam(length, numParams);
1820
Geoff Lang2186c382016-10-14 10:54:54 -04001821 return true;
1822}
1823
1824bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1825{
1826 if (numParams)
1827 {
1828 *numParams = 0;
1829 }
1830
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001831 Query *queryObject = context->getQuery(id, false, GL_NONE);
1832
1833 if (!queryObject)
1834 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001835 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001836 return false;
1837 }
1838
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001839 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001840 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001841 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001842 return false;
1843 }
1844
1845 switch (pname)
1846 {
1847 case GL_QUERY_RESULT_EXT:
1848 case GL_QUERY_RESULT_AVAILABLE_EXT:
1849 break;
1850
1851 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001852 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001853 return false;
1854 }
1855
Geoff Lang2186c382016-10-14 10:54:54 -04001856 if (numParams)
1857 {
1858 *numParams = 1;
1859 }
1860
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001861 return true;
1862}
1863
1864bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1865{
1866 if (!context->getExtensions().disjointTimerQuery)
1867 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001868 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001869 return false;
1870 }
Geoff Lang2186c382016-10-14 10:54:54 -04001871 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1872}
1873
1874bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1875 GLuint id,
1876 GLenum pname,
1877 GLsizei bufSize,
1878 GLsizei *length,
1879 GLint *params)
1880{
1881 if (!context->getExtensions().disjointTimerQuery)
1882 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001883 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001884 return false;
1885 }
1886
1887 if (!ValidateRobustEntryPoint(context, bufSize))
1888 {
1889 return false;
1890 }
1891
Brandon Jonesd1049182018-03-28 10:02:20 -07001892 GLsizei numParams = 0;
1893
1894 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001895 {
1896 return false;
1897 }
1898
Brandon Jonesd1049182018-03-28 10:02:20 -07001899 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001900 {
1901 return false;
1902 }
1903
Brandon Jonesd1049182018-03-28 10:02:20 -07001904 SetRobustLengthParam(length, numParams);
1905
Geoff Lang2186c382016-10-14 10:54:54 -04001906 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001907}
1908
1909bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1910{
1911 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001912 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001913 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001914 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001915 return false;
1916 }
Geoff Lang2186c382016-10-14 10:54:54 -04001917 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1918}
1919
1920bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1921 GLuint id,
1922 GLenum pname,
1923 GLsizei bufSize,
1924 GLsizei *length,
1925 GLuint *params)
1926{
1927 if (!context->getExtensions().disjointTimerQuery &&
1928 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1929 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001930 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001931 return false;
1932 }
1933
1934 if (!ValidateRobustEntryPoint(context, bufSize))
1935 {
1936 return false;
1937 }
1938
Brandon Jonesd1049182018-03-28 10:02:20 -07001939 GLsizei numParams = 0;
1940
1941 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001942 {
1943 return false;
1944 }
1945
Brandon Jonesd1049182018-03-28 10:02:20 -07001946 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001947 {
1948 return false;
1949 }
1950
Brandon Jonesd1049182018-03-28 10:02:20 -07001951 SetRobustLengthParam(length, numParams);
1952
Geoff Lang2186c382016-10-14 10:54:54 -04001953 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001954}
1955
1956bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1957{
1958 if (!context->getExtensions().disjointTimerQuery)
1959 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001960 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001961 return false;
1962 }
Geoff Lang2186c382016-10-14 10:54:54 -04001963 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1964}
1965
1966bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1967 GLuint id,
1968 GLenum pname,
1969 GLsizei bufSize,
1970 GLsizei *length,
1971 GLint64 *params)
1972{
1973 if (!context->getExtensions().disjointTimerQuery)
1974 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001975 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001976 return false;
1977 }
1978
1979 if (!ValidateRobustEntryPoint(context, bufSize))
1980 {
1981 return false;
1982 }
1983
Brandon Jonesd1049182018-03-28 10:02:20 -07001984 GLsizei numParams = 0;
1985
1986 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001987 {
1988 return false;
1989 }
1990
Brandon Jonesd1049182018-03-28 10:02:20 -07001991 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001992 {
1993 return false;
1994 }
1995
Brandon Jonesd1049182018-03-28 10:02:20 -07001996 SetRobustLengthParam(length, numParams);
1997
Geoff Lang2186c382016-10-14 10:54:54 -04001998 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001999}
2000
2001bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2002{
2003 if (!context->getExtensions().disjointTimerQuery)
2004 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002005 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002006 return false;
2007 }
Geoff Lang2186c382016-10-14 10:54:54 -04002008 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2009}
2010
2011bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2012 GLuint id,
2013 GLenum pname,
2014 GLsizei bufSize,
2015 GLsizei *length,
2016 GLuint64 *params)
2017{
2018 if (!context->getExtensions().disjointTimerQuery)
2019 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002020 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002021 return false;
2022 }
2023
2024 if (!ValidateRobustEntryPoint(context, bufSize))
2025 {
2026 return false;
2027 }
2028
Brandon Jonesd1049182018-03-28 10:02:20 -07002029 GLsizei numParams = 0;
2030
2031 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002032 {
2033 return false;
2034 }
2035
Brandon Jonesd1049182018-03-28 10:02:20 -07002036 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002037 {
2038 return false;
2039 }
2040
Brandon Jonesd1049182018-03-28 10:02:20 -07002041 SetRobustLengthParam(length, numParams);
2042
Geoff Lang2186c382016-10-14 10:54:54 -04002043 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002044}
2045
Jamie Madill5b772312018-03-08 20:28:32 -05002046bool ValidateUniformCommonBase(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002047 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002048 GLint location,
2049 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002050 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002051{
Jiajia Qin5451d532017-11-16 17:16:34 +08002052 // TODO(Jiajia): Add image uniform check in future.
2053 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002054 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002055 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002056 return false;
2057 }
2058
Jiajia Qin5451d532017-11-16 17:16:34 +08002059 if (!program)
2060 {
2061 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2062 return false;
2063 }
2064
2065 if (!program->isLinked())
2066 {
2067 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2068 return false;
2069 }
2070
2071 if (location == -1)
2072 {
2073 // Silently ignore the uniform command
2074 return false;
2075 }
2076
2077 const auto &uniformLocations = program->getUniformLocations();
2078 size_t castedLocation = static_cast<size_t>(location);
2079 if (castedLocation >= uniformLocations.size())
2080 {
2081 context->handleError(InvalidOperation() << "Invalid uniform location");
2082 return false;
2083 }
2084
2085 const auto &uniformLocation = uniformLocations[castedLocation];
2086 if (uniformLocation.ignored)
2087 {
2088 // Silently ignore the uniform command
2089 return false;
2090 }
2091
2092 if (!uniformLocation.used())
2093 {
2094 context->handleError(InvalidOperation());
2095 return false;
2096 }
2097
2098 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2099
2100 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2101 if (!uniform.isArray() && count > 1)
2102 {
2103 context->handleError(InvalidOperation());
2104 return false;
2105 }
2106
2107 *uniformOut = &uniform;
2108 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002109}
2110
Jamie Madill5b772312018-03-08 20:28:32 -05002111bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002112 GLenum uniformType,
2113 GLsizei count,
2114 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002115{
Jiajia Qin5451d532017-11-16 17:16:34 +08002116 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2117 // It is compatible with INT or BOOL.
2118 // Do these cheap tests first, for a little extra speed.
2119 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002120 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002121 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002122 }
2123
Jiajia Qin5451d532017-11-16 17:16:34 +08002124 if (IsSamplerType(uniformType))
2125 {
2126 // Check that the values are in range.
2127 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2128 for (GLsizei i = 0; i < count; ++i)
2129 {
2130 if (value[i] < 0 || value[i] >= max)
2131 {
2132 context->handleError(InvalidValue() << "sampler uniform value out of range");
2133 return false;
2134 }
2135 }
2136 return true;
2137 }
2138
2139 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2140 return false;
2141}
2142
Jamie Madill5b772312018-03-08 20:28:32 -05002143bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002144{
2145 // Check that the value type is compatible with uniform type.
2146 // Do the cheaper test first, for a little extra speed.
2147 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2148 {
2149 return true;
2150 }
2151
2152 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2153 return false;
2154}
2155
Jamie Madill5b772312018-03-08 20:28:32 -05002156bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002157{
2158 // Check that the value type is compatible with uniform type.
2159 if (valueType == uniformType)
2160 {
2161 return true;
2162 }
2163
2164 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2165 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002166}
2167
Jamie Madill5b772312018-03-08 20:28:32 -05002168bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002169{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002170 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002171 gl::Program *programObject = context->getGLState().getProgram();
2172 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2173 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002174}
2175
Jamie Madill5b772312018-03-08 20:28:32 -05002176bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002177{
2178 const LinkedUniform *uniform = nullptr;
2179 gl::Program *programObject = context->getGLState().getProgram();
2180 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2181 ValidateUniform1ivValue(context, uniform->type, count, value);
2182}
2183
Jamie Madill5b772312018-03-08 20:28:32 -05002184bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002185 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002186 GLint location,
2187 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002188 GLboolean transpose)
2189{
Geoff Lang92019432017-11-20 13:09:34 -05002190 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002191 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002192 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002193 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002194 }
2195
Jamie Madill62d31cb2015-09-11 13:25:51 -04002196 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002197 gl::Program *programObject = context->getGLState().getProgram();
2198 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2199 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002200}
2201
Jamie Madill5b772312018-03-08 20:28:32 -05002202bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002203{
2204 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2205 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002206 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002207 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002208 }
2209
Jamie Madill0af26e12015-03-05 19:54:33 -05002210 const Caps &caps = context->getCaps();
2211
Jamie Madill893ab082014-05-16 16:56:10 -04002212 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2213 {
2214 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2215
Jamie Madill0af26e12015-03-05 19:54:33 -05002216 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002217 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002218 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002219 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002220 }
2221 }
2222
2223 switch (pname)
2224 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002225 case GL_TEXTURE_BINDING_2D:
2226 case GL_TEXTURE_BINDING_CUBE_MAP:
2227 case GL_TEXTURE_BINDING_3D:
2228 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002229 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002230 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002231 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2232 if (!context->getExtensions().textureRectangle)
2233 {
2234 context->handleError(InvalidEnum()
2235 << "ANGLE_texture_rectangle extension not present");
2236 return false;
2237 }
2238 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002239 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2240 if (!context->getExtensions().eglStreamConsumerExternal &&
2241 !context->getExtensions().eglImageExternal)
2242 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002243 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2244 "nor GL_OES_EGL_image_external "
2245 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002246 return false;
2247 }
2248 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002249
He Yunchaoced53ae2016-11-29 15:00:51 +08002250 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2251 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002252 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002253 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2254 ASSERT(readFramebuffer);
2255
2256 if (!ValidateFramebufferComplete(context, readFramebuffer, false))
Jamie Madill893ab082014-05-16 16:56:10 -04002257 {
Geoff Langb1196682014-07-23 13:47:29 -04002258 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002259 }
2260
Jamie Madille98b1b52018-03-08 09:47:23 -05002261 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002262 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002263 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002264 return false;
2265 }
2266
Jamie Madille98b1b52018-03-08 09:47:23 -05002267 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002268 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002269 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002270 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002271 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002272 }
2273 }
2274 break;
2275
He Yunchaoced53ae2016-11-29 15:00:51 +08002276 default:
2277 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002278 }
2279
2280 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002281 if (*numParams == 0)
2282 {
2283 return false;
2284 }
2285
2286 return true;
2287}
2288
Brandon Jonesd1049182018-03-28 10:02:20 -07002289bool ValidateGetBooleanvRobustANGLE(Context *context,
2290 GLenum pname,
2291 GLsizei bufSize,
2292 GLsizei *length,
2293 GLboolean *params)
2294{
2295 GLenum nativeType;
2296 unsigned int numParams = 0;
2297
2298 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2299 {
2300 return false;
2301 }
2302
2303 SetRobustLengthParam(length, numParams);
2304
2305 return true;
2306}
2307
2308bool ValidateGetFloatvRobustANGLE(Context *context,
2309 GLenum pname,
2310 GLsizei bufSize,
2311 GLsizei *length,
2312 GLfloat *params)
2313{
2314 GLenum nativeType;
2315 unsigned int numParams = 0;
2316
2317 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2318 {
2319 return false;
2320 }
2321
2322 SetRobustLengthParam(length, numParams);
2323
2324 return true;
2325}
2326
2327bool ValidateGetIntegervRobustANGLE(Context *context,
2328 GLenum pname,
2329 GLsizei bufSize,
2330 GLsizei *length,
2331 GLint *data)
2332{
2333 GLenum nativeType;
2334 unsigned int numParams = 0;
2335
2336 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2337 {
2338 return false;
2339 }
2340
2341 SetRobustLengthParam(length, numParams);
2342
2343 return true;
2344}
2345
2346bool ValidateGetInteger64vRobustANGLE(Context *context,
2347 GLenum pname,
2348 GLsizei bufSize,
2349 GLsizei *length,
2350 GLint64 *data)
2351{
2352 GLenum nativeType;
2353 unsigned int numParams = 0;
2354
2355 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2356 {
2357 return false;
2358 }
2359
2360 if (nativeType == GL_INT_64_ANGLEX)
2361 {
2362 CastStateValues(context, nativeType, pname, numParams, data);
2363 return false;
2364 }
2365
2366 SetRobustLengthParam(length, numParams);
2367 return true;
2368}
2369
Jamie Madill5b772312018-03-08 20:28:32 -05002370bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002371 GLenum pname,
2372 GLsizei bufSize,
2373 GLenum *nativeType,
2374 unsigned int *numParams)
2375{
2376 if (!ValidateRobustEntryPoint(context, bufSize))
2377 {
2378 return false;
2379 }
2380
2381 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2382 {
2383 return false;
2384 }
2385
2386 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002387 {
2388 return false;
2389 }
2390
2391 return true;
2392}
2393
Jamie Madill5b772312018-03-08 20:28:32 -05002394bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002395 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002396 GLint level,
2397 GLenum internalformat,
2398 bool isSubImage,
2399 GLint xoffset,
2400 GLint yoffset,
2401 GLint zoffset,
2402 GLint x,
2403 GLint y,
2404 GLsizei width,
2405 GLsizei height,
2406 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002407 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002408{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002409 TextureType texType = TextureTargetToType(target);
2410
Brandon Jones6cad5662017-06-14 13:25:13 -07002411 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002412 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002413 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2414 return false;
2415 }
2416
2417 if (width < 0 || height < 0)
2418 {
2419 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002420 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002421 }
2422
He Yunchaoced53ae2016-11-29 15:00:51 +08002423 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2424 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002425 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002426 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002427 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002428 }
2429
2430 if (border != 0)
2431 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002432 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002433 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002434 }
2435
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002436 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002437 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002438 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002439 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002440 }
2441
Jamie Madille98b1b52018-03-08 09:47:23 -05002442 const gl::State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002443 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madille98b1b52018-03-08 09:47:23 -05002444 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madill560a8d82014-05-21 13:06:20 -04002445 {
Geoff Langb1196682014-07-23 13:47:29 -04002446 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002447 }
2448
Jamie Madille98b1b52018-03-08 09:47:23 -05002449 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002450 {
Geoff Langb1196682014-07-23 13:47:29 -04002451 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002452 }
2453
Martin Radev138064f2016-07-15 12:03:41 +03002454 if (readFramebuffer->getReadBufferState() == GL_NONE)
2455 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002456 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002457 return false;
2458 }
2459
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002460 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2461 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002462 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002463 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002464 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2465 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002466 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002467 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002468 return false;
2469 }
2470
Martin Radev04e2c3b2017-07-27 16:54:35 +03002471 // ANGLE_multiview spec, Revision 1:
2472 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2473 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2474 // is not NONE.
2475 if (source->getMultiviewLayout() != GL_NONE)
2476 {
2477 context->handleError(InvalidFramebufferOperation()
2478 << "The active read framebuffer object has multiview attachments.");
2479 return false;
2480 }
2481
Geoff Langaae65a42014-05-26 12:43:44 -04002482 const gl::Caps &caps = context->getCaps();
2483
Geoff Langaae65a42014-05-26 12:43:44 -04002484 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002485 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002486 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002487 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002488 maxDimension = caps.max2DTextureSize;
2489 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002490
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002491 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002492 maxDimension = caps.maxCubeMapTextureSize;
2493 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002494
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002495 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002496 maxDimension = caps.maxRectangleTextureSize;
2497 break;
2498
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002499 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002500 maxDimension = caps.max2DTextureSize;
2501 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002502
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002503 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002504 maxDimension = caps.max3DTextureSize;
2505 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002506
He Yunchaoced53ae2016-11-29 15:00:51 +08002507 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002508 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002509 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002510 }
2511
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002512 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002513 if (!texture)
2514 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002515 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002516 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002517 }
2518
Geoff Lang69cce582015-09-17 13:20:36 -04002519 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002521 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002522 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002523 }
2524
Geoff Langca271392017-04-05 12:30:00 -04002525 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002526 isSubImage ? *texture->getFormat(target, level).info
2527 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002528
Geoff Lang966c9402017-04-18 12:38:27 -04002529 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002530 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002531 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002532 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002533 }
2534
2535 if (isSubImage)
2536 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002537 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2538 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2539 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002540 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002541 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002542 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002543 }
2544 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002545 else
2546 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002547 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002548 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002549 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002550 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002551 }
2552
Geoff Langeb66a6e2016-10-31 13:06:12 -04002553 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002554 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002555 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002556 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002557 }
2558
2559 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002560 if (static_cast<int>(width) > maxLevelDimension ||
2561 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002562 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002563 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002564 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002565 }
2566 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002567
Jamie Madill0c8abca2016-07-22 20:21:26 -04002568 if (textureFormatOut)
2569 {
2570 *textureFormatOut = texture->getFormat(target, level);
2571 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002572
2573 // Detect texture copying feedback loops for WebGL.
2574 if (context->getExtensions().webglCompatibility)
2575 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002576 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002577 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002578 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002579 return false;
2580 }
2581 }
2582
Jamie Madill560a8d82014-05-21 13:06:20 -04002583 return true;
2584}
2585
Jamie Madill5b772312018-03-08 20:28:32 -05002586bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002587{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002588 const Extensions &extensions = context->getExtensions();
2589
Jamie Madill1aeb1312014-06-20 13:21:25 -04002590 switch (mode)
2591 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002592 case GL_POINTS:
2593 case GL_LINES:
2594 case GL_LINE_LOOP:
2595 case GL_LINE_STRIP:
2596 case GL_TRIANGLES:
2597 case GL_TRIANGLE_STRIP:
2598 case GL_TRIANGLE_FAN:
2599 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002600
2601 case GL_LINES_ADJACENCY_EXT:
2602 case GL_LINE_STRIP_ADJACENCY_EXT:
2603 case GL_TRIANGLES_ADJACENCY_EXT:
2604 case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
2605 if (!extensions.geometryShader)
2606 {
2607 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2608 return false;
2609 }
2610 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002611 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002612 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002613 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002614 }
2615
Jamie Madill250d33f2014-06-06 17:09:03 -04002616 if (count < 0)
2617 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002618 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002619 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002620 }
2621
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002622 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002623
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002624 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2625 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2626 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2627 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002628 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002629 // Check for mapped buffers
2630 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002631 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002632 {
2633 context->handleError(InvalidOperation());
2634 return false;
2635 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002636 }
2637
Jamie Madillcbcde722017-01-06 14:50:00 -05002638 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2639 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002640 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002641 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002642 {
Ken Russellb9f92502018-01-27 19:00:26 -08002643 ASSERT(framebuffer);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002644 const FramebufferAttachment *dsAttachment =
2645 framebuffer->getStencilOrDepthStencilAttachment();
Ken Russellb9f92502018-01-27 19:00:26 -08002646 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2647 ASSERT(stencilBits <= 8);
2648
Jinyoung Hur85769f02015-10-20 17:08:44 -04002649 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Ken Russellb9f92502018-01-27 19:00:26 -08002650 if (depthStencilState.stencilTest && stencilBits > 0)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002651 {
Ken Russellb9f92502018-01-27 19:00:26 -08002652 GLuint maxStencilValue = (1 << stencilBits) - 1;
2653
2654 bool differentRefs =
2655 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2656 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2657 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2658 (depthStencilState.stencilBackWritemask & maxStencilValue);
2659 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2660 (depthStencilState.stencilBackMask & maxStencilValue);
2661
2662 if (differentRefs || differentWritemasks || differentMasks)
Jamie Madillcbcde722017-01-06 14:50:00 -05002663 {
Ken Russellb9f92502018-01-27 19:00:26 -08002664 if (!extensions.webglCompatibility)
2665 {
2666 ERR() << "This ANGLE implementation does not support separate front/back "
2667 "stencil writemasks, reference values, or stencil mask values.";
2668 }
2669 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
2670 return false;
Jamie Madillcbcde722017-01-06 14:50:00 -05002671 }
Geoff Lang3a86ad32015-09-01 11:47:05 -04002672 }
Jamie Madillac528012014-06-20 13:21:23 -04002673 }
2674
Jamie Madille98b1b52018-03-08 09:47:23 -05002675 if (!ValidateFramebufferComplete(context, framebuffer, true))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002676 {
Geoff Langb1196682014-07-23 13:47:29 -04002677 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002678 }
2679
Geoff Lang7dd2e102014-11-10 15:19:26 -05002680 gl::Program *program = state.getProgram();
2681 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002682 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002683 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002684 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002685 }
2686
Yunchao Hecddcb592017-11-13 15:27:35 +08002687 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2688 // vertex shader stage or fragment shader stage is a undefined behaviour.
2689 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2690 // produce undefined result.
Jiawei Shao385b3e02018-03-21 09:43:28 +08002691 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2692 !program->hasLinkedShaderStage(ShaderType::Fragment))
Yunchao Hecddcb592017-11-13 15:27:35 +08002693 {
2694 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2695 "vertex shader stage or fragment shader stage.");
2696 return false;
2697 }
2698
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002699 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002700 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002701 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002702 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002703 }
2704
Martin Radevffe754b2017-07-31 10:38:07 +03002705 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002706 {
Martin Radevda8e2572017-09-12 17:21:16 +03002707 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002708 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002709 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002710 {
2711 context->handleError(InvalidOperation() << "The number of views in the active program "
2712 "and draw framebuffer does not match.");
2713 return false;
2714 }
Martin Radev7e69f762017-07-27 14:54:13 +03002715
2716 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2717 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2718 framebufferNumViews > 1)
2719 {
2720 context->handleError(InvalidOperation()
2721 << "There is an active transform feedback object "
2722 "when the number of views in the active draw "
2723 "framebuffer is greater than 1.");
2724 return false;
2725 }
Martin Radevffe754b2017-07-31 10:38:07 +03002726
2727 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2728 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2729 {
2730 context->handleError(InvalidOperation() << "There is an active query for target "
2731 "GL_TIME_ELAPSED_EXT when the number of "
2732 "views in the active draw framebuffer is "
2733 "greater than 1.");
2734 return false;
2735 }
Martin Radev7cf61662017-07-26 17:10:53 +03002736 }
2737
Jiawei Shaofccebff2018-03-08 13:51:02 +08002738 // Do geometry shader specific validations
Jiawei Shao385b3e02018-03-21 09:43:28 +08002739 if (program->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shaofccebff2018-03-08 13:51:02 +08002740 {
2741 if (!IsCompatibleDrawModeWithGeometryShader(mode,
2742 program->getGeometryShaderInputPrimitiveType()))
2743 {
2744 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2745 IncompatibleDrawModeAgainstGeometryShader);
2746 return false;
2747 }
2748 }
2749
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002750 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002751 for (unsigned int uniformBlockIndex = 0;
2752 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002753 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002754 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002755 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002756 const OffsetBindingPointer<Buffer> &uniformBuffer =
2757 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002758
Geoff Lang5d124a62015-09-15 13:03:27 -04002759 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002760 {
2761 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002762 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002763 InvalidOperation()
2764 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002765 return false;
2766 }
2767
Geoff Lang5d124a62015-09-15 13:03:27 -04002768 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002769 if (uniformBufferSize == 0)
2770 {
2771 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002772 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002773 }
2774
Jamie Madill62d31cb2015-09-11 13:25:51 -04002775 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002776 {
2777 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002778 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002779 InvalidOperation()
2780 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002781 return false;
2782 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002783
2784 if (extensions.webglCompatibility &&
2785 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2786 {
2787 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2788 UniformBufferBoundForTransformFeedback);
2789 return false;
2790 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002791 }
2792
Geoff Lange0cff192017-05-30 13:04:56 -04002793 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002794 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002795 {
James Darpiniane8a93c62018-01-04 18:02:24 -08002796 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2797 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2798 transformFeedbackObject->buffersBoundForOtherUse())
2799 {
2800 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferDoubleBound);
2801 return false;
2802 }
Geoff Lange0cff192017-05-30 13:04:56 -04002803 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002804 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2805 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002806 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002807 return false;
2808 }
Geoff Lange0cff192017-05-30 13:04:56 -04002809
Geoff Lang9ab5b822017-05-30 16:19:23 -04002810 // Detect that the vertex shader input types match the attribute types
2811 if (!ValidateVertexShaderAttributeTypeMatch(context))
2812 {
2813 return false;
2814 }
2815
Geoff Lange0cff192017-05-30 13:04:56 -04002816 // Detect that the color buffer types match the fragment shader output types
2817 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2818 {
2819 return false;
2820 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002821 }
2822
Jamie Madill9fdaa492018-02-16 10:52:11 -05002823 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002824}
2825
Jamie Madill5b772312018-03-08 20:28:32 -05002826bool ValidateDrawArraysCommon(Context *context,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002827 GLenum mode,
2828 GLint first,
2829 GLsizei count,
2830 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002831{
Jamie Madillfd716582014-06-06 17:09:04 -04002832 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002833 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002834 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002835 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002836 }
2837
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002838 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002839 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002840 if (curTransformFeedback && curTransformFeedback->isActive() &&
2841 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002842 {
2843 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002844 // that does not match the current transform feedback object's draw mode (if transform
2845 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002846 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002847 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002848 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002849 }
2850
Jiajia Qind9671222016-11-29 16:30:31 +08002851 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002852 {
2853 return false;
2854 }
2855
Corentin Wallez71168a02016-12-19 15:11:18 -08002856 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002857 // - first < 0 has been checked as an error condition.
2858 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002859 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002860 ASSERT(first >= 0);
2861 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002862 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002863 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2864 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2865 {
2866 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2867 return false;
2868 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002869
Jamie Madill9fdaa492018-02-16 10:52:11 -05002870 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2871 {
2872 return false;
2873 }
Jamie Madillfd716582014-06-06 17:09:04 -04002874 }
2875
2876 return true;
2877}
2878
He Yunchaoced53ae2016-11-29 15:00:51 +08002879bool ValidateDrawArraysInstancedANGLE(Context *context,
2880 GLenum mode,
2881 GLint first,
2882 GLsizei count,
2883 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002884{
Geoff Lang63c5a592017-09-27 14:08:16 -04002885 if (!context->getExtensions().instancedArrays)
2886 {
2887 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2888 return false;
2889 }
2890
Corentin Wallez170efbf2017-05-02 13:45:01 -04002891 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002892 {
2893 return false;
2894 }
2895
Corentin Wallez0dc97812017-06-22 14:38:44 -04002896 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002897}
2898
Jamie Madill5b772312018-03-08 20:28:32 -05002899bool ValidateDrawElementsBase(Context *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002900{
Jamie Madill250d33f2014-06-06 17:09:03 -04002901 switch (type)
2902 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002903 case GL_UNSIGNED_BYTE:
2904 case GL_UNSIGNED_SHORT:
2905 break;
2906 case GL_UNSIGNED_INT:
2907 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2908 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002909 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002910 return false;
2911 }
2912 break;
2913 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002914 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002915 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002916 }
2917
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002918 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002919
2920 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002921 if (curTransformFeedback && curTransformFeedback->isActive() &&
2922 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002923 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002924 // It is an invalid operation to call DrawElements, DrawRangeElements or
2925 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002926 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002927 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002928 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002929 }
2930
Jiajia Qind9671222016-11-29 16:30:31 +08002931 return true;
2932}
2933
Jamie Madill5b772312018-03-08 20:28:32 -05002934bool ValidateDrawElementsCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002935 GLenum mode,
2936 GLsizei count,
2937 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002938 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002939 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002940{
2941 if (!ValidateDrawElementsBase(context, type))
2942 return false;
2943
2944 const State &state = context->getGLState();
2945
Corentin Wallez170efbf2017-05-02 13:45:01 -04002946 if (!ValidateDrawBase(context, mode, count))
2947 {
2948 return false;
2949 }
2950
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002951 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2952 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2953 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2954 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002955 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002956 // Check for mapped buffers
2957 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002958 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002959 {
2960 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2961 return false;
2962 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002963 }
2964
He Yunchaoced53ae2016-11-29 15:00:51 +08002965 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002966 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002967
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002968 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2969
2970 if (context->getExtensions().webglCompatibility)
2971 {
2972 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2973 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2974 {
2975 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2976 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2977 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002978 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002979 return false;
2980 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002981
2982 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2983 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2984 // error is generated.
2985 if (reinterpret_cast<intptr_t>(indices) < 0)
2986 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002987 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002988 return false;
2989 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002990 }
2991
2992 if (context->getExtensions().webglCompatibility ||
2993 !context->getGLState().areClientArraysEnabled())
2994 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002995 if (!elementArrayBuffer && count > 0)
2996 {
2997 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2998 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2999 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003000 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003001 return false;
3002 }
3003 }
3004
Jamie Madill9fdaa492018-02-16 10:52:11 -05003005 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003006 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003007 // This is an application error that would normally result in a crash, but we catch it and
3008 // return an error
3009 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3010 return false;
3011 }
3012
3013 if (count > 0 && elementArrayBuffer)
3014 {
3015 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3016 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3017 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3018 constexpr uint64_t kMaxTypeSize = 8;
3019 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3020 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3021 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3022
3023 uint64_t typeSize = typeBytes;
3024 uint64_t elementCount = static_cast<uint64_t>(count);
3025 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3026
3027 // Doing the multiplication here is overflow-safe
3028 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3029
3030 // The offset can be any value, check for overflows
3031 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3032 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003033 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003034 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3035 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003036 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003037
3038 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3039 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003040 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003041 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3042 return false;
3043 }
3044
3045 ASSERT(isPow2(typeSize) && typeSize > 0);
3046 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3047 {
3048 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003049 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003050 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003051
3052 if (context->getExtensions().webglCompatibility &&
3053 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3054 {
3055 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3056 ElementArrayBufferBoundForTransformFeedback);
3057 return false;
3058 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003059 }
3060
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003061 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003062 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003063 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
3064 // access is enabled.
3065 if (!ValidateDrawAttribs(context, primcount, 0, 1))
3066 {
3067 return false;
3068 }
3069 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003070 else if (count == 0)
3071 {
3072 // ValidateDrawAttribs also does some extra validation that is independent of the vertex
3073 // count.
3074 if (!ValidateDrawAttribs(context, 0, 0, 0))
3075 {
3076 return false;
3077 }
3078 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003079 else
3080 {
3081 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003082 const DrawCallParams &params = context->getParams<DrawCallParams>();
3083 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3084 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003085
3086 // If we use an index greater than our maximum supported index range, return an error.
3087 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3088 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003089 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003090 {
3091 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3092 return false;
3093 }
3094
Jamie Madill6f5444d2018-03-14 10:08:11 -04003095 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end),
3096 static_cast<GLint>(indexRange.vertexCount())))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003097 {
3098 return false;
3099 }
3100
3101 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003102 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003103 }
3104
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003105 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003106}
3107
Jamie Madill5b772312018-03-08 20:28:32 -05003108bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003109 GLenum mode,
3110 GLsizei count,
3111 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003112 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003113 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003114{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003115 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003116}
3117
Geoff Lang3edfe032015-09-04 16:38:24 -04003118bool ValidateDrawElementsInstancedANGLE(Context *context,
3119 GLenum mode,
3120 GLsizei count,
3121 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003122 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003123 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003124{
Geoff Lang63c5a592017-09-27 14:08:16 -04003125 if (!context->getExtensions().instancedArrays)
3126 {
3127 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3128 return false;
3129 }
3130
Corentin Wallez170efbf2017-05-02 13:45:01 -04003131 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003132 {
3133 return false;
3134 }
3135
Corentin Wallez0dc97812017-06-22 14:38:44 -04003136 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003137}
3138
He Yunchaoced53ae2016-11-29 15:00:51 +08003139bool ValidateFramebufferTextureBase(Context *context,
3140 GLenum target,
3141 GLenum attachment,
3142 GLuint texture,
3143 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003144{
Geoff Lange8afa902017-09-27 15:00:43 -04003145 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003146 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003147 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003148 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003149 }
3150
3151 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003152 {
3153 return false;
3154 }
3155
Jamie Madill55ec3b12014-07-03 10:38:57 -04003156 if (texture != 0)
3157 {
3158 gl::Texture *tex = context->getTexture(texture);
3159
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003160 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003161 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003162 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003163 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003164 }
3165
3166 if (level < 0)
3167 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003168 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003169 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003170 }
3171 }
3172
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003173 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003174 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003175
Jamie Madill84115c92015-04-23 15:00:07 -04003176 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003177 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003178 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003179 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003180 }
3181
3182 return true;
3183}
3184
Geoff Langb1196682014-07-23 13:47:29 -04003185bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003186{
3187 if (program == 0)
3188 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003189 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003190 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003191 }
3192
Dian Xiang769769a2015-09-09 15:20:08 -07003193 gl::Program *programObject = GetValidProgram(context, program);
3194 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003195 {
3196 return false;
3197 }
3198
Jamie Madill0063c512014-08-25 15:47:53 -04003199 if (!programObject || !programObject->isLinked())
3200 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003201 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003202 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003203 }
3204
Geoff Lang7dd2e102014-11-10 15:19:26 -05003205 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003206 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003207 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003208 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003209 }
3210
Jamie Madill0063c512014-08-25 15:47:53 -04003211 return true;
3212}
3213
Geoff Langf41d0ee2016-10-07 13:04:23 -04003214static bool ValidateSizedGetUniform(Context *context,
3215 GLuint program,
3216 GLint location,
3217 GLsizei bufSize,
3218 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003219{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003220 if (length)
3221 {
3222 *length = 0;
3223 }
3224
Jamie Madill78f41802014-08-25 15:47:55 -04003225 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003226 {
Jamie Madill78f41802014-08-25 15:47:55 -04003227 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003228 }
3229
Geoff Langf41d0ee2016-10-07 13:04:23 -04003230 if (bufSize < 0)
3231 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003232 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003233 return false;
3234 }
3235
Jamie Madilla502c742014-08-28 17:19:13 -04003236 gl::Program *programObject = context->getProgram(program);
3237 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003238
Jamie Madill78f41802014-08-25 15:47:55 -04003239 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003240 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003241 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003242 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003243 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003244 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003245 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003246 }
3247
Geoff Langf41d0ee2016-10-07 13:04:23 -04003248 if (length)
3249 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003250 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003251 }
3252
Jamie Madill0063c512014-08-25 15:47:53 -04003253 return true;
3254}
3255
He Yunchaoced53ae2016-11-29 15:00:51 +08003256bool ValidateGetnUniformfvEXT(Context *context,
3257 GLuint program,
3258 GLint location,
3259 GLsizei bufSize,
3260 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003261{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003262 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003263}
3264
He Yunchaoced53ae2016-11-29 15:00:51 +08003265bool ValidateGetnUniformivEXT(Context *context,
3266 GLuint program,
3267 GLint location,
3268 GLsizei bufSize,
3269 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003270{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003271 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3272}
3273
3274bool ValidateGetUniformfvRobustANGLE(Context *context,
3275 GLuint program,
3276 GLint location,
3277 GLsizei bufSize,
3278 GLsizei *length,
3279 GLfloat *params)
3280{
3281 if (!ValidateRobustEntryPoint(context, bufSize))
3282 {
3283 return false;
3284 }
3285
Brandon Jonesd1049182018-03-28 10:02:20 -07003286 GLsizei writeLength = 0;
3287
Geoff Langf41d0ee2016-10-07 13:04:23 -04003288 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003289 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3290 {
3291 return false;
3292 }
3293
3294 SetRobustLengthParam(length, writeLength);
3295
3296 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003297}
3298
3299bool ValidateGetUniformivRobustANGLE(Context *context,
3300 GLuint program,
3301 GLint location,
3302 GLsizei bufSize,
3303 GLsizei *length,
3304 GLint *params)
3305{
3306 if (!ValidateRobustEntryPoint(context, bufSize))
3307 {
3308 return false;
3309 }
3310
Brandon Jonesd1049182018-03-28 10:02:20 -07003311 GLsizei writeLength = 0;
3312
Geoff Langf41d0ee2016-10-07 13:04:23 -04003313 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003314 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3315 {
3316 return false;
3317 }
3318
3319 SetRobustLengthParam(length, writeLength);
3320
3321 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003322}
3323
3324bool ValidateGetUniformuivRobustANGLE(Context *context,
3325 GLuint program,
3326 GLint location,
3327 GLsizei bufSize,
3328 GLsizei *length,
3329 GLuint *params)
3330{
3331 if (!ValidateRobustEntryPoint(context, bufSize))
3332 {
3333 return false;
3334 }
3335
3336 if (context->getClientMajorVersion() < 3)
3337 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003338 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003339 return false;
3340 }
3341
Brandon Jonesd1049182018-03-28 10:02:20 -07003342 GLsizei writeLength = 0;
3343
Geoff Langf41d0ee2016-10-07 13:04:23 -04003344 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003345 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3346 {
3347 return false;
3348 }
3349
3350 SetRobustLengthParam(length, writeLength);
3351
3352 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003353}
3354
He Yunchaoced53ae2016-11-29 15:00:51 +08003355bool ValidateDiscardFramebufferBase(Context *context,
3356 GLenum target,
3357 GLsizei numAttachments,
3358 const GLenum *attachments,
3359 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003360{
3361 if (numAttachments < 0)
3362 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003363 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003364 return false;
3365 }
3366
3367 for (GLsizei i = 0; i < numAttachments; ++i)
3368 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003369 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003370 {
3371 if (defaultFramebuffer)
3372 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003373 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003374 return false;
3375 }
3376
3377 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3378 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003379 context->handleError(InvalidOperation() << "Requested color attachment is "
3380 "greater than the maximum supported "
3381 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003382 return false;
3383 }
3384 }
3385 else
3386 {
3387 switch (attachments[i])
3388 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003389 case GL_DEPTH_ATTACHMENT:
3390 case GL_STENCIL_ATTACHMENT:
3391 case GL_DEPTH_STENCIL_ATTACHMENT:
3392 if (defaultFramebuffer)
3393 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003394 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3395 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003396 return false;
3397 }
3398 break;
3399 case GL_COLOR:
3400 case GL_DEPTH:
3401 case GL_STENCIL:
3402 if (!defaultFramebuffer)
3403 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003404 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3405 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003406 return false;
3407 }
3408 break;
3409 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003410 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003411 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003412 }
3413 }
3414 }
3415
3416 return true;
3417}
3418
Austin Kinross6ee1e782015-05-29 17:05:37 -07003419bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3420{
Jamie Madill007530e2017-12-28 14:27:04 -05003421 if (!context->getExtensions().debugMarker)
3422 {
3423 // The debug marker calls should not set error state
3424 // However, it seems reasonable to set an error state if the extension is not enabled
3425 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3426 return false;
3427 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003428
Jamie Madill007530e2017-12-28 14:27:04 -05003429 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003430 if (length < 0)
3431 {
3432 return false;
3433 }
3434
3435 if (marker == nullptr)
3436 {
3437 return false;
3438 }
3439
3440 return true;
3441}
3442
3443bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3444{
Jamie Madill007530e2017-12-28 14:27:04 -05003445 if (!context->getExtensions().debugMarker)
3446 {
3447 // The debug marker calls should not set error state
3448 // However, it seems reasonable to set an error state if the extension is not enabled
3449 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3450 return false;
3451 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003452
Jamie Madill007530e2017-12-28 14:27:04 -05003453 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003454 if (length < 0)
3455 {
3456 return false;
3457 }
3458
3459 if (length > 0 && marker == nullptr)
3460 {
3461 return false;
3462 }
3463
3464 return true;
3465}
3466
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003467bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003468{
Geoff Langa8406172015-07-21 16:53:39 -04003469 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3470 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003471 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003472 return false;
3473 }
3474
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003475 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003476 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003477 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003478 if (!context->getExtensions().eglImage)
3479 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003480 context->handleError(InvalidEnum()
3481 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003482 }
3483 break;
3484
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003485 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003486 if (!context->getExtensions().eglImageExternal)
3487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003488 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3489 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003490 }
Geoff Langa8406172015-07-21 16:53:39 -04003491 break;
3492
3493 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003494 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003495 return false;
3496 }
3497
Jamie Madill007530e2017-12-28 14:27:04 -05003498 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3499
Jamie Madill61e16b42017-06-19 11:13:23 -04003500 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003501 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003502 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003503 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003504 return false;
3505 }
3506
Jamie Madill007530e2017-12-28 14:27:04 -05003507 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003508 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003509 context->handleError(InvalidOperation()
3510 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003511 return false;
3512 }
3513
Geoff Langca271392017-04-05 12:30:00 -04003514 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003515 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003516 if (!textureCaps.texturable)
3517 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003518 context->handleError(InvalidOperation()
3519 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003520 return false;
3521 }
3522
Geoff Langdcab33b2015-07-21 13:03:16 -04003523 return true;
3524}
3525
3526bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003527 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003528 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003529{
Geoff Langa8406172015-07-21 16:53:39 -04003530 if (!context->getExtensions().eglImage)
3531 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003532 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003533 return false;
3534 }
3535
3536 switch (target)
3537 {
3538 case GL_RENDERBUFFER:
3539 break;
3540
3541 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003542 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003543 return false;
3544 }
3545
Jamie Madill007530e2017-12-28 14:27:04 -05003546 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3547
Jamie Madill61e16b42017-06-19 11:13:23 -04003548 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003549 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003550 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003551 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003552 return false;
3553 }
3554
Geoff Langca271392017-04-05 12:30:00 -04003555 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003556 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003557 if (!textureCaps.renderable)
3558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003559 context->handleError(InvalidOperation()
3560 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003561 return false;
3562 }
3563
Geoff Langdcab33b2015-07-21 13:03:16 -04003564 return true;
3565}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003566
3567bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3568{
Geoff Lang36167ab2015-12-07 10:27:14 -05003569 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003570 {
3571 // The default VAO should always exist
3572 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003573 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003574 return false;
3575 }
3576
3577 return true;
3578}
3579
Geoff Langc5629752015-12-07 16:29:04 -05003580bool ValidateProgramBinaryBase(Context *context,
3581 GLuint program,
3582 GLenum binaryFormat,
3583 const void *binary,
3584 GLint length)
3585{
3586 Program *programObject = GetValidProgram(context, program);
3587 if (programObject == nullptr)
3588 {
3589 return false;
3590 }
3591
3592 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3593 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3594 programBinaryFormats.end())
3595 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003596 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003597 return false;
3598 }
3599
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003600 if (context->hasActiveTransformFeedback(program))
3601 {
3602 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003603 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3604 "is associated with an active transform "
3605 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003606 return false;
3607 }
3608
Geoff Langc5629752015-12-07 16:29:04 -05003609 return true;
3610}
3611
3612bool ValidateGetProgramBinaryBase(Context *context,
3613 GLuint program,
3614 GLsizei bufSize,
3615 GLsizei *length,
3616 GLenum *binaryFormat,
3617 void *binary)
3618{
3619 Program *programObject = GetValidProgram(context, program);
3620 if (programObject == nullptr)
3621 {
3622 return false;
3623 }
3624
3625 if (!programObject->isLinked())
3626 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003627 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003628 return false;
3629 }
3630
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003631 if (context->getCaps().programBinaryFormats.empty())
3632 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003633 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003634 return false;
3635 }
3636
Geoff Langc5629752015-12-07 16:29:04 -05003637 return true;
3638}
Jamie Madillc29968b2016-01-20 11:17:23 -05003639
Jamie Madill5b772312018-03-08 20:28:32 -05003640bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003641{
3642 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003643 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003644 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003645 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3646 return false;
3647 }
3648 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3649 {
3650 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003651 return false;
3652 }
3653
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003654 ASSERT(context->getGLState().getDrawFramebuffer());
3655 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003656 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3657
3658 // This should come first before the check for the default frame buffer
3659 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3660 // rather than INVALID_OPERATION
3661 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3662 {
3663 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3664
3665 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003666 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3667 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003668 {
3669 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003670 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3671 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3672 // 3.1 is still a bit ambiguous about the error, but future specs are
3673 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003674 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003675 return false;
3676 }
3677 else if (bufs[colorAttachment] >= maxColorAttachment)
3678 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003679 context->handleError(InvalidOperation()
3680 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003681 return false;
3682 }
3683 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3684 frameBufferId != 0)
3685 {
3686 // INVALID_OPERATION-GL is bound to buffer and ith argument
3687 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003688 context->handleError(InvalidOperation()
3689 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003690 return false;
3691 }
3692 }
3693
3694 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3695 // and n is not 1 or bufs is bound to value other than BACK and NONE
3696 if (frameBufferId == 0)
3697 {
3698 if (n != 1)
3699 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003700 context->handleError(InvalidOperation()
3701 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003702 return false;
3703 }
3704
3705 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3706 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003707 context->handleError(
3708 InvalidOperation()
3709 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003710 return false;
3711 }
3712 }
3713
3714 return true;
3715}
3716
Geoff Lang496c02d2016-10-20 11:38:11 -07003717bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003718 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003719 GLenum pname,
3720 GLsizei *length,
3721 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003722{
Geoff Lang496c02d2016-10-20 11:38:11 -07003723 if (length)
3724 {
3725 *length = 0;
3726 }
3727
3728 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3729 {
3730 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003731 InvalidOperation()
3732 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003733 return false;
3734 }
3735
Corentin Walleze4477002017-12-01 14:39:58 -05003736 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003737 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003738 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003739 return false;
3740 }
3741
Geoff Lang496c02d2016-10-20 11:38:11 -07003742 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003743 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003744 case GL_BUFFER_MAP_POINTER:
3745 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003746
Geoff Lang496c02d2016-10-20 11:38:11 -07003747 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003748 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003749 return false;
3750 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003751
3752 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3753 // target bound to zero generate an INVALID_OPERATION error."
3754 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003755 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003756 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003757 context->handleError(InvalidOperation()
3758 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003759 return false;
3760 }
3761
Geoff Lang496c02d2016-10-20 11:38:11 -07003762 if (length)
3763 {
3764 *length = 1;
3765 }
3766
Olli Etuaho4f667482016-03-30 15:56:35 +03003767 return true;
3768}
3769
Corentin Wallez336129f2017-10-17 15:55:40 -04003770bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003771{
Corentin Walleze4477002017-12-01 14:39:58 -05003772 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003773 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003774 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003775 return false;
3776 }
3777
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003778 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003779
3780 if (buffer == nullptr || !buffer->isMapped())
3781 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003782 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003783 return false;
3784 }
3785
3786 return true;
3787}
3788
3789bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003790 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003791 GLintptr offset,
3792 GLsizeiptr length,
3793 GLbitfield access)
3794{
Corentin Walleze4477002017-12-01 14:39:58 -05003795 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003796 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003797 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003798 return false;
3799 }
3800
Brandon Jones6cad5662017-06-14 13:25:13 -07003801 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003802 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003803 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3804 return false;
3805 }
3806
3807 if (length < 0)
3808 {
3809 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003810 return false;
3811 }
3812
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003813 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003814
3815 if (!buffer)
3816 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003817 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003818 return false;
3819 }
3820
3821 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003822 CheckedNumeric<size_t> checkedOffset(offset);
3823 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003824
Jamie Madille2e406c2016-06-02 13:04:10 -04003825 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003826 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003827 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003828 return false;
3829 }
3830
3831 // Check for invalid bits in the mask
3832 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3833 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3834 GL_MAP_UNSYNCHRONIZED_BIT;
3835
3836 if (access & ~(allAccessBits))
3837 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003838 context->handleError(InvalidValue()
3839 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003840 return false;
3841 }
3842
3843 if (length == 0)
3844 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003845 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003846 return false;
3847 }
3848
3849 if (buffer->isMapped())
3850 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003851 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003852 return false;
3853 }
3854
3855 // Check for invalid bit combinations
3856 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3857 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003858 context->handleError(InvalidOperation()
3859 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003860 return false;
3861 }
3862
3863 GLbitfield writeOnlyBits =
3864 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3865
3866 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3867 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003868 context->handleError(InvalidOperation()
3869 << "Invalid access bits when mapping buffer for reading: 0x"
3870 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003871 return false;
3872 }
3873
3874 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3875 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003876 context->handleError(
3877 InvalidOperation()
3878 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003879 return false;
3880 }
Geoff Lang79f71042017-08-14 16:43:43 -04003881
3882 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003883}
3884
3885bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003886 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003887 GLintptr offset,
3888 GLsizeiptr length)
3889{
Brandon Jones6cad5662017-06-14 13:25:13 -07003890 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003891 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003892 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3893 return false;
3894 }
3895
3896 if (length < 0)
3897 {
3898 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003899 return false;
3900 }
3901
Corentin Walleze4477002017-12-01 14:39:58 -05003902 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003903 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003904 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003905 return false;
3906 }
3907
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003908 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003909
3910 if (buffer == nullptr)
3911 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003912 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003913 return false;
3914 }
3915
3916 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3917 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003918 context->handleError(InvalidOperation()
3919 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003920 return false;
3921 }
3922
3923 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003924 CheckedNumeric<size_t> checkedOffset(offset);
3925 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003926
Jamie Madille2e406c2016-06-02 13:04:10 -04003927 if (!checkedSize.IsValid() ||
3928 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003929 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003930 context->handleError(InvalidValue()
3931 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003932 return false;
3933 }
3934
3935 return true;
3936}
3937
Olli Etuaho41997e72016-03-10 13:38:39 +02003938bool ValidateGenOrDelete(Context *context, GLint n)
3939{
3940 if (n < 0)
3941 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003942 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003943 return false;
3944 }
3945 return true;
3946}
3947
Jamie Madill5b772312018-03-08 20:28:32 -05003948bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003949{
3950 if (!context->getExtensions().robustClientMemory)
3951 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003952 context->handleError(InvalidOperation()
3953 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003954 return false;
3955 }
3956
3957 if (bufSize < 0)
3958 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003959 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003960 return false;
3961 }
3962
3963 return true;
3964}
3965
Jamie Madill5b772312018-03-08 20:28:32 -05003966bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003967{
3968 if (bufSize < numParams)
3969 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003970 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3971 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003972 return false;
3973 }
3974
3975 return true;
3976}
3977
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003978bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04003979 GLenum target,
3980 GLenum attachment,
3981 GLenum pname,
3982 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003983{
Geoff Lange8afa902017-09-27 15:00:43 -04003984 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003985 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003986 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003987 return false;
3988 }
3989
3990 int clientVersion = context->getClientMajorVersion();
3991
3992 switch (pname)
3993 {
3994 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3995 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3996 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3997 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3998 break;
3999
Martin Radeve5285d22017-07-14 16:23:53 +03004000 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4001 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4002 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4003 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4004 if (clientVersion < 3 || !context->getExtensions().multiview)
4005 {
4006 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4007 return false;
4008 }
4009 break;
4010
Geoff Langff5b2d52016-09-07 11:32:23 -04004011 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4012 if (clientVersion < 3 && !context->getExtensions().sRGB)
4013 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004014 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004015 return false;
4016 }
4017 break;
4018
4019 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4020 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4021 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4022 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4023 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4024 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4025 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4026 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4027 if (clientVersion < 3)
4028 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004029 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004030 return false;
4031 }
4032 break;
4033
4034 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004035 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004036 return false;
4037 }
4038
4039 // Determine if the attachment is a valid enum
4040 switch (attachment)
4041 {
4042 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004043 case GL_DEPTH:
4044 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004045 if (clientVersion < 3)
4046 {
Geoff Langfa125c92017-10-24 13:01:46 -04004047 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004048 return false;
4049 }
4050 break;
4051
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004052 case GL_DEPTH_STENCIL_ATTACHMENT:
4053 if (clientVersion < 3 && !context->isWebGL1())
4054 {
4055 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4056 return false;
4057 }
4058 break;
4059
Geoff Langfa125c92017-10-24 13:01:46 -04004060 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004061 case GL_DEPTH_ATTACHMENT:
4062 case GL_STENCIL_ATTACHMENT:
4063 break;
4064
4065 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004066 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4067 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004068 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4069 {
Geoff Langfa125c92017-10-24 13:01:46 -04004070 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004071 return false;
4072 }
4073 break;
4074 }
4075
4076 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4077 ASSERT(framebuffer);
4078
4079 if (framebuffer->id() == 0)
4080 {
4081 if (clientVersion < 3)
4082 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004083 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004084 return false;
4085 }
4086
4087 switch (attachment)
4088 {
4089 case GL_BACK:
4090 case GL_DEPTH:
4091 case GL_STENCIL:
4092 break;
4093
4094 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004095 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004096 return false;
4097 }
4098 }
4099 else
4100 {
4101 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4102 {
4103 // Valid attachment query
4104 }
4105 else
4106 {
4107 switch (attachment)
4108 {
4109 case GL_DEPTH_ATTACHMENT:
4110 case GL_STENCIL_ATTACHMENT:
4111 break;
4112
4113 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004114 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004115 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004116 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004117 return false;
4118 }
4119 break;
4120
4121 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004122 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004123 return false;
4124 }
4125 }
4126 }
4127
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004128 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004129 if (attachmentObject)
4130 {
4131 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4132 attachmentObject->type() == GL_TEXTURE ||
4133 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4134
4135 switch (pname)
4136 {
4137 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4138 if (attachmentObject->type() != GL_RENDERBUFFER &&
4139 attachmentObject->type() != GL_TEXTURE)
4140 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004141 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004142 return false;
4143 }
4144 break;
4145
4146 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4147 if (attachmentObject->type() != GL_TEXTURE)
4148 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004149 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004150 return false;
4151 }
4152 break;
4153
4154 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4155 if (attachmentObject->type() != GL_TEXTURE)
4156 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004157 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004158 return false;
4159 }
4160 break;
4161
4162 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4163 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4164 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004165 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004166 return false;
4167 }
4168 break;
4169
4170 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4171 if (attachmentObject->type() != GL_TEXTURE)
4172 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004173 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004174 return false;
4175 }
4176 break;
4177
4178 default:
4179 break;
4180 }
4181 }
4182 else
4183 {
4184 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4185 // is NONE, then querying any other pname will generate INVALID_ENUM.
4186
4187 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4188 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4189 // INVALID_OPERATION for all other pnames
4190
4191 switch (pname)
4192 {
4193 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4194 break;
4195
4196 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4197 if (clientVersion < 3)
4198 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004199 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004200 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004201 return false;
4202 }
4203 break;
4204
4205 default:
4206 if (clientVersion < 3)
4207 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004208 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004209 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004210 return false;
4211 }
4212 else
4213 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004214 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004215 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004216 return false;
4217 }
4218 }
4219 }
4220
Martin Radeve5285d22017-07-14 16:23:53 +03004221 if (numParams)
4222 {
4223 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4224 {
4225 // Only when the viewport offsets are queried we can have a varying number of output
4226 // parameters.
4227 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4228 *numParams = numViews * 2;
4229 }
4230 else
4231 {
4232 // For all other queries we can have only one output parameter.
4233 *numParams = 1;
4234 }
4235 }
4236
Geoff Langff5b2d52016-09-07 11:32:23 -04004237 return true;
4238}
4239
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004240bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004241 GLenum target,
4242 GLenum attachment,
4243 GLenum pname,
4244 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004245 GLsizei *length,
4246 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004247{
4248 if (!ValidateRobustEntryPoint(context, bufSize))
4249 {
4250 return false;
4251 }
4252
Brandon Jonesd1049182018-03-28 10:02:20 -07004253 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004254 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004255 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004256 {
4257 return false;
4258 }
4259
Brandon Jonesd1049182018-03-28 10:02:20 -07004260 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004261 {
4262 return false;
4263 }
4264
Brandon Jonesd1049182018-03-28 10:02:20 -07004265 SetRobustLengthParam(length, numParams);
4266
Geoff Langff5b2d52016-09-07 11:32:23 -04004267 return true;
4268}
4269
Jamie Madill5b772312018-03-08 20:28:32 -05004270bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004271 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004272 GLenum pname,
4273 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004274 GLsizei *length,
4275 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004276{
4277 if (!ValidateRobustEntryPoint(context, bufSize))
4278 {
4279 return false;
4280 }
4281
Brandon Jonesd1049182018-03-28 10:02:20 -07004282 GLsizei numParams = 0;
4283
4284 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004285 {
4286 return false;
4287 }
4288
Brandon Jonesd1049182018-03-28 10:02:20 -07004289 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004290 {
4291 return false;
4292 }
4293
Brandon Jonesd1049182018-03-28 10:02:20 -07004294 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004295 return true;
4296}
4297
Jamie Madill5b772312018-03-08 20:28:32 -05004298bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004299 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004300 GLenum pname,
4301 GLsizei bufSize,
4302 GLsizei *length,
4303 GLint64 *params)
4304{
Brandon Jonesd1049182018-03-28 10:02:20 -07004305 GLsizei numParams = 0;
4306
Geoff Langebebe1c2016-10-14 12:01:31 -04004307 if (!ValidateRobustEntryPoint(context, bufSize))
4308 {
4309 return false;
4310 }
4311
Brandon Jonesd1049182018-03-28 10:02:20 -07004312 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004313 {
4314 return false;
4315 }
4316
Brandon Jonesd1049182018-03-28 10:02:20 -07004317 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004318 {
4319 return false;
4320 }
4321
Brandon Jonesd1049182018-03-28 10:02:20 -07004322 SetRobustLengthParam(length, numParams);
4323
Geoff Langff5b2d52016-09-07 11:32:23 -04004324 return true;
4325}
4326
Jamie Madill5b772312018-03-08 20:28:32 -05004327bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004328{
4329 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004330 if (numParams)
4331 {
4332 *numParams = 1;
4333 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004334
4335 Program *programObject = GetValidProgram(context, program);
4336 if (!programObject)
4337 {
4338 return false;
4339 }
4340
4341 switch (pname)
4342 {
4343 case GL_DELETE_STATUS:
4344 case GL_LINK_STATUS:
4345 case GL_VALIDATE_STATUS:
4346 case GL_INFO_LOG_LENGTH:
4347 case GL_ATTACHED_SHADERS:
4348 case GL_ACTIVE_ATTRIBUTES:
4349 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4350 case GL_ACTIVE_UNIFORMS:
4351 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4352 break;
4353
4354 case GL_PROGRAM_BINARY_LENGTH:
4355 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4356 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004357 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4358 "requires GL_OES_get_program_binary or "
4359 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004360 return false;
4361 }
4362 break;
4363
4364 case GL_ACTIVE_UNIFORM_BLOCKS:
4365 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4366 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4367 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4368 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4369 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4370 if (context->getClientMajorVersion() < 3)
4371 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004372 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004373 return false;
4374 }
4375 break;
4376
Yunchao He61afff12017-03-14 15:34:03 +08004377 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004378 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004379 if (context->getClientVersion() < Version(3, 1))
4380 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004381 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004382 return false;
4383 }
4384 break;
4385
Jiawei Shao6ae51612018-02-23 14:03:25 +08004386 case GL_COMPUTE_WORK_GROUP_SIZE:
4387 if (context->getClientVersion() < Version(3, 1))
4388 {
4389 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4390 return false;
4391 }
4392
4393 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4394 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4395 // program which has not been linked successfully, or which does not contain objects to
4396 // form a compute shader.
4397 if (!programObject->isLinked())
4398 {
4399 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4400 return false;
4401 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004402 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004403 {
4404 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4405 return false;
4406 }
4407 break;
4408
Jiawei Shao447bfac2018-03-14 14:23:40 +08004409 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4410 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4411 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4412 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4413 if (!context->getExtensions().geometryShader)
4414 {
4415 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4416 return false;
4417 }
4418
4419 // [EXT_geometry_shader] Chapter 7.12
4420 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4421 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4422 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4423 // successfully, or which does not contain objects to form a geometry shader.
4424 if (!programObject->isLinked())
4425 {
4426 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4427 return false;
4428 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004429 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004430 {
4431 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4432 return false;
4433 }
4434 break;
4435
Geoff Langff5b2d52016-09-07 11:32:23 -04004436 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004437 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004438 return false;
4439 }
4440
4441 return true;
4442}
4443
4444bool ValidateGetProgramivRobustANGLE(Context *context,
4445 GLuint program,
4446 GLenum pname,
4447 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004448 GLsizei *length,
4449 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004450{
4451 if (!ValidateRobustEntryPoint(context, bufSize))
4452 {
4453 return false;
4454 }
4455
Brandon Jonesd1049182018-03-28 10:02:20 -07004456 GLsizei numParams = 0;
4457
4458 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004459 {
4460 return false;
4461 }
4462
Brandon Jonesd1049182018-03-28 10:02:20 -07004463 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004464 {
4465 return false;
4466 }
4467
Brandon Jonesd1049182018-03-28 10:02:20 -07004468 SetRobustLengthParam(length, numParams);
4469
Geoff Langff5b2d52016-09-07 11:32:23 -04004470 return true;
4471}
4472
Geoff Lang740d9022016-10-07 11:20:52 -04004473bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4474 GLenum target,
4475 GLenum pname,
4476 GLsizei bufSize,
4477 GLsizei *length,
4478 GLint *params)
4479{
4480 if (!ValidateRobustEntryPoint(context, bufSize))
4481 {
4482 return false;
4483 }
4484
Brandon Jonesd1049182018-03-28 10:02:20 -07004485 GLsizei numParams = 0;
4486
4487 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004488 {
4489 return false;
4490 }
4491
Brandon Jonesd1049182018-03-28 10:02:20 -07004492 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004493 {
4494 return false;
4495 }
4496
Brandon Jonesd1049182018-03-28 10:02:20 -07004497 SetRobustLengthParam(length, numParams);
4498
Geoff Lang740d9022016-10-07 11:20:52 -04004499 return true;
4500}
4501
Geoff Langd7d0ed32016-10-07 11:33:51 -04004502bool ValidateGetShaderivRobustANGLE(Context *context,
4503 GLuint shader,
4504 GLenum pname,
4505 GLsizei bufSize,
4506 GLsizei *length,
4507 GLint *params)
4508{
4509 if (!ValidateRobustEntryPoint(context, bufSize))
4510 {
4511 return false;
4512 }
4513
Brandon Jonesd1049182018-03-28 10:02:20 -07004514 GLsizei numParams = 0;
4515
4516 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004517 {
4518 return false;
4519 }
4520
Brandon Jonesd1049182018-03-28 10:02:20 -07004521 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004522 {
4523 return false;
4524 }
4525
Brandon Jonesd1049182018-03-28 10:02:20 -07004526 SetRobustLengthParam(length, numParams);
4527
Geoff Langd7d0ed32016-10-07 11:33:51 -04004528 return true;
4529}
4530
Geoff Langc1984ed2016-10-07 12:41:00 -04004531bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004532 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004533 GLenum pname,
4534 GLsizei bufSize,
4535 GLsizei *length,
4536 GLfloat *params)
4537{
4538 if (!ValidateRobustEntryPoint(context, bufSize))
4539 {
4540 return false;
4541 }
4542
Brandon Jonesd1049182018-03-28 10:02:20 -07004543 GLsizei numParams = 0;
4544
4545 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004546 {
4547 return false;
4548 }
4549
Brandon Jonesd1049182018-03-28 10:02:20 -07004550 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004551 {
4552 return false;
4553 }
4554
Brandon Jonesd1049182018-03-28 10:02:20 -07004555 SetRobustLengthParam(length, numParams);
4556
Geoff Langc1984ed2016-10-07 12:41:00 -04004557 return true;
4558}
4559
Geoff Langc1984ed2016-10-07 12:41:00 -04004560bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004561 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004562 GLenum pname,
4563 GLsizei bufSize,
4564 GLsizei *length,
4565 GLint *params)
4566{
Brandon Jonesd1049182018-03-28 10:02:20 -07004567
Geoff Langc1984ed2016-10-07 12:41:00 -04004568 if (!ValidateRobustEntryPoint(context, bufSize))
4569 {
4570 return false;
4571 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004572 GLsizei numParams = 0;
4573 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004574 {
4575 return false;
4576 }
4577
Brandon Jonesd1049182018-03-28 10:02:20 -07004578 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004579 {
4580 return false;
4581 }
4582
Brandon Jonesd1049182018-03-28 10:02:20 -07004583 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004584 return true;
4585}
4586
Geoff Langc1984ed2016-10-07 12:41:00 -04004587bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004588 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004589 GLenum pname,
4590 GLsizei bufSize,
4591 const GLfloat *params)
4592{
4593 if (!ValidateRobustEntryPoint(context, bufSize))
4594 {
4595 return false;
4596 }
4597
4598 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4599}
4600
Geoff Langc1984ed2016-10-07 12:41:00 -04004601bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004602 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004603 GLenum pname,
4604 GLsizei bufSize,
4605 const GLint *params)
4606{
4607 if (!ValidateRobustEntryPoint(context, bufSize))
4608 {
4609 return false;
4610 }
4611
4612 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4613}
4614
Geoff Langc1984ed2016-10-07 12:41:00 -04004615bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4616 GLuint sampler,
4617 GLenum pname,
4618 GLuint bufSize,
4619 GLsizei *length,
4620 GLfloat *params)
4621{
4622 if (!ValidateRobustEntryPoint(context, bufSize))
4623 {
4624 return false;
4625 }
4626
Brandon Jonesd1049182018-03-28 10:02:20 -07004627 GLsizei numParams = 0;
4628
4629 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004630 {
4631 return false;
4632 }
4633
Brandon Jonesd1049182018-03-28 10:02:20 -07004634 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004635 {
4636 return false;
4637 }
4638
Brandon Jonesd1049182018-03-28 10:02:20 -07004639 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004640 return true;
4641}
4642
Geoff Langc1984ed2016-10-07 12:41:00 -04004643bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4644 GLuint sampler,
4645 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004646 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004647 GLsizei *length,
4648 GLint *params)
4649{
4650 if (!ValidateRobustEntryPoint(context, bufSize))
4651 {
4652 return false;
4653 }
4654
Brandon Jonesd1049182018-03-28 10:02:20 -07004655 GLsizei numParams = 0;
4656
4657 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004658 {
4659 return false;
4660 }
4661
Brandon Jonesd1049182018-03-28 10:02:20 -07004662 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004663 {
4664 return false;
4665 }
4666
Brandon Jonesd1049182018-03-28 10:02:20 -07004667 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004668 return true;
4669}
4670
Geoff Langc1984ed2016-10-07 12:41:00 -04004671bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4672 GLuint sampler,
4673 GLenum pname,
4674 GLsizei bufSize,
4675 const GLfloat *params)
4676{
4677 if (!ValidateRobustEntryPoint(context, bufSize))
4678 {
4679 return false;
4680 }
4681
4682 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4683}
4684
Geoff Langc1984ed2016-10-07 12:41:00 -04004685bool ValidateSamplerParameterivRobustANGLE(Context *context,
4686 GLuint sampler,
4687 GLenum pname,
4688 GLsizei bufSize,
4689 const GLint *params)
4690{
4691 if (!ValidateRobustEntryPoint(context, bufSize))
4692 {
4693 return false;
4694 }
4695
4696 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4697}
4698
Geoff Lang0b031062016-10-13 14:30:04 -04004699bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4700 GLuint index,
4701 GLenum pname,
4702 GLsizei bufSize,
4703 GLsizei *length,
4704 GLfloat *params)
4705{
4706 if (!ValidateRobustEntryPoint(context, bufSize))
4707 {
4708 return false;
4709 }
4710
Brandon Jonesd1049182018-03-28 10:02:20 -07004711 GLsizei writeLength = 0;
4712
4713 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004714 {
4715 return false;
4716 }
4717
Brandon Jonesd1049182018-03-28 10:02:20 -07004718 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004719 {
4720 return false;
4721 }
4722
Brandon Jonesd1049182018-03-28 10:02:20 -07004723 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004724 return true;
4725}
4726
Geoff Lang0b031062016-10-13 14:30:04 -04004727bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4728 GLuint index,
4729 GLenum pname,
4730 GLsizei bufSize,
4731 GLsizei *length,
4732 GLint *params)
4733{
4734 if (!ValidateRobustEntryPoint(context, bufSize))
4735 {
4736 return false;
4737 }
4738
Brandon Jonesd1049182018-03-28 10:02:20 -07004739 GLsizei writeLength = 0;
4740
4741 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004742 {
4743 return false;
4744 }
4745
Brandon Jonesd1049182018-03-28 10:02:20 -07004746 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004747 {
4748 return false;
4749 }
4750
Brandon Jonesd1049182018-03-28 10:02:20 -07004751 SetRobustLengthParam(length, writeLength);
4752
Geoff Lang0b031062016-10-13 14:30:04 -04004753 return true;
4754}
4755
Geoff Lang0b031062016-10-13 14:30:04 -04004756bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4757 GLuint index,
4758 GLenum pname,
4759 GLsizei bufSize,
4760 GLsizei *length,
4761 void **pointer)
4762{
4763 if (!ValidateRobustEntryPoint(context, bufSize))
4764 {
4765 return false;
4766 }
4767
Brandon Jonesd1049182018-03-28 10:02:20 -07004768 GLsizei writeLength = 0;
4769
4770 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004771 {
4772 return false;
4773 }
4774
Brandon Jonesd1049182018-03-28 10:02:20 -07004775 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004776 {
4777 return false;
4778 }
4779
Brandon Jonesd1049182018-03-28 10:02:20 -07004780 SetRobustLengthParam(length, writeLength);
4781
Geoff Lang0b031062016-10-13 14:30:04 -04004782 return true;
4783}
4784
Geoff Lang0b031062016-10-13 14:30:04 -04004785bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4786 GLuint index,
4787 GLenum pname,
4788 GLsizei bufSize,
4789 GLsizei *length,
4790 GLint *params)
4791{
4792 if (!ValidateRobustEntryPoint(context, bufSize))
4793 {
4794 return false;
4795 }
4796
Brandon Jonesd1049182018-03-28 10:02:20 -07004797 GLsizei writeLength = 0;
4798
4799 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004800 {
4801 return false;
4802 }
4803
Brandon Jonesd1049182018-03-28 10:02:20 -07004804 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004805 {
4806 return false;
4807 }
4808
Brandon Jonesd1049182018-03-28 10:02:20 -07004809 SetRobustLengthParam(length, writeLength);
4810
Geoff Lang0b031062016-10-13 14:30:04 -04004811 return true;
4812}
4813
Geoff Lang0b031062016-10-13 14:30:04 -04004814bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4815 GLuint index,
4816 GLenum pname,
4817 GLsizei bufSize,
4818 GLsizei *length,
4819 GLuint *params)
4820{
4821 if (!ValidateRobustEntryPoint(context, bufSize))
4822 {
4823 return false;
4824 }
4825
Brandon Jonesd1049182018-03-28 10:02:20 -07004826 GLsizei writeLength = 0;
4827
4828 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004829 {
4830 return false;
4831 }
4832
Brandon Jonesd1049182018-03-28 10:02:20 -07004833 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004834 {
4835 return false;
4836 }
4837
Brandon Jonesd1049182018-03-28 10:02:20 -07004838 SetRobustLengthParam(length, writeLength);
4839
Geoff Lang0b031062016-10-13 14:30:04 -04004840 return true;
4841}
4842
Geoff Lang6899b872016-10-14 11:30:13 -04004843bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4844 GLuint program,
4845 GLuint uniformBlockIndex,
4846 GLenum pname,
4847 GLsizei bufSize,
4848 GLsizei *length,
4849 GLint *params)
4850{
4851 if (!ValidateRobustEntryPoint(context, bufSize))
4852 {
4853 return false;
4854 }
4855
Brandon Jonesd1049182018-03-28 10:02:20 -07004856 GLsizei writeLength = 0;
4857
4858 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
4859 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004860 {
4861 return false;
4862 }
4863
Brandon Jonesd1049182018-03-28 10:02:20 -07004864 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004865 {
4866 return false;
4867 }
4868
Brandon Jonesd1049182018-03-28 10:02:20 -07004869 SetRobustLengthParam(length, writeLength);
4870
Geoff Lang6899b872016-10-14 11:30:13 -04004871 return true;
4872}
4873
Geoff Lang0a9661f2016-10-20 10:59:20 -07004874bool ValidateGetInternalFormativRobustANGLE(Context *context,
4875 GLenum target,
4876 GLenum internalformat,
4877 GLenum pname,
4878 GLsizei bufSize,
4879 GLsizei *length,
4880 GLint *params)
4881{
4882 if (!ValidateRobustEntryPoint(context, bufSize))
4883 {
4884 return false;
4885 }
4886
Brandon Jonesd1049182018-03-28 10:02:20 -07004887 GLsizei numParams = 0;
4888
4889 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4890 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07004891 {
4892 return false;
4893 }
4894
Brandon Jonesd1049182018-03-28 10:02:20 -07004895 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07004896 {
4897 return false;
4898 }
4899
Brandon Jonesd1049182018-03-28 10:02:20 -07004900 SetRobustLengthParam(length, numParams);
4901
Geoff Lang0a9661f2016-10-20 10:59:20 -07004902 return true;
4903}
4904
Jamie Madill5b772312018-03-08 20:28:32 -05004905bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08004906 GLuint attribIndex,
4907 GLint size,
4908 GLenum type,
4909 GLboolean pureInteger)
4910{
4911 const Caps &caps = context->getCaps();
4912 if (attribIndex >= caps.maxVertexAttributes)
4913 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004914 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004915 return false;
4916 }
4917
4918 if (size < 1 || size > 4)
4919 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004920 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004921 return false;
Shao80957d92017-02-20 21:25:59 +08004922 }
4923
4924 switch (type)
4925 {
4926 case GL_BYTE:
4927 case GL_UNSIGNED_BYTE:
4928 case GL_SHORT:
4929 case GL_UNSIGNED_SHORT:
4930 break;
4931
4932 case GL_INT:
4933 case GL_UNSIGNED_INT:
4934 if (context->getClientMajorVersion() < 3)
4935 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004936 context->handleError(InvalidEnum()
4937 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004938 return false;
4939 }
4940 break;
4941
4942 case GL_FIXED:
4943 case GL_FLOAT:
4944 if (pureInteger)
4945 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004946 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004947 return false;
4948 }
4949 break;
4950
4951 case GL_HALF_FLOAT:
4952 if (context->getClientMajorVersion() < 3)
4953 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004954 context->handleError(InvalidEnum()
4955 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004956 return false;
4957 }
4958 if (pureInteger)
4959 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004960 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004961 return false;
4962 }
4963 break;
4964
4965 case GL_INT_2_10_10_10_REV:
4966 case GL_UNSIGNED_INT_2_10_10_10_REV:
4967 if (context->getClientMajorVersion() < 3)
4968 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004969 context->handleError(InvalidEnum()
4970 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004971 return false;
4972 }
4973 if (pureInteger)
4974 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004975 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004976 return false;
4977 }
4978 if (size != 4)
4979 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004980 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4981 "UNSIGNED_INT_2_10_10_10_REV and "
4982 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004983 return false;
4984 }
4985 break;
4986
4987 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004988 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004989 return false;
4990 }
4991
4992 return true;
4993}
4994
Geoff Lang76e65652017-03-27 14:58:02 -04004995// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4996// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4997// specified clear value and the type of a buffer that is being cleared generates an
4998// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05004999bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005000 GLint drawbuffer,
5001 const GLenum *validComponentTypes,
5002 size_t validComponentTypeCount)
5003{
5004 const FramebufferAttachment *attachment =
5005 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5006 if (attachment)
5007 {
5008 GLenum componentType = attachment->getFormat().info->componentType;
5009 const GLenum *end = validComponentTypes + validComponentTypeCount;
5010 if (std::find(validComponentTypes, end, componentType) == end)
5011 {
5012 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005013 InvalidOperation()
5014 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005015 return false;
5016 }
5017 }
5018
5019 return true;
5020}
5021
Jamie Madill5b772312018-03-08 20:28:32 -05005022bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005023{
5024 if (!ValidateRobustEntryPoint(context, dataSize))
5025 {
5026 return false;
5027 }
5028
Corentin Wallez336129f2017-10-17 15:55:40 -04005029 gl::Buffer *pixelUnpackBuffer =
5030 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005031 if (pixelUnpackBuffer == nullptr)
5032 {
5033 if (dataSize < imageSize)
5034 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005035 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005036 }
5037 }
5038 return true;
5039}
5040
Jamie Madill5b772312018-03-08 20:28:32 -05005041bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005042 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005043 GLenum pname,
5044 bool pointerVersion,
5045 GLsizei *numParams)
5046{
5047 if (numParams)
5048 {
5049 *numParams = 0;
5050 }
5051
Corentin Walleze4477002017-12-01 14:39:58 -05005052 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005053 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005054 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005055 return false;
5056 }
5057
5058 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5059 if (!buffer)
5060 {
5061 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005062 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005063 return false;
5064 }
5065
5066 const Extensions &extensions = context->getExtensions();
5067
5068 switch (pname)
5069 {
5070 case GL_BUFFER_USAGE:
5071 case GL_BUFFER_SIZE:
5072 break;
5073
5074 case GL_BUFFER_ACCESS_OES:
5075 if (!extensions.mapBuffer)
5076 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005077 context->handleError(InvalidEnum()
5078 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005079 return false;
5080 }
5081 break;
5082
5083 case GL_BUFFER_MAPPED:
5084 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5085 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5086 !extensions.mapBufferRange)
5087 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005088 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5089 "GL_OES_mapbuffer or "
5090 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005091 return false;
5092 }
5093 break;
5094
5095 case GL_BUFFER_MAP_POINTER:
5096 if (!pointerVersion)
5097 {
5098 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005099 InvalidEnum()
5100 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005101 return false;
5102 }
5103 break;
5104
5105 case GL_BUFFER_ACCESS_FLAGS:
5106 case GL_BUFFER_MAP_OFFSET:
5107 case GL_BUFFER_MAP_LENGTH:
5108 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5109 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005110 context->handleError(InvalidEnum()
5111 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005112 return false;
5113 }
5114 break;
5115
5116 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005117 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005118 return false;
5119 }
5120
5121 // All buffer parameter queries return one value.
5122 if (numParams)
5123 {
5124 *numParams = 1;
5125 }
5126
5127 return true;
5128}
5129
5130bool ValidateGetRenderbufferParameterivBase(Context *context,
5131 GLenum target,
5132 GLenum pname,
5133 GLsizei *length)
5134{
5135 if (length)
5136 {
5137 *length = 0;
5138 }
5139
5140 if (target != GL_RENDERBUFFER)
5141 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005142 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005143 return false;
5144 }
5145
5146 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5147 if (renderbuffer == nullptr)
5148 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005149 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005150 return false;
5151 }
5152
5153 switch (pname)
5154 {
5155 case GL_RENDERBUFFER_WIDTH:
5156 case GL_RENDERBUFFER_HEIGHT:
5157 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5158 case GL_RENDERBUFFER_RED_SIZE:
5159 case GL_RENDERBUFFER_GREEN_SIZE:
5160 case GL_RENDERBUFFER_BLUE_SIZE:
5161 case GL_RENDERBUFFER_ALPHA_SIZE:
5162 case GL_RENDERBUFFER_DEPTH_SIZE:
5163 case GL_RENDERBUFFER_STENCIL_SIZE:
5164 break;
5165
5166 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5167 if (!context->getExtensions().framebufferMultisample)
5168 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005169 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005170 return false;
5171 }
5172 break;
5173
5174 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005175 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005176 return false;
5177 }
5178
5179 if (length)
5180 {
5181 *length = 1;
5182 }
5183 return true;
5184}
5185
5186bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5187{
5188 if (length)
5189 {
5190 *length = 0;
5191 }
5192
5193 if (GetValidShader(context, shader) == nullptr)
5194 {
5195 return false;
5196 }
5197
5198 switch (pname)
5199 {
5200 case GL_SHADER_TYPE:
5201 case GL_DELETE_STATUS:
5202 case GL_COMPILE_STATUS:
5203 case GL_INFO_LOG_LENGTH:
5204 case GL_SHADER_SOURCE_LENGTH:
5205 break;
5206
5207 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5208 if (!context->getExtensions().translatedShaderSource)
5209 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005210 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005211 return false;
5212 }
5213 break;
5214
5215 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005216 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005217 return false;
5218 }
5219
5220 if (length)
5221 {
5222 *length = 1;
5223 }
5224 return true;
5225}
5226
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005227bool ValidateGetTexParameterBase(Context *context,
5228 TextureType target,
5229 GLenum pname,
5230 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005231{
5232 if (length)
5233 {
5234 *length = 0;
5235 }
5236
5237 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5238 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005239 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005240 return false;
5241 }
5242
5243 if (context->getTargetTexture(target) == nullptr)
5244 {
5245 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005246 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005247 return false;
5248 }
5249
5250 switch (pname)
5251 {
5252 case GL_TEXTURE_MAG_FILTER:
5253 case GL_TEXTURE_MIN_FILTER:
5254 case GL_TEXTURE_WRAP_S:
5255 case GL_TEXTURE_WRAP_T:
5256 break;
5257
5258 case GL_TEXTURE_USAGE_ANGLE:
5259 if (!context->getExtensions().textureUsage)
5260 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005261 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005262 return false;
5263 }
5264 break;
5265
5266 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005267 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005268 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005269 return false;
5270 }
5271 break;
5272
5273 case GL_TEXTURE_IMMUTABLE_FORMAT:
5274 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5275 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005276 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005277 return false;
5278 }
5279 break;
5280
5281 case GL_TEXTURE_WRAP_R:
5282 case GL_TEXTURE_IMMUTABLE_LEVELS:
5283 case GL_TEXTURE_SWIZZLE_R:
5284 case GL_TEXTURE_SWIZZLE_G:
5285 case GL_TEXTURE_SWIZZLE_B:
5286 case GL_TEXTURE_SWIZZLE_A:
5287 case GL_TEXTURE_BASE_LEVEL:
5288 case GL_TEXTURE_MAX_LEVEL:
5289 case GL_TEXTURE_MIN_LOD:
5290 case GL_TEXTURE_MAX_LOD:
5291 case GL_TEXTURE_COMPARE_MODE:
5292 case GL_TEXTURE_COMPARE_FUNC:
5293 if (context->getClientMajorVersion() < 3)
5294 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005295 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005296 return false;
5297 }
5298 break;
5299
5300 case GL_TEXTURE_SRGB_DECODE_EXT:
5301 if (!context->getExtensions().textureSRGBDecode)
5302 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005303 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005304 return false;
5305 }
5306 break;
5307
Yunchao Hebacaa712018-01-30 14:01:39 +08005308 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5309 if (context->getClientVersion() < Version(3, 1))
5310 {
5311 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5312 return false;
5313 }
5314 break;
5315
Jamie Madillbe849e42017-05-02 15:49:00 -04005316 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005317 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005318 return false;
5319 }
5320
5321 if (length)
5322 {
5323 *length = 1;
5324 }
5325 return true;
5326}
5327
5328bool ValidateGetVertexAttribBase(Context *context,
5329 GLuint index,
5330 GLenum pname,
5331 GLsizei *length,
5332 bool pointer,
5333 bool pureIntegerEntryPoint)
5334{
5335 if (length)
5336 {
5337 *length = 0;
5338 }
5339
5340 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5341 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005342 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005343 return false;
5344 }
5345
5346 if (index >= context->getCaps().maxVertexAttributes)
5347 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005348 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005349 return false;
5350 }
5351
5352 if (pointer)
5353 {
5354 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5355 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005356 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005357 return false;
5358 }
5359 }
5360 else
5361 {
5362 switch (pname)
5363 {
5364 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5365 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5366 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5367 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5368 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5369 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5370 case GL_CURRENT_VERTEX_ATTRIB:
5371 break;
5372
5373 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5374 static_assert(
5375 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5376 "ANGLE extension enums not equal to GL enums.");
5377 if (context->getClientMajorVersion() < 3 &&
5378 !context->getExtensions().instancedArrays)
5379 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005380 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5381 "requires OpenGL ES 3.0 or "
5382 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005383 return false;
5384 }
5385 break;
5386
5387 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5388 if (context->getClientMajorVersion() < 3)
5389 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005390 context->handleError(
5391 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005392 return false;
5393 }
5394 break;
5395
5396 case GL_VERTEX_ATTRIB_BINDING:
5397 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5398 if (context->getClientVersion() < ES_3_1)
5399 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005400 context->handleError(InvalidEnum()
5401 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005402 return false;
5403 }
5404 break;
5405
5406 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005407 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005408 return false;
5409 }
5410 }
5411
5412 if (length)
5413 {
5414 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5415 {
5416 *length = 4;
5417 }
5418 else
5419 {
5420 *length = 1;
5421 }
5422 }
5423
5424 return true;
5425}
5426
Jamie Madill4928b7c2017-06-20 12:57:39 -04005427bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005428 GLint x,
5429 GLint y,
5430 GLsizei width,
5431 GLsizei height,
5432 GLenum format,
5433 GLenum type,
5434 GLsizei bufSize,
5435 GLsizei *length,
5436 GLsizei *columns,
5437 GLsizei *rows,
5438 void *pixels)
5439{
5440 if (length != nullptr)
5441 {
5442 *length = 0;
5443 }
5444 if (rows != nullptr)
5445 {
5446 *rows = 0;
5447 }
5448 if (columns != nullptr)
5449 {
5450 *columns = 0;
5451 }
5452
5453 if (width < 0 || height < 0)
5454 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005455 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005456 return false;
5457 }
5458
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005459 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005460
Jamie Madille98b1b52018-03-08 09:47:23 -05005461 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madillbe849e42017-05-02 15:49:00 -04005462 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005463 return false;
5464 }
5465
Jamie Madille98b1b52018-03-08 09:47:23 -05005466 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005467 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005468 return false;
5469 }
5470
Jamie Madill690c8eb2018-03-12 15:20:03 -04005471 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005472 ASSERT(framebuffer);
5473
5474 if (framebuffer->getReadBufferState() == GL_NONE)
5475 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005476 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005477 return false;
5478 }
5479
5480 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5481 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5482 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5483 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5484 // situation is an application error that would lead to a crash in ANGLE.
5485 if (readBuffer == nullptr)
5486 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005487 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005488 return false;
5489 }
5490
Martin Radev28031682017-07-28 14:47:56 +03005491 // ANGLE_multiview, Revision 1:
5492 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5493 // current read framebuffer is not NONE.
5494 if (readBuffer->getMultiviewLayout() != GL_NONE)
5495 {
5496 context->handleError(InvalidFramebufferOperation()
5497 << "Attempting to read from a multi-view framebuffer.");
5498 return false;
5499 }
5500
Geoff Lang280ba992017-04-18 16:30:58 -04005501 if (context->getExtensions().webglCompatibility)
5502 {
5503 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5504 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5505 // and type before validating the combination of format and type. However, the
5506 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5507 // verifies that GL_INVALID_OPERATION is generated.
5508 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5509 // dEQP/WebGL.
5510 if (!ValidReadPixelsFormatEnum(context, format))
5511 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005512 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005513 return false;
5514 }
5515
5516 if (!ValidReadPixelsTypeEnum(context, type))
5517 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005518 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005519 return false;
5520 }
5521 }
5522
Jamie Madill690c8eb2018-03-12 15:20:03 -04005523 GLenum currentFormat = GL_NONE;
5524 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5525
5526 GLenum currentType = GL_NONE;
5527 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5528
Jamie Madillbe849e42017-05-02 15:49:00 -04005529 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5530
5531 bool validFormatTypeCombination =
5532 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5533
5534 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5535 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005536 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005537 return false;
5538 }
5539
5540 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005541 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005542 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5543 {
5544 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005545 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005546 return false;
5547 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005548 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5549 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5550 {
5551 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5552 return false;
5553 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005554
5555 // .. the data would be packed to the buffer object such that the memory writes required
5556 // would exceed the data store size.
5557 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5558 const gl::Extents size(width, height, 1);
5559 const auto &pack = context->getGLState().getPackState();
5560
5561 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5562 if (endByteOrErr.isError())
5563 {
5564 context->handleError(endByteOrErr.getError());
5565 return false;
5566 }
5567
5568 size_t endByte = endByteOrErr.getResult();
5569 if (bufSize >= 0)
5570 {
5571 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5572 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005573 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005574 return false;
5575 }
5576 }
5577
5578 if (pixelPackBuffer != nullptr)
5579 {
5580 CheckedNumeric<size_t> checkedEndByte(endByte);
5581 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5582 checkedEndByte += checkedOffset;
5583
5584 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5585 {
5586 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005587 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005588 return false;
5589 }
5590 }
5591
5592 if (pixelPackBuffer == nullptr && length != nullptr)
5593 {
5594 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5595 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005596 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005597 return false;
5598 }
5599
5600 *length = static_cast<GLsizei>(endByte);
5601 }
5602
Geoff Langa953b522018-02-21 16:56:23 -05005603 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005604 angle::CheckedNumeric<int> clippedExtent(length);
5605 if (start < 0)
5606 {
5607 // "subtract" the area that is less than 0
5608 clippedExtent += start;
5609 }
5610
Geoff Langa953b522018-02-21 16:56:23 -05005611 angle::CheckedNumeric<int> readExtent = start;
5612 readExtent += length;
5613 if (!readExtent.IsValid())
5614 {
5615 return false;
5616 }
5617
5618 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005619 {
5620 // Subtract the region to the right of the read buffer
5621 clippedExtent -= (readExtent - bufferSize);
5622 }
5623
5624 if (!clippedExtent.IsValid())
5625 {
Geoff Langa953b522018-02-21 16:56:23 -05005626 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005627 }
5628
Geoff Langa953b522018-02-21 16:56:23 -05005629 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5630 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005631 };
5632
Geoff Langa953b522018-02-21 16:56:23 -05005633 GLsizei writtenColumns = 0;
5634 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5635 {
5636 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5637 return false;
5638 }
5639
5640 GLsizei writtenRows = 0;
5641 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5642 {
5643 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5644 return false;
5645 }
5646
Jamie Madillbe849e42017-05-02 15:49:00 -04005647 if (columns != nullptr)
5648 {
Geoff Langa953b522018-02-21 16:56:23 -05005649 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005650 }
5651
5652 if (rows != nullptr)
5653 {
Geoff Langa953b522018-02-21 16:56:23 -05005654 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005655 }
5656
5657 return true;
5658}
5659
5660template <typename ParamType>
5661bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005662 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005663 GLenum pname,
5664 GLsizei bufSize,
5665 const ParamType *params)
5666{
5667 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5668 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005669 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005670 return false;
5671 }
5672
5673 if (context->getTargetTexture(target) == nullptr)
5674 {
5675 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005676 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005677 return false;
5678 }
5679
5680 const GLsizei minBufSize = 1;
5681 if (bufSize >= 0 && bufSize < minBufSize)
5682 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005683 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005684 return false;
5685 }
5686
5687 switch (pname)
5688 {
5689 case GL_TEXTURE_WRAP_R:
5690 case GL_TEXTURE_SWIZZLE_R:
5691 case GL_TEXTURE_SWIZZLE_G:
5692 case GL_TEXTURE_SWIZZLE_B:
5693 case GL_TEXTURE_SWIZZLE_A:
5694 case GL_TEXTURE_BASE_LEVEL:
5695 case GL_TEXTURE_MAX_LEVEL:
5696 case GL_TEXTURE_COMPARE_MODE:
5697 case GL_TEXTURE_COMPARE_FUNC:
5698 case GL_TEXTURE_MIN_LOD:
5699 case GL_TEXTURE_MAX_LOD:
5700 if (context->getClientMajorVersion() < 3)
5701 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005702 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005703 return false;
5704 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005705 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005706 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005707 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5708 "available without "
5709 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005710 return false;
5711 }
5712 break;
5713
5714 default:
5715 break;
5716 }
5717
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005718 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005719 {
5720 switch (pname)
5721 {
5722 case GL_TEXTURE_MIN_FILTER:
5723 case GL_TEXTURE_MAG_FILTER:
5724 case GL_TEXTURE_WRAP_S:
5725 case GL_TEXTURE_WRAP_T:
5726 case GL_TEXTURE_WRAP_R:
5727 case GL_TEXTURE_MIN_LOD:
5728 case GL_TEXTURE_MAX_LOD:
5729 case GL_TEXTURE_COMPARE_MODE:
5730 case GL_TEXTURE_COMPARE_FUNC:
5731 context->handleError(InvalidEnum()
5732 << "Invalid parameter for 2D multisampled textures.");
5733 return false;
5734 }
5735 }
5736
Jamie Madillbe849e42017-05-02 15:49:00 -04005737 switch (pname)
5738 {
5739 case GL_TEXTURE_WRAP_S:
5740 case GL_TEXTURE_WRAP_T:
5741 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005742 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005743 bool restrictedWrapModes =
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005744 target == TextureType::External || target == TextureType::Rectangle;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005745 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5746 {
5747 return false;
5748 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005749 }
5750 break;
5751
5752 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005753 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005754 bool restrictedMinFilter =
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005755 target == TextureType::External || target == TextureType::Rectangle;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005756 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5757 {
5758 return false;
5759 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005760 }
5761 break;
5762
5763 case GL_TEXTURE_MAG_FILTER:
5764 if (!ValidateTextureMagFilterValue(context, params))
5765 {
5766 return false;
5767 }
5768 break;
5769
5770 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005771 if (!context->getExtensions().textureUsage)
5772 {
5773 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5774 return false;
5775 }
5776
Jamie Madillbe849e42017-05-02 15:49:00 -04005777 switch (ConvertToGLenum(params[0]))
5778 {
5779 case GL_NONE:
5780 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5781 break;
5782
5783 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005784 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005785 return false;
5786 }
5787 break;
5788
5789 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Jamie Madillbe849e42017-05-02 15:49:00 -04005790 {
Luc Ferron1b1a8642018-01-23 15:12:01 -05005791 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5792 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5793 {
5794 return false;
5795 }
5796 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
Jamie Madillbe849e42017-05-02 15:49:00 -04005797 }
5798 break;
5799
5800 case GL_TEXTURE_MIN_LOD:
5801 case GL_TEXTURE_MAX_LOD:
5802 // any value is permissible
5803 break;
5804
5805 case GL_TEXTURE_COMPARE_MODE:
5806 if (!ValidateTextureCompareModeValue(context, params))
5807 {
5808 return false;
5809 }
5810 break;
5811
5812 case GL_TEXTURE_COMPARE_FUNC:
5813 if (!ValidateTextureCompareFuncValue(context, params))
5814 {
5815 return false;
5816 }
5817 break;
5818
5819 case GL_TEXTURE_SWIZZLE_R:
5820 case GL_TEXTURE_SWIZZLE_G:
5821 case GL_TEXTURE_SWIZZLE_B:
5822 case GL_TEXTURE_SWIZZLE_A:
5823 switch (ConvertToGLenum(params[0]))
5824 {
5825 case GL_RED:
5826 case GL_GREEN:
5827 case GL_BLUE:
5828 case GL_ALPHA:
5829 case GL_ZERO:
5830 case GL_ONE:
5831 break;
5832
5833 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005834 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005835 return false;
5836 }
5837 break;
5838
5839 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005840 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005841 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005842 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005843 return false;
5844 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005845 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005846 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005847 context->handleError(InvalidOperation()
5848 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005849 return false;
5850 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005851 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005852 {
5853 context->handleError(InvalidOperation()
5854 << "Base level must be 0 for multisampled textures.");
5855 return false;
5856 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005857 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005858 {
5859 context->handleError(InvalidOperation()
5860 << "Base level must be 0 for rectangle textures.");
5861 return false;
5862 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005863 break;
5864
5865 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005866 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005867 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005868 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005869 return false;
5870 }
5871 break;
5872
5873 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5874 if (context->getClientVersion() < Version(3, 1))
5875 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005876 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005877 return false;
5878 }
5879 switch (ConvertToGLenum(params[0]))
5880 {
5881 case GL_DEPTH_COMPONENT:
5882 case GL_STENCIL_INDEX:
5883 break;
5884
5885 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005886 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005887 return false;
5888 }
5889 break;
5890
5891 case GL_TEXTURE_SRGB_DECODE_EXT:
5892 if (!ValidateTextureSRGBDecodeValue(context, params))
5893 {
5894 return false;
5895 }
5896 break;
5897
5898 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005899 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005900 return false;
5901 }
5902
5903 return true;
5904}
5905
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005906template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
5907template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04005908
Jamie Madill5b772312018-03-08 20:28:32 -05005909bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04005910{
5911 if (index >= MAX_VERTEX_ATTRIBS)
5912 {
5913 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5914 return false;
5915 }
5916
5917 return true;
5918}
5919
5920bool ValidateGetActiveUniformBlockivBase(Context *context,
5921 GLuint program,
5922 GLuint uniformBlockIndex,
5923 GLenum pname,
5924 GLsizei *length)
5925{
5926 if (length)
5927 {
5928 *length = 0;
5929 }
5930
5931 if (context->getClientMajorVersion() < 3)
5932 {
5933 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5934 return false;
5935 }
5936
5937 Program *programObject = GetValidProgram(context, program);
5938 if (!programObject)
5939 {
5940 return false;
5941 }
5942
5943 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5944 {
5945 context->handleError(InvalidValue()
5946 << "uniformBlockIndex exceeds active uniform block count.");
5947 return false;
5948 }
5949
5950 switch (pname)
5951 {
5952 case GL_UNIFORM_BLOCK_BINDING:
5953 case GL_UNIFORM_BLOCK_DATA_SIZE:
5954 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5955 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5956 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5957 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5958 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5959 break;
5960
5961 default:
5962 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5963 return false;
5964 }
5965
5966 if (length)
5967 {
5968 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5969 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005970 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005971 programObject->getUniformBlockByIndex(uniformBlockIndex);
5972 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5973 }
5974 else
5975 {
5976 *length = 1;
5977 }
5978 }
5979
5980 return true;
5981}
5982
Jamie Madill9696d072017-08-26 23:19:57 -04005983template <typename ParamType>
5984bool ValidateSamplerParameterBase(Context *context,
5985 GLuint sampler,
5986 GLenum pname,
5987 GLsizei bufSize,
5988 ParamType *params)
5989{
5990 if (context->getClientMajorVersion() < 3)
5991 {
5992 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5993 return false;
5994 }
5995
5996 if (!context->isSampler(sampler))
5997 {
5998 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5999 return false;
6000 }
6001
6002 const GLsizei minBufSize = 1;
6003 if (bufSize >= 0 && bufSize < minBufSize)
6004 {
6005 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6006 return false;
6007 }
6008
6009 switch (pname)
6010 {
6011 case GL_TEXTURE_WRAP_S:
6012 case GL_TEXTURE_WRAP_T:
6013 case GL_TEXTURE_WRAP_R:
6014 if (!ValidateTextureWrapModeValue(context, params, false))
6015 {
6016 return false;
6017 }
6018 break;
6019
6020 case GL_TEXTURE_MIN_FILTER:
6021 if (!ValidateTextureMinFilterValue(context, params, false))
6022 {
6023 return false;
6024 }
6025 break;
6026
6027 case GL_TEXTURE_MAG_FILTER:
6028 if (!ValidateTextureMagFilterValue(context, params))
6029 {
6030 return false;
6031 }
6032 break;
6033
6034 case GL_TEXTURE_MIN_LOD:
6035 case GL_TEXTURE_MAX_LOD:
6036 // any value is permissible
6037 break;
6038
6039 case GL_TEXTURE_COMPARE_MODE:
6040 if (!ValidateTextureCompareModeValue(context, params))
6041 {
6042 return false;
6043 }
6044 break;
6045
6046 case GL_TEXTURE_COMPARE_FUNC:
6047 if (!ValidateTextureCompareFuncValue(context, params))
6048 {
6049 return false;
6050 }
6051 break;
6052
6053 case GL_TEXTURE_SRGB_DECODE_EXT:
6054 if (!ValidateTextureSRGBDecodeValue(context, params))
6055 {
6056 return false;
6057 }
6058 break;
6059
Luc Ferron1b1a8642018-01-23 15:12:01 -05006060 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6061 {
6062 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6063 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6064 {
6065 return false;
6066 }
6067 }
6068 break;
6069
Jamie Madill9696d072017-08-26 23:19:57 -04006070 default:
6071 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6072 return false;
6073 }
6074
6075 return true;
6076}
6077
6078template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6079template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6080
6081bool ValidateGetSamplerParameterBase(Context *context,
6082 GLuint sampler,
6083 GLenum pname,
6084 GLsizei *length)
6085{
6086 if (length)
6087 {
6088 *length = 0;
6089 }
6090
6091 if (context->getClientMajorVersion() < 3)
6092 {
6093 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6094 return false;
6095 }
6096
6097 if (!context->isSampler(sampler))
6098 {
6099 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6100 return false;
6101 }
6102
6103 switch (pname)
6104 {
6105 case GL_TEXTURE_WRAP_S:
6106 case GL_TEXTURE_WRAP_T:
6107 case GL_TEXTURE_WRAP_R:
6108 case GL_TEXTURE_MIN_FILTER:
6109 case GL_TEXTURE_MAG_FILTER:
6110 case GL_TEXTURE_MIN_LOD:
6111 case GL_TEXTURE_MAX_LOD:
6112 case GL_TEXTURE_COMPARE_MODE:
6113 case GL_TEXTURE_COMPARE_FUNC:
6114 break;
6115
Luc Ferron1b1a8642018-01-23 15:12:01 -05006116 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6117 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6118 {
6119 return false;
6120 }
6121 break;
6122
Jamie Madill9696d072017-08-26 23:19:57 -04006123 case GL_TEXTURE_SRGB_DECODE_EXT:
6124 if (!context->getExtensions().textureSRGBDecode)
6125 {
6126 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6127 return false;
6128 }
6129 break;
6130
6131 default:
6132 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6133 return false;
6134 }
6135
6136 if (length)
6137 {
6138 *length = 1;
6139 }
6140 return true;
6141}
6142
6143bool ValidateGetInternalFormativBase(Context *context,
6144 GLenum target,
6145 GLenum internalformat,
6146 GLenum pname,
6147 GLsizei bufSize,
6148 GLsizei *numParams)
6149{
6150 if (numParams)
6151 {
6152 *numParams = 0;
6153 }
6154
6155 if (context->getClientMajorVersion() < 3)
6156 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006157 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006158 return false;
6159 }
6160
6161 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
6162 if (!formatCaps.renderable)
6163 {
6164 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6165 return false;
6166 }
6167
6168 switch (target)
6169 {
6170 case GL_RENDERBUFFER:
6171 break;
6172
6173 case GL_TEXTURE_2D_MULTISAMPLE:
6174 if (context->getClientVersion() < ES_3_1)
6175 {
6176 context->handleError(InvalidOperation()
6177 << "Texture target requires at least OpenGL ES 3.1.");
6178 return false;
6179 }
6180 break;
6181
6182 default:
6183 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6184 return false;
6185 }
6186
6187 if (bufSize < 0)
6188 {
6189 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6190 return false;
6191 }
6192
6193 GLsizei maxWriteParams = 0;
6194 switch (pname)
6195 {
6196 case GL_NUM_SAMPLE_COUNTS:
6197 maxWriteParams = 1;
6198 break;
6199
6200 case GL_SAMPLES:
6201 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6202 break;
6203
6204 default:
6205 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6206 return false;
6207 }
6208
6209 if (numParams)
6210 {
6211 // glGetInternalFormativ will not overflow bufSize
6212 *numParams = std::min(bufSize, maxWriteParams);
6213 }
6214
6215 return true;
6216}
6217
Jamie Madille98b1b52018-03-08 09:47:23 -05006218// We should check with Khronos if returning INVALID_FRAMEBUFFER_OPERATION is OK when querying
6219// implementation format info for incomplete framebuffers. It seems like these queries are
6220// incongruent with the other errors.
6221bool ValidateFramebufferComplete(Context *context, Framebuffer *framebuffer, bool isFramebufferOp)
6222{
6223 bool complete = false;
6224 ANGLE_VALIDATION_TRY(framebuffer->isComplete(context, &complete));
6225 if (!complete)
6226 {
6227 if (isFramebufferOp)
6228 {
6229 context->handleError(InvalidFramebufferOperation());
6230 }
6231 else
6232 {
6233 context->handleError(InvalidOperation());
6234 }
6235 return false;
6236 }
6237 return true;
6238}
6239
6240bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6241{
6242 GLint samples = 0;
6243 ANGLE_VALIDATION_TRY(framebuffer->getSamples(context, &samples));
6244 if (samples != 0)
6245 {
6246 context->handleError(InvalidOperation());
6247 return false;
6248 }
6249 return true;
6250}
6251
Jamie Madillc29968b2016-01-20 11:17:23 -05006252} // namespace gl