blob: 1d7e0910348a471049bb9479ef56ba9e7f6310de [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
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500526bool IsETC2EACFormat(const GLenum format)
527{
528 // ES 3.1, Table 8.19
529 switch (format)
530 {
531 case GL_COMPRESSED_R11_EAC:
532 case GL_COMPRESSED_SIGNED_R11_EAC:
533 case GL_COMPRESSED_RG11_EAC:
534 case GL_COMPRESSED_SIGNED_RG11_EAC:
535 case GL_COMPRESSED_RGB8_ETC2:
536 case GL_COMPRESSED_SRGB8_ETC2:
537 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
538 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
539 case GL_COMPRESSED_RGBA8_ETC2_EAC:
540 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
541 return true;
542
543 default:
544 return false;
545 }
546}
547
Jamie Madill5b772312018-03-08 20:28:32 -0500548bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400549{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800550 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400551 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800552 case TextureType::_2D:
553 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800554 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400555
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800556 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400557 return context->getExtensions().textureRectangle;
558
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800559 case TextureType::_3D:
560 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800561 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500562
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800563 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800564 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400565
He Yunchaoced53ae2016-11-29 15:00:51 +0800566 default:
567 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500568 }
Jamie Madill35d15012013-10-07 10:46:37 -0400569}
570
Jamie Madill5b772312018-03-08 20:28:32 -0500571bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500572{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800573 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500574 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800575 case TextureType::_2D:
576 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500577 return true;
578
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800579 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400580 return context->getExtensions().textureRectangle;
581
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500582 default:
583 return false;
584 }
585}
586
Jamie Madill5b772312018-03-08 20:28:32 -0500587bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500588{
589 switch (target)
590 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800591 case TextureType::_3D:
592 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300593 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500594
595 default:
596 return false;
597 }
598}
599
Ian Ewellbda75592016-04-18 17:25:54 -0400600// Most texture GL calls are not compatible with external textures, so we have a separate validation
601// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500602bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400603{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800604 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400605 (context->getExtensions().eglImageExternal ||
606 context->getExtensions().eglStreamConsumerExternal);
607}
608
Shannon Woods4dfed832014-03-17 20:03:39 -0400609// This function differs from ValidTextureTarget in that the target must be
610// usable as the destination of a 2D operation-- so a cube face is valid, but
611// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400612// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500613bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400614{
615 switch (target)
616 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800617 case TextureTarget::_2D:
618 case TextureTarget::CubeMapNegativeX:
619 case TextureTarget::CubeMapNegativeY:
620 case TextureTarget::CubeMapNegativeZ:
621 case TextureTarget::CubeMapPositiveX:
622 case TextureTarget::CubeMapPositiveY:
623 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800624 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800625 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400626 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800627 default:
628 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500629 }
630}
631
Jamie Madill5b772312018-03-08 20:28:32 -0500632bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -0400633 GLenum mode,
634 GLsizei count,
635 GLenum type,
636 const GLvoid *indices,
637 GLsizei primcount)
638{
639 if (primcount < 0)
640 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700641 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400642 return false;
643 }
644
645 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
646 {
647 return false;
648 }
649
Jamie Madill9fdaa492018-02-16 10:52:11 -0500650 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400651}
652
653bool ValidateDrawArraysInstancedBase(Context *context,
654 GLenum mode,
655 GLint first,
656 GLsizei count,
657 GLsizei primcount)
658{
659 if (primcount < 0)
660 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700661 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400662 return false;
663 }
664
665 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
666 {
667 return false;
668 }
669
Jamie Madill9fdaa492018-02-16 10:52:11 -0500670 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400671}
672
Jamie Madill5b772312018-03-08 20:28:32 -0500673bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400674{
675 // Verify there is at least one active attribute with a divisor of zero
676 const State &state = context->getGLState();
677
678 Program *program = state.getProgram();
679
680 const auto &attribs = state.getVertexArray()->getVertexAttributes();
681 const auto &bindings = state.getVertexArray()->getVertexBindings();
682 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
683 {
684 const VertexAttribute &attrib = attribs[attributeIndex];
685 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300686 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400687 {
688 return true;
689 }
690 }
691
Brandon Jonesafa75152017-07-21 13:11:29 -0700692 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400693 return false;
694}
695
Jamie Madill5b772312018-03-08 20:28:32 -0500696bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500697{
698 switch (target)
699 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800700 case TextureType::_3D:
701 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800702 return true;
703 default:
704 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400705 }
706}
707
Jamie Madill5b772312018-03-08 20:28:32 -0500708bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800709{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800710 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800711 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800712 case TextureType::_2D:
713 case TextureType::_2DArray:
714 case TextureType::_2DMultisample:
715 case TextureType::CubeMap:
716 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800717 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800718 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400719 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800720 default:
721 return false;
722 }
723}
724
Jamie Madill5b772312018-03-08 20:28:32 -0500725bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500726{
He Yunchaoced53ae2016-11-29 15:00:51 +0800727 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
728 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400729 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500730
731 switch (target)
732 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800733 case GL_FRAMEBUFFER:
734 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400735
He Yunchaoced53ae2016-11-29 15:00:51 +0800736 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800737 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400738 return (context->getExtensions().framebufferBlit ||
739 context->getClientMajorVersion() >= 3);
740
He Yunchaoced53ae2016-11-29 15:00:51 +0800741 default:
742 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500743 }
744}
745
Jamie Madill5b772312018-03-08 20:28:32 -0500746bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400747{
Jamie Madillc29968b2016-01-20 11:17:23 -0500748 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400749 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800750 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400751 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800752 case TextureType::_2D:
753 case TextureType::_2DArray:
754 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500755 maxDimension = caps.max2DTextureSize;
756 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800757 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800758 maxDimension = caps.maxCubeMapTextureSize;
759 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800760 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400761 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800762 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800763 maxDimension = caps.max3DTextureSize;
764 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800765 default:
766 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400767 }
768
Brandon Jones6cad5662017-06-14 13:25:13 -0700769 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400770}
771
Jamie Madill5b772312018-03-08 20:28:32 -0500772bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800773 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700774 GLint level,
775 GLsizei width,
776 GLsizei height,
777 GLsizei depth,
778 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400779{
Brandon Jones6cad5662017-06-14 13:25:13 -0700780 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400781 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700782 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400783 return false;
784 }
Austin Kinross08528e12015-10-07 16:24:40 -0700785 // TexSubImage parameters can be NPOT without textureNPOT extension,
786 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500787 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500788 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500789 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400790 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400791 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700792 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400793 return false;
794 }
795
796 if (!ValidMipLevel(context, target, level))
797 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700798 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400799 return false;
800 }
801
802 return true;
803}
804
Geoff Lang966c9402017-04-18 12:38:27 -0400805bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
806{
807 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
808 (size % blockSize == 0);
809}
810
Jamie Madill5b772312018-03-08 20:28:32 -0500811bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500812 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400813 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500814 GLsizei width,
815 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400816{
Geoff Langca271392017-04-05 12:30:00 -0400817 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400818 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400819 {
820 return false;
821 }
822
Geoff Lang966c9402017-04-18 12:38:27 -0400823 if (width < 0 || height < 0)
824 {
825 return false;
826 }
827
828 if (CompressedTextureFormatRequiresExactSize(internalFormat))
829 {
830 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
831 // block size for level 0 but WebGL disallows this.
832 bool smallerThanBlockSizeAllowed =
833 level > 0 || !context->getExtensions().webglCompatibility;
834
835 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
836 smallerThanBlockSizeAllowed) ||
837 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
838 smallerThanBlockSizeAllowed))
839 {
840 return false;
841 }
842 }
843
844 return true;
845}
846
Jamie Madill5b772312018-03-08 20:28:32 -0500847bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400848 GLenum internalFormat,
849 GLint xoffset,
850 GLint yoffset,
851 GLsizei width,
852 GLsizei height,
853 size_t textureWidth,
854 size_t textureHeight)
855{
856 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
857 if (!formatInfo.compressed)
858 {
859 return false;
860 }
861
Geoff Lang44ff5a72017-02-03 15:15:43 -0500862 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400863 {
864 return false;
865 }
866
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500867 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400868 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500869 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400870 yoffset % formatInfo.compressedBlockHeight != 0)
871 {
872 return false;
873 }
874
875 // Allowed to either have data that is a multiple of block size or is smaller than the block
876 // size but fills the entire mip
877 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
878 static_cast<size_t>(width) == textureWidth &&
879 static_cast<size_t>(height) == textureHeight;
880 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
881 (height % formatInfo.compressedBlockHeight) == 0;
882 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400883 {
884 return false;
885 }
886 }
887
Geoff Langd4f180b2013-09-24 13:57:44 -0400888 return true;
889}
890
Jamie Madill5b772312018-03-08 20:28:32 -0500891bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800892 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400893 GLsizei width,
894 GLsizei height,
895 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400896 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400897 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400898 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400899 GLsizei imageSize)
900{
Corentin Wallez336129f2017-10-17 15:55:40 -0400901 gl::Buffer *pixelUnpackBuffer =
902 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400903 if (pixelUnpackBuffer == nullptr && imageSize < 0)
904 {
905 // Checks are not required
906 return true;
907 }
908
909 // ...the data would be unpacked from the buffer object such that the memory reads required
910 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400911 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
912 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400913 const gl::Extents size(width, height, depth);
914 const auto &unpack = context->getGLState().getUnpackState();
915
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800916 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Geoff Langff5b2d52016-09-07 11:32:23 -0400917 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
918 if (endByteOrErr.isError())
919 {
920 context->handleError(endByteOrErr.getError());
921 return false;
922 }
923
924 GLuint endByte = endByteOrErr.getResult();
925
926 if (pixelUnpackBuffer)
927 {
928 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
929 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
930 checkedEndByte += checkedOffset;
931
932 if (!checkedEndByte.IsValid() ||
933 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
934 {
935 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500936 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -0400937 return false;
938 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800939 if (context->getExtensions().webglCompatibility &&
940 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
941 {
942 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
943 PixelUnpackBufferBoundForTransformFeedback);
944 return false;
945 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400946 }
947 else
948 {
949 ASSERT(imageSize >= 0);
950 if (pixels == nullptr && imageSize != 0)
951 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500952 context->handleError(InvalidOperation()
953 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400954 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400955 }
956
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400957 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400958 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500959 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400960 return false;
961 }
962 }
963
964 return true;
965}
966
Geoff Lang37dde692014-01-31 16:34:54 -0500967bool ValidQueryType(const Context *context, GLenum queryType)
968{
He Yunchaoced53ae2016-11-29 15:00:51 +0800969 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
970 "GL extension enums not equal.");
971 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
972 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -0500973
974 switch (queryType)
975 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800976 case GL_ANY_SAMPLES_PASSED:
977 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400978 return context->getClientMajorVersion() >= 3 ||
979 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +0800980 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
981 return (context->getClientMajorVersion() >= 3);
982 case GL_TIME_ELAPSED_EXT:
983 return context->getExtensions().disjointTimerQuery;
984 case GL_COMMANDS_COMPLETED_CHROMIUM:
985 return context->getExtensions().syncQuery;
Jiawei Shaod2fa07e2018-03-15 09:20:25 +0800986 case GL_PRIMITIVES_GENERATED_EXT:
987 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +0800988 default:
989 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500990 }
991}
992
Jamie Madill5b772312018-03-08 20:28:32 -0500993bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400994 GLenum type,
995 GLboolean normalized,
996 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400997 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400998 bool pureInteger)
999{
1000 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001001 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1002 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1003 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1004 // parameter exceeds 255.
1005 constexpr GLsizei kMaxWebGLStride = 255;
1006 if (stride > kMaxWebGLStride)
1007 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001008 context->handleError(InvalidValue()
1009 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001010 return false;
1011 }
1012
1013 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1014 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1015 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1016 // or an INVALID_OPERATION error is generated.
1017 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1018 size_t typeSize = GetVertexFormatTypeSize(internalType);
1019
1020 ASSERT(isPow2(typeSize) && typeSize > 0);
1021 size_t sizeMask = (typeSize - 1);
1022 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1023 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001024 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001025 return false;
1026 }
1027
1028 if ((stride & sizeMask) != 0)
1029 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001030 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001031 return false;
1032 }
1033
1034 return true;
1035}
1036
Jamie Madill5b772312018-03-08 20:28:32 -05001037Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001038{
He Yunchaoced53ae2016-11-29 15:00:51 +08001039 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1040 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1041 // or program object and INVALID_OPERATION if the provided name identifies an object
1042 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001043
Dian Xiang769769a2015-09-09 15:20:08 -07001044 Program *validProgram = context->getProgram(id);
1045
1046 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001047 {
Dian Xiang769769a2015-09-09 15:20:08 -07001048 if (context->getShader(id))
1049 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001050 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001051 }
1052 else
1053 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001054 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001055 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001056 }
Dian Xiang769769a2015-09-09 15:20:08 -07001057
1058 return validProgram;
1059}
1060
Jamie Madill5b772312018-03-08 20:28:32 -05001061Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001062{
1063 // See ValidProgram for spec details.
1064
1065 Shader *validShader = context->getShader(id);
1066
1067 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001068 {
Dian Xiang769769a2015-09-09 15:20:08 -07001069 if (context->getProgram(id))
1070 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001071 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001072 }
1073 else
1074 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001075 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001076 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001077 }
Dian Xiang769769a2015-09-09 15:20:08 -07001078
1079 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001080}
1081
Geoff Langb1196682014-07-23 13:47:29 -04001082bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001083{
Geoff Langfa125c92017-10-24 13:01:46 -04001084 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001085 {
Geoff Langfa125c92017-10-24 13:01:46 -04001086 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1087 {
1088 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1089 return false;
1090 }
Jamie Madillb4472272014-07-03 10:38:55 -04001091
Geoff Langfa125c92017-10-24 13:01:46 -04001092 // Color attachment 0 is validated below because it is always valid
1093 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001094 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001095 {
Geoff Langfa125c92017-10-24 13:01:46 -04001096 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001097 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001098 }
1099 }
1100 else
1101 {
1102 switch (attachment)
1103 {
Geoff Langfa125c92017-10-24 13:01:46 -04001104 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001105 case GL_DEPTH_ATTACHMENT:
1106 case GL_STENCIL_ATTACHMENT:
1107 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001108
He Yunchaoced53ae2016-11-29 15:00:51 +08001109 case GL_DEPTH_STENCIL_ATTACHMENT:
1110 if (!context->getExtensions().webglCompatibility &&
1111 context->getClientMajorVersion() < 3)
1112 {
Geoff Langfa125c92017-10-24 13:01:46 -04001113 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001114 return false;
1115 }
1116 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001117
He Yunchaoced53ae2016-11-29 15:00:51 +08001118 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001119 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001120 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001121 }
1122 }
1123
1124 return true;
1125}
1126
Jamie Madill5b772312018-03-08 20:28:32 -05001127bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001128 GLenum target,
1129 GLsizei samples,
1130 GLenum internalformat,
1131 GLsizei width,
1132 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001133{
1134 switch (target)
1135 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001136 case GL_RENDERBUFFER:
1137 break;
1138 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001139 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001140 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001141 }
1142
1143 if (width < 0 || height < 0 || samples < 0)
1144 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001145 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001146 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001147 }
1148
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001149 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1150 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1151
1152 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001153 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001154 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001155 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001156 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001157 }
1158
1159 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1160 // 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 -08001161 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001162 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1163 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001164 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001165 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001166 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001167 }
1168
Geoff Langaae65a42014-05-26 12:43:44 -04001169 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001170 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001171 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001172 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001173 }
1174
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001175 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001176 if (handle == 0)
1177 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001178 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001179 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001180 }
1181
1182 return true;
1183}
1184
He Yunchaoced53ae2016-11-29 15:00:51 +08001185bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1186 GLenum target,
1187 GLenum attachment,
1188 GLenum renderbuffertarget,
1189 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001190{
Geoff Lange8afa902017-09-27 15:00:43 -04001191 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001193 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001194 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001195 }
1196
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001197 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001198
Jamie Madill84115c92015-04-23 15:00:07 -04001199 ASSERT(framebuffer);
1200 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001201 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001202 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001203 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001204 }
1205
Jamie Madillb4472272014-07-03 10:38:55 -04001206 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001207 {
Jamie Madillb4472272014-07-03 10:38:55 -04001208 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001209 }
1210
Jamie Madillab9d82c2014-01-21 16:38:14 -05001211 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1212 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1213 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1214 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1215 if (renderbuffer != 0)
1216 {
1217 if (!context->getRenderbuffer(renderbuffer))
1218 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001219 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001220 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001221 }
1222 }
1223
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001224 return true;
1225}
1226
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001227bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001228 GLint srcX0,
1229 GLint srcY0,
1230 GLint srcX1,
1231 GLint srcY1,
1232 GLint dstX0,
1233 GLint dstY0,
1234 GLint dstX1,
1235 GLint dstY1,
1236 GLbitfield mask,
1237 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001238{
1239 switch (filter)
1240 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001241 case GL_NEAREST:
1242 break;
1243 case GL_LINEAR:
1244 break;
1245 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001246 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001247 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001248 }
1249
1250 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1251 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001252 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001253 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001254 }
1255
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001256 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1257 // color buffer, leaving only nearest being unfiltered from above
1258 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1259 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001260 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001261 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001262 }
1263
Jamie Madill51f40ec2016-06-15 14:06:00 -04001264 const auto &glState = context->getGLState();
1265 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1266 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001267
1268 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001269 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001270 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001271 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001272 }
1273
Jamie Madille98b1b52018-03-08 09:47:23 -05001274 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madill48faf802014-11-06 15:27:22 -05001275 {
Jamie Madill48faf802014-11-06 15:27:22 -05001276 return false;
1277 }
1278
Jamie Madille98b1b52018-03-08 09:47:23 -05001279 if (!ValidateFramebufferComplete(context, drawFramebuffer, true))
Jamie Madill48faf802014-11-06 15:27:22 -05001280 {
Jamie Madill48faf802014-11-06 15:27:22 -05001281 return false;
1282 }
1283
Qin Jiajiaaef92162018-02-27 13:51:44 +08001284 if (readFramebuffer->id() == drawFramebuffer->id())
1285 {
1286 context->handleError(InvalidOperation());
1287 return false;
1288 }
1289
Jamie Madille98b1b52018-03-08 09:47:23 -05001290 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001291 {
Geoff Langb1196682014-07-23 13:47:29 -04001292 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001293 }
1294
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001295 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1296
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001297 if (mask & GL_COLOR_BUFFER_BIT)
1298 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001299 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001300 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001301
He Yunchao66a41a22016-12-15 16:45:05 +08001302 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001303 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001304 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001305
Geoff Langa15472a2015-08-11 11:48:03 -04001306 for (size_t drawbufferIdx = 0;
1307 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001308 {
Geoff Langa15472a2015-08-11 11:48:03 -04001309 const FramebufferAttachment *attachment =
1310 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1311 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001312 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001313 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001314
Geoff Langb2f3d052013-08-13 12:49:27 -04001315 // The GL ES 3.0.2 spec (pg 193) states that:
1316 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001317 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1318 // as well
1319 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1320 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001321 // Changes with EXT_color_buffer_float:
1322 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001323 GLenum readComponentType = readFormat.info->componentType;
1324 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001325 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001326 readComponentType == GL_SIGNED_NORMALIZED);
1327 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1328 drawComponentType == GL_SIGNED_NORMALIZED);
1329
1330 if (extensions.colorBufferFloat)
1331 {
1332 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1333 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1334
1335 if (readFixedOrFloat != drawFixedOrFloat)
1336 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001337 context->handleError(InvalidOperation()
1338 << "If the read buffer contains fixed-point or "
1339 "floating-point values, the draw buffer must "
1340 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001341 return false;
1342 }
1343 }
1344 else if (readFixedPoint != drawFixedPoint)
1345 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001346 context->handleError(InvalidOperation()
1347 << "If the read buffer contains fixed-point values, "
1348 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001349 return false;
1350 }
1351
1352 if (readComponentType == GL_UNSIGNED_INT &&
1353 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001354 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001355 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001356 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001357 }
1358
Jamie Madill6163c752015-12-07 16:32:59 -05001359 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001360 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001361 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001362 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001363 }
1364
Jamie Madilla3944d42016-07-22 22:13:26 -04001365 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001366 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001367 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001368 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001369 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001370 }
Geoff Lange4915782017-04-12 15:19:07 -04001371
1372 if (context->getExtensions().webglCompatibility &&
1373 *readColorBuffer == *attachment)
1374 {
1375 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001376 InvalidOperation()
1377 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001378 return false;
1379 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001380 }
1381 }
1382
Jamie Madilla3944d42016-07-22 22:13:26 -04001383 if ((readFormat.info->componentType == GL_INT ||
1384 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1385 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001386 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001387 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001388 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001389 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001390 }
He Yunchao66a41a22016-12-15 16:45:05 +08001391 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1392 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1393 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1394 // situation is an application error that would lead to a crash in ANGLE.
1395 else if (drawFramebuffer->hasEnabledDrawBuffer())
1396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001397 context->handleError(
1398 InvalidOperation()
1399 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001400 return false;
1401 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001402 }
1403
He Yunchaoced53ae2016-11-29 15:00:51 +08001404 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001405 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1406 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001407 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001408 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001409 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001410 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001411 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001412 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001413 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001414
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001415 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001416 {
Kenneth Russell69382852017-07-21 16:38:44 -04001417 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001418 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001419 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001420 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001421 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001422
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001423 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001424 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001425 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001426 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001427 }
Geoff Lange4915782017-04-12 15:19:07 -04001428
1429 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1430 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001431 context->handleError(
1432 InvalidOperation()
1433 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001434 return false;
1435 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001436 }
He Yunchao66a41a22016-12-15 16:45:05 +08001437 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1438 else if (drawBuffer)
1439 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001440 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1441 "depth/stencil attachment of a "
1442 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001443 return false;
1444 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001445 }
1446 }
1447
Martin Radeva3ed4572017-07-27 18:29:37 +03001448 // ANGLE_multiview, Revision 1:
1449 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1450 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1451 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1452 {
1453 context->handleError(InvalidFramebufferOperation()
1454 << "Attempt to read from a multi-view framebuffer.");
1455 return false;
1456 }
1457 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1458 {
1459 context->handleError(InvalidFramebufferOperation()
1460 << "Attempt to write to a multi-view framebuffer.");
1461 return false;
1462 }
1463
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001464 return true;
1465}
1466
Jamie Madill4928b7c2017-06-20 12:57:39 -04001467bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001468 GLint x,
1469 GLint y,
1470 GLsizei width,
1471 GLsizei height,
1472 GLenum format,
1473 GLenum type,
1474 GLsizei bufSize,
1475 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001476 GLsizei *columns,
1477 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001478 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001479{
1480 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001481 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001482 return false;
1483 }
1484
Geoff Lang62fce5b2016-09-30 10:46:35 -04001485 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001486 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001487 {
Geoff Langb1196682014-07-23 13:47:29 -04001488 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001489 }
1490
Geoff Lang62fce5b2016-09-30 10:46:35 -04001491 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001492 {
Geoff Langb1196682014-07-23 13:47:29 -04001493 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001494 }
1495
Jamie Madillc29968b2016-01-20 11:17:23 -05001496 return true;
1497}
1498
1499bool ValidateReadnPixelsEXT(Context *context,
1500 GLint x,
1501 GLint y,
1502 GLsizei width,
1503 GLsizei height,
1504 GLenum format,
1505 GLenum type,
1506 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001507 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001508{
1509 if (bufSize < 0)
1510 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001511 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001512 return false;
1513 }
1514
Geoff Lang62fce5b2016-09-30 10:46:35 -04001515 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001516 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001517}
Jamie Madill26e91952014-03-05 15:01:27 -05001518
Jamie Madill4928b7c2017-06-20 12:57:39 -04001519bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001520 GLint x,
1521 GLint y,
1522 GLsizei width,
1523 GLsizei height,
1524 GLenum format,
1525 GLenum type,
1526 GLsizei bufSize,
1527 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001528 GLsizei *columns,
1529 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001530 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001531{
1532 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001533 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001534 return false;
1535 }
1536
Geoff Lange93daba2017-03-30 13:54:40 -04001537 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1538 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001539 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001540 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001541 }
1542
Geoff Lang62fce5b2016-09-30 10:46:35 -04001543 if (!ValidateRobustBufferSize(context, bufSize, *length))
1544 {
1545 return false;
1546 }
1547
1548 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001549}
1550
Jamie Madillf0e04492017-08-26 15:28:42 -04001551bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001552{
1553 if (!context->getExtensions().occlusionQueryBoolean &&
1554 !context->getExtensions().disjointTimerQuery)
1555 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001556 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001557 return false;
1558 }
1559
Olli Etuaho41997e72016-03-10 13:38:39 +02001560 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001561}
1562
Jamie Madillf0e04492017-08-26 15:28:42 -04001563bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001564{
1565 if (!context->getExtensions().occlusionQueryBoolean &&
1566 !context->getExtensions().disjointTimerQuery)
1567 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001568 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001569 return false;
1570 }
1571
Olli Etuaho41997e72016-03-10 13:38:39 +02001572 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001573}
1574
Jamie Madillf0e04492017-08-26 15:28:42 -04001575bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1576{
1577 if (!context->getExtensions().occlusionQueryBoolean &&
1578 !context->getExtensions().disjointTimerQuery)
1579 {
1580 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1581 return false;
1582 }
1583
1584 return true;
1585}
1586
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001587bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001588{
1589 if (!ValidQueryType(context, target))
1590 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001591 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001592 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001593 }
1594
1595 if (id == 0)
1596 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001597 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001598 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001599 }
1600
1601 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1602 // of zero, if the active query object name for <target> is non-zero (for the
1603 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1604 // the active query for either target is non-zero), if <id> is the name of an
1605 // existing query object whose type does not match <target>, or if <id> is the
1606 // active query object name for any query type, the error INVALID_OPERATION is
1607 // generated.
1608
1609 // Ensure no other queries are active
1610 // NOTE: If other queries than occlusion are supported, we will need to check
1611 // separately that:
1612 // a) The query ID passed is not the current active query for any target/type
1613 // b) There are no active queries for the requested target (and in the case
1614 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1615 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001616
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001617 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001618 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001619 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001620 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001621 }
1622
1623 Query *queryObject = context->getQuery(id, true, target);
1624
1625 // check that name was obtained with glGenQueries
1626 if (!queryObject)
1627 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001628 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001629 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001630 }
1631
1632 // check for type mismatch
1633 if (queryObject->getType() != target)
1634 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001635 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001636 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001637 }
1638
1639 return true;
1640}
1641
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001642bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1643{
1644 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001645 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001646 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001647 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001648 return false;
1649 }
1650
1651 return ValidateBeginQueryBase(context, target, id);
1652}
1653
1654bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001655{
1656 if (!ValidQueryType(context, target))
1657 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001658 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001659 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001660 }
1661
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001662 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001663
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001664 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001665 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001666 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001667 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001668 }
1669
Jamie Madill45c785d2014-05-13 14:09:34 -04001670 return true;
1671}
1672
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001673bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1674{
1675 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001676 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001677 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001678 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001679 return false;
1680 }
1681
1682 return ValidateEndQueryBase(context, target);
1683}
1684
1685bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1686{
1687 if (!context->getExtensions().disjointTimerQuery)
1688 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001689 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001690 return false;
1691 }
1692
1693 if (target != GL_TIMESTAMP_EXT)
1694 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001695 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001696 return false;
1697 }
1698
1699 Query *queryObject = context->getQuery(id, true, target);
1700 if (queryObject == nullptr)
1701 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001702 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001703 return false;
1704 }
1705
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001706 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001707 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001708 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001709 return false;
1710 }
1711
1712 return true;
1713}
1714
Geoff Lang2186c382016-10-14 10:54:54 -04001715bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001716{
Geoff Lang2186c382016-10-14 10:54:54 -04001717 if (numParams)
1718 {
1719 *numParams = 0;
1720 }
1721
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001722 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1723 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001724 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001725 return false;
1726 }
1727
1728 switch (pname)
1729 {
1730 case GL_CURRENT_QUERY_EXT:
1731 if (target == GL_TIMESTAMP_EXT)
1732 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001733 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001734 return false;
1735 }
1736 break;
1737 case GL_QUERY_COUNTER_BITS_EXT:
1738 if (!context->getExtensions().disjointTimerQuery ||
1739 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1740 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001741 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001742 return false;
1743 }
1744 break;
1745 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001746 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001747 return false;
1748 }
1749
Geoff Lang2186c382016-10-14 10:54:54 -04001750 if (numParams)
1751 {
1752 // All queries return only one value
1753 *numParams = 1;
1754 }
1755
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001756 return true;
1757}
1758
1759bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1760{
1761 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001762 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001763 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001764 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001765 return false;
1766 }
1767
Geoff Lang2186c382016-10-14 10:54:54 -04001768 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001769}
1770
Geoff Lang2186c382016-10-14 10:54:54 -04001771bool ValidateGetQueryivRobustANGLE(Context *context,
1772 GLenum target,
1773 GLenum pname,
1774 GLsizei bufSize,
1775 GLsizei *length,
1776 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001777{
Geoff Lang2186c382016-10-14 10:54:54 -04001778 if (!ValidateRobustEntryPoint(context, bufSize))
1779 {
1780 return false;
1781 }
1782
1783 if (!ValidateGetQueryivBase(context, target, pname, length))
1784 {
1785 return false;
1786 }
1787
1788 if (!ValidateRobustBufferSize(context, bufSize, *length))
1789 {
1790 return false;
1791 }
1792
1793 return true;
1794}
1795
1796bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1797{
1798 if (numParams)
1799 {
1800 *numParams = 0;
1801 }
1802
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001803 Query *queryObject = context->getQuery(id, false, GL_NONE);
1804
1805 if (!queryObject)
1806 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001807 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001808 return false;
1809 }
1810
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001811 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001812 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001813 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001814 return false;
1815 }
1816
1817 switch (pname)
1818 {
1819 case GL_QUERY_RESULT_EXT:
1820 case GL_QUERY_RESULT_AVAILABLE_EXT:
1821 break;
1822
1823 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001824 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001825 return false;
1826 }
1827
Geoff Lang2186c382016-10-14 10:54:54 -04001828 if (numParams)
1829 {
1830 *numParams = 1;
1831 }
1832
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001833 return true;
1834}
1835
1836bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1837{
1838 if (!context->getExtensions().disjointTimerQuery)
1839 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001840 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001841 return false;
1842 }
Geoff Lang2186c382016-10-14 10:54:54 -04001843 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1844}
1845
1846bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1847 GLuint id,
1848 GLenum pname,
1849 GLsizei bufSize,
1850 GLsizei *length,
1851 GLint *params)
1852{
1853 if (!context->getExtensions().disjointTimerQuery)
1854 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001855 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001856 return false;
1857 }
1858
1859 if (!ValidateRobustEntryPoint(context, bufSize))
1860 {
1861 return false;
1862 }
1863
1864 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1865 {
1866 return false;
1867 }
1868
1869 if (!ValidateRobustBufferSize(context, bufSize, *length))
1870 {
1871 return false;
1872 }
1873
1874 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001875}
1876
1877bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1878{
1879 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001880 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001881 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001882 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001883 return false;
1884 }
Geoff Lang2186c382016-10-14 10:54:54 -04001885 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1886}
1887
1888bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1889 GLuint id,
1890 GLenum pname,
1891 GLsizei bufSize,
1892 GLsizei *length,
1893 GLuint *params)
1894{
1895 if (!context->getExtensions().disjointTimerQuery &&
1896 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1897 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001898 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001899 return false;
1900 }
1901
1902 if (!ValidateRobustEntryPoint(context, bufSize))
1903 {
1904 return false;
1905 }
1906
1907 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1908 {
1909 return false;
1910 }
1911
1912 if (!ValidateRobustBufferSize(context, bufSize, *length))
1913 {
1914 return false;
1915 }
1916
1917 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001918}
1919
1920bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1921{
1922 if (!context->getExtensions().disjointTimerQuery)
1923 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001924 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001925 return false;
1926 }
Geoff Lang2186c382016-10-14 10:54:54 -04001927 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1928}
1929
1930bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1931 GLuint id,
1932 GLenum pname,
1933 GLsizei bufSize,
1934 GLsizei *length,
1935 GLint64 *params)
1936{
1937 if (!context->getExtensions().disjointTimerQuery)
1938 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001939 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001940 return false;
1941 }
1942
1943 if (!ValidateRobustEntryPoint(context, bufSize))
1944 {
1945 return false;
1946 }
1947
1948 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1949 {
1950 return false;
1951 }
1952
1953 if (!ValidateRobustBufferSize(context, bufSize, *length))
1954 {
1955 return false;
1956 }
1957
1958 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001959}
1960
1961bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1962{
1963 if (!context->getExtensions().disjointTimerQuery)
1964 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001965 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001966 return false;
1967 }
Geoff Lang2186c382016-10-14 10:54:54 -04001968 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1969}
1970
1971bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1972 GLuint id,
1973 GLenum pname,
1974 GLsizei bufSize,
1975 GLsizei *length,
1976 GLuint64 *params)
1977{
1978 if (!context->getExtensions().disjointTimerQuery)
1979 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001980 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001981 return false;
1982 }
1983
1984 if (!ValidateRobustEntryPoint(context, bufSize))
1985 {
1986 return false;
1987 }
1988
1989 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1990 {
1991 return false;
1992 }
1993
1994 if (!ValidateRobustBufferSize(context, bufSize, *length))
1995 {
1996 return false;
1997 }
1998
1999 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002000}
2001
Jamie Madill5b772312018-03-08 20:28:32 -05002002bool ValidateUniformCommonBase(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002003 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002004 GLint location,
2005 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002006 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002007{
Jiajia Qin5451d532017-11-16 17:16:34 +08002008 // TODO(Jiajia): Add image uniform check in future.
2009 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002010 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002011 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002012 return false;
2013 }
2014
Jiajia Qin5451d532017-11-16 17:16:34 +08002015 if (!program)
2016 {
2017 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2018 return false;
2019 }
2020
2021 if (!program->isLinked())
2022 {
2023 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2024 return false;
2025 }
2026
2027 if (location == -1)
2028 {
2029 // Silently ignore the uniform command
2030 return false;
2031 }
2032
2033 const auto &uniformLocations = program->getUniformLocations();
2034 size_t castedLocation = static_cast<size_t>(location);
2035 if (castedLocation >= uniformLocations.size())
2036 {
2037 context->handleError(InvalidOperation() << "Invalid uniform location");
2038 return false;
2039 }
2040
2041 const auto &uniformLocation = uniformLocations[castedLocation];
2042 if (uniformLocation.ignored)
2043 {
2044 // Silently ignore the uniform command
2045 return false;
2046 }
2047
2048 if (!uniformLocation.used())
2049 {
2050 context->handleError(InvalidOperation());
2051 return false;
2052 }
2053
2054 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2055
2056 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2057 if (!uniform.isArray() && count > 1)
2058 {
2059 context->handleError(InvalidOperation());
2060 return false;
2061 }
2062
2063 *uniformOut = &uniform;
2064 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002065}
2066
Jamie Madill5b772312018-03-08 20:28:32 -05002067bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002068 GLenum uniformType,
2069 GLsizei count,
2070 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002071{
Jiajia Qin5451d532017-11-16 17:16:34 +08002072 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2073 // It is compatible with INT or BOOL.
2074 // Do these cheap tests first, for a little extra speed.
2075 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002076 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002077 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002078 }
2079
Jiajia Qin5451d532017-11-16 17:16:34 +08002080 if (IsSamplerType(uniformType))
2081 {
2082 // Check that the values are in range.
2083 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2084 for (GLsizei i = 0; i < count; ++i)
2085 {
2086 if (value[i] < 0 || value[i] >= max)
2087 {
2088 context->handleError(InvalidValue() << "sampler uniform value out of range");
2089 return false;
2090 }
2091 }
2092 return true;
2093 }
2094
2095 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2096 return false;
2097}
2098
Jamie Madill5b772312018-03-08 20:28:32 -05002099bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002100{
2101 // Check that the value type is compatible with uniform type.
2102 // Do the cheaper test first, for a little extra speed.
2103 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2104 {
2105 return true;
2106 }
2107
2108 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2109 return false;
2110}
2111
Jamie Madill5b772312018-03-08 20:28:32 -05002112bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002113{
2114 // Check that the value type is compatible with uniform type.
2115 if (valueType == uniformType)
2116 {
2117 return true;
2118 }
2119
2120 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2121 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002122}
2123
Jamie Madill5b772312018-03-08 20:28:32 -05002124bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002125{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002126 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002127 gl::Program *programObject = context->getGLState().getProgram();
2128 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2129 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002130}
2131
Jamie Madill5b772312018-03-08 20:28:32 -05002132bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002133{
2134 const LinkedUniform *uniform = nullptr;
2135 gl::Program *programObject = context->getGLState().getProgram();
2136 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2137 ValidateUniform1ivValue(context, uniform->type, count, value);
2138}
2139
Jamie Madill5b772312018-03-08 20:28:32 -05002140bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002141 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002142 GLint location,
2143 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002144 GLboolean transpose)
2145{
Geoff Lang92019432017-11-20 13:09:34 -05002146 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002147 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002148 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002149 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002150 }
2151
Jamie Madill62d31cb2015-09-11 13:25:51 -04002152 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002153 gl::Program *programObject = context->getGLState().getProgram();
2154 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2155 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002156}
2157
Jamie Madill5b772312018-03-08 20:28:32 -05002158bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002159{
2160 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2161 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002162 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002163 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002164 }
2165
Jamie Madill0af26e12015-03-05 19:54:33 -05002166 const Caps &caps = context->getCaps();
2167
Jamie Madill893ab082014-05-16 16:56:10 -04002168 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2169 {
2170 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2171
Jamie Madill0af26e12015-03-05 19:54:33 -05002172 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002173 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002174 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002175 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002176 }
2177 }
2178
2179 switch (pname)
2180 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002181 case GL_TEXTURE_BINDING_2D:
2182 case GL_TEXTURE_BINDING_CUBE_MAP:
2183 case GL_TEXTURE_BINDING_3D:
2184 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002185 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002186 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002187 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2188 if (!context->getExtensions().textureRectangle)
2189 {
2190 context->handleError(InvalidEnum()
2191 << "ANGLE_texture_rectangle extension not present");
2192 return false;
2193 }
2194 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002195 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2196 if (!context->getExtensions().eglStreamConsumerExternal &&
2197 !context->getExtensions().eglImageExternal)
2198 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002199 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2200 "nor GL_OES_EGL_image_external "
2201 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002202 return false;
2203 }
2204 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002205
He Yunchaoced53ae2016-11-29 15:00:51 +08002206 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2207 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002208 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002209 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2210 ASSERT(readFramebuffer);
2211
2212 if (!ValidateFramebufferComplete(context, readFramebuffer, false))
Jamie Madill893ab082014-05-16 16:56:10 -04002213 {
Geoff Langb1196682014-07-23 13:47:29 -04002214 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002215 }
2216
Jamie Madille98b1b52018-03-08 09:47:23 -05002217 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002218 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002219 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002220 return false;
2221 }
2222
Jamie Madille98b1b52018-03-08 09:47:23 -05002223 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002224 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002225 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002226 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002227 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002228 }
2229 }
2230 break;
2231
He Yunchaoced53ae2016-11-29 15:00:51 +08002232 default:
2233 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002234 }
2235
2236 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002237 if (*numParams == 0)
2238 {
2239 return false;
2240 }
2241
2242 return true;
2243}
2244
Jamie Madill5b772312018-03-08 20:28:32 -05002245bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002246 GLenum pname,
2247 GLsizei bufSize,
2248 GLenum *nativeType,
2249 unsigned int *numParams)
2250{
2251 if (!ValidateRobustEntryPoint(context, bufSize))
2252 {
2253 return false;
2254 }
2255
2256 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2257 {
2258 return false;
2259 }
2260
2261 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002262 {
2263 return false;
2264 }
2265
2266 return true;
2267}
2268
Jamie Madill5b772312018-03-08 20:28:32 -05002269bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002270 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002271 GLint level,
2272 GLenum internalformat,
2273 bool isSubImage,
2274 GLint xoffset,
2275 GLint yoffset,
2276 GLint zoffset,
2277 GLint x,
2278 GLint y,
2279 GLsizei width,
2280 GLsizei height,
2281 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002282 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002283{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002284 TextureType texType = TextureTargetToType(target);
2285
Brandon Jones6cad5662017-06-14 13:25:13 -07002286 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002287 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002288 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2289 return false;
2290 }
2291
2292 if (width < 0 || height < 0)
2293 {
2294 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002295 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002296 }
2297
He Yunchaoced53ae2016-11-29 15:00:51 +08002298 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2299 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002300 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002301 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002302 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002303 }
2304
2305 if (border != 0)
2306 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002307 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002308 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002309 }
2310
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002311 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002312 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002313 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002314 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002315 }
2316
Jamie Madille98b1b52018-03-08 09:47:23 -05002317 const gl::State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002318 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madille98b1b52018-03-08 09:47:23 -05002319 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madill560a8d82014-05-21 13:06:20 -04002320 {
Geoff Langb1196682014-07-23 13:47:29 -04002321 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002322 }
2323
Jamie Madille98b1b52018-03-08 09:47:23 -05002324 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002325 {
Geoff Langb1196682014-07-23 13:47:29 -04002326 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002327 }
2328
Martin Radev138064f2016-07-15 12:03:41 +03002329 if (readFramebuffer->getReadBufferState() == GL_NONE)
2330 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002331 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002332 return false;
2333 }
2334
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002335 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2336 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002337 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002338 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002339 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2340 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002341 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002342 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002343 return false;
2344 }
2345
Martin Radev04e2c3b2017-07-27 16:54:35 +03002346 // ANGLE_multiview spec, Revision 1:
2347 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2348 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2349 // is not NONE.
2350 if (source->getMultiviewLayout() != GL_NONE)
2351 {
2352 context->handleError(InvalidFramebufferOperation()
2353 << "The active read framebuffer object has multiview attachments.");
2354 return false;
2355 }
2356
Geoff Langaae65a42014-05-26 12:43:44 -04002357 const gl::Caps &caps = context->getCaps();
2358
Geoff Langaae65a42014-05-26 12:43:44 -04002359 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002360 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002361 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002362 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002363 maxDimension = caps.max2DTextureSize;
2364 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002365
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002366 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002367 maxDimension = caps.maxCubeMapTextureSize;
2368 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002369
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002370 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002371 maxDimension = caps.maxRectangleTextureSize;
2372 break;
2373
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002374 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002375 maxDimension = caps.max2DTextureSize;
2376 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002377
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002378 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002379 maxDimension = caps.max3DTextureSize;
2380 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002381
He Yunchaoced53ae2016-11-29 15:00:51 +08002382 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002383 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002384 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002385 }
2386
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002387 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002388 if (!texture)
2389 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002390 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002391 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002392 }
2393
Geoff Lang69cce582015-09-17 13:20:36 -04002394 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002395 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002396 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002397 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002398 }
2399
Geoff Langca271392017-04-05 12:30:00 -04002400 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002401 isSubImage ? *texture->getFormat(target, level).info
2402 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002403
Geoff Lang966c9402017-04-18 12:38:27 -04002404 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002406 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002407 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002408 }
2409
2410 if (isSubImage)
2411 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002412 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2413 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2414 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002415 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002416 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002417 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002418 }
2419 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002420 else
2421 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002422 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002423 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002424 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002425 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002426 }
2427
Geoff Langeb66a6e2016-10-31 13:06:12 -04002428 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002429 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002430 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002431 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002432 }
2433
2434 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002435 if (static_cast<int>(width) > maxLevelDimension ||
2436 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002437 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002438 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002439 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002440 }
2441 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002442
Jamie Madill0c8abca2016-07-22 20:21:26 -04002443 if (textureFormatOut)
2444 {
2445 *textureFormatOut = texture->getFormat(target, level);
2446 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002447
2448 // Detect texture copying feedback loops for WebGL.
2449 if (context->getExtensions().webglCompatibility)
2450 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002451 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002452 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002453 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002454 return false;
2455 }
2456 }
2457
Jamie Madill560a8d82014-05-21 13:06:20 -04002458 return true;
2459}
2460
Jamie Madill5b772312018-03-08 20:28:32 -05002461bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002462{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002463 const Extensions &extensions = context->getExtensions();
2464
Jamie Madill1aeb1312014-06-20 13:21:25 -04002465 switch (mode)
2466 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002467 case GL_POINTS:
2468 case GL_LINES:
2469 case GL_LINE_LOOP:
2470 case GL_LINE_STRIP:
2471 case GL_TRIANGLES:
2472 case GL_TRIANGLE_STRIP:
2473 case GL_TRIANGLE_FAN:
2474 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002475
2476 case GL_LINES_ADJACENCY_EXT:
2477 case GL_LINE_STRIP_ADJACENCY_EXT:
2478 case GL_TRIANGLES_ADJACENCY_EXT:
2479 case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
2480 if (!extensions.geometryShader)
2481 {
2482 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2483 return false;
2484 }
2485 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002486 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002487 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002488 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002489 }
2490
Jamie Madill250d33f2014-06-06 17:09:03 -04002491 if (count < 0)
2492 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002493 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002494 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002495 }
2496
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002497 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002498
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002499 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2500 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2501 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2502 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002503 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002504 // Check for mapped buffers
2505 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002506 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002507 {
2508 context->handleError(InvalidOperation());
2509 return false;
2510 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002511 }
2512
Jamie Madillcbcde722017-01-06 14:50:00 -05002513 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2514 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002515 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002516 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002517 {
Ken Russellb9f92502018-01-27 19:00:26 -08002518 ASSERT(framebuffer);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002519 const FramebufferAttachment *dsAttachment =
2520 framebuffer->getStencilOrDepthStencilAttachment();
Ken Russellb9f92502018-01-27 19:00:26 -08002521 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2522 ASSERT(stencilBits <= 8);
2523
Jinyoung Hur85769f02015-10-20 17:08:44 -04002524 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Ken Russellb9f92502018-01-27 19:00:26 -08002525 if (depthStencilState.stencilTest && stencilBits > 0)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002526 {
Ken Russellb9f92502018-01-27 19:00:26 -08002527 GLuint maxStencilValue = (1 << stencilBits) - 1;
2528
2529 bool differentRefs =
2530 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2531 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2532 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2533 (depthStencilState.stencilBackWritemask & maxStencilValue);
2534 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2535 (depthStencilState.stencilBackMask & maxStencilValue);
2536
2537 if (differentRefs || differentWritemasks || differentMasks)
Jamie Madillcbcde722017-01-06 14:50:00 -05002538 {
Ken Russellb9f92502018-01-27 19:00:26 -08002539 if (!extensions.webglCompatibility)
2540 {
2541 ERR() << "This ANGLE implementation does not support separate front/back "
2542 "stencil writemasks, reference values, or stencil mask values.";
2543 }
2544 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
2545 return false;
Jamie Madillcbcde722017-01-06 14:50:00 -05002546 }
Geoff Lang3a86ad32015-09-01 11:47:05 -04002547 }
Jamie Madillac528012014-06-20 13:21:23 -04002548 }
2549
Jamie Madille98b1b52018-03-08 09:47:23 -05002550 if (!ValidateFramebufferComplete(context, framebuffer, true))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002551 {
Geoff Langb1196682014-07-23 13:47:29 -04002552 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002553 }
2554
Geoff Lang7dd2e102014-11-10 15:19:26 -05002555 gl::Program *program = state.getProgram();
2556 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002557 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002558 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002559 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002560 }
2561
Yunchao Hecddcb592017-11-13 15:27:35 +08002562 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2563 // vertex shader stage or fragment shader stage is a undefined behaviour.
2564 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2565 // produce undefined result.
Jiawei Shao385b3e02018-03-21 09:43:28 +08002566 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2567 !program->hasLinkedShaderStage(ShaderType::Fragment))
Yunchao Hecddcb592017-11-13 15:27:35 +08002568 {
2569 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2570 "vertex shader stage or fragment shader stage.");
2571 return false;
2572 }
2573
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002574 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002575 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002576 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002577 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002578 }
2579
Martin Radevffe754b2017-07-31 10:38:07 +03002580 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002581 {
Martin Radevda8e2572017-09-12 17:21:16 +03002582 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002583 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002584 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002585 {
2586 context->handleError(InvalidOperation() << "The number of views in the active program "
2587 "and draw framebuffer does not match.");
2588 return false;
2589 }
Martin Radev7e69f762017-07-27 14:54:13 +03002590
2591 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2592 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2593 framebufferNumViews > 1)
2594 {
2595 context->handleError(InvalidOperation()
2596 << "There is an active transform feedback object "
2597 "when the number of views in the active draw "
2598 "framebuffer is greater than 1.");
2599 return false;
2600 }
Martin Radevffe754b2017-07-31 10:38:07 +03002601
2602 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2603 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2604 {
2605 context->handleError(InvalidOperation() << "There is an active query for target "
2606 "GL_TIME_ELAPSED_EXT when the number of "
2607 "views in the active draw framebuffer is "
2608 "greater than 1.");
2609 return false;
2610 }
Martin Radev7cf61662017-07-26 17:10:53 +03002611 }
2612
Jiawei Shaofccebff2018-03-08 13:51:02 +08002613 // Do geometry shader specific validations
Jiawei Shao385b3e02018-03-21 09:43:28 +08002614 if (program->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shaofccebff2018-03-08 13:51:02 +08002615 {
2616 if (!IsCompatibleDrawModeWithGeometryShader(mode,
2617 program->getGeometryShaderInputPrimitiveType()))
2618 {
2619 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2620 IncompatibleDrawModeAgainstGeometryShader);
2621 return false;
2622 }
2623 }
2624
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002625 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002626 for (unsigned int uniformBlockIndex = 0;
2627 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002628 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002629 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002630 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002631 const OffsetBindingPointer<Buffer> &uniformBuffer =
2632 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002633
Geoff Lang5d124a62015-09-15 13:03:27 -04002634 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002635 {
2636 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002637 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002638 InvalidOperation()
2639 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002640 return false;
2641 }
2642
Geoff Lang5d124a62015-09-15 13:03:27 -04002643 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002644 if (uniformBufferSize == 0)
2645 {
2646 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002647 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002648 }
2649
Jamie Madill62d31cb2015-09-11 13:25:51 -04002650 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002651 {
2652 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002653 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002654 InvalidOperation()
2655 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002656 return false;
2657 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002658
2659 if (extensions.webglCompatibility &&
2660 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2661 {
2662 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2663 UniformBufferBoundForTransformFeedback);
2664 return false;
2665 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002666 }
2667
Geoff Lange0cff192017-05-30 13:04:56 -04002668 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002669 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002670 {
James Darpiniane8a93c62018-01-04 18:02:24 -08002671 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2672 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2673 transformFeedbackObject->buffersBoundForOtherUse())
2674 {
2675 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferDoubleBound);
2676 return false;
2677 }
Geoff Lange0cff192017-05-30 13:04:56 -04002678 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002679 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2680 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002681 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002682 return false;
2683 }
Geoff Lange0cff192017-05-30 13:04:56 -04002684
Geoff Lang9ab5b822017-05-30 16:19:23 -04002685 // Detect that the vertex shader input types match the attribute types
2686 if (!ValidateVertexShaderAttributeTypeMatch(context))
2687 {
2688 return false;
2689 }
2690
Geoff Lange0cff192017-05-30 13:04:56 -04002691 // Detect that the color buffer types match the fragment shader output types
2692 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2693 {
2694 return false;
2695 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002696 }
2697
Jamie Madill9fdaa492018-02-16 10:52:11 -05002698 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002699}
2700
Jamie Madill5b772312018-03-08 20:28:32 -05002701bool ValidateDrawArraysCommon(Context *context,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002702 GLenum mode,
2703 GLint first,
2704 GLsizei count,
2705 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002706{
Jamie Madillfd716582014-06-06 17:09:04 -04002707 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002708 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002709 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002710 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002711 }
2712
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002713 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002714 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002715 if (curTransformFeedback && curTransformFeedback->isActive() &&
2716 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002717 {
2718 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002719 // that does not match the current transform feedback object's draw mode (if transform
2720 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002721 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002722 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002723 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002724 }
2725
Jiajia Qind9671222016-11-29 16:30:31 +08002726 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002727 {
2728 return false;
2729 }
2730
Corentin Wallez71168a02016-12-19 15:11:18 -08002731 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002732 // - first < 0 has been checked as an error condition.
2733 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002734 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002735 ASSERT(first >= 0);
2736 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002737 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002738 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2739 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2740 {
2741 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2742 return false;
2743 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002744
Jamie Madill9fdaa492018-02-16 10:52:11 -05002745 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2746 {
2747 return false;
2748 }
Jamie Madillfd716582014-06-06 17:09:04 -04002749 }
2750
2751 return true;
2752}
2753
He Yunchaoced53ae2016-11-29 15:00:51 +08002754bool ValidateDrawArraysInstancedANGLE(Context *context,
2755 GLenum mode,
2756 GLint first,
2757 GLsizei count,
2758 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002759{
Geoff Lang63c5a592017-09-27 14:08:16 -04002760 if (!context->getExtensions().instancedArrays)
2761 {
2762 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2763 return false;
2764 }
2765
Corentin Wallez170efbf2017-05-02 13:45:01 -04002766 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002767 {
2768 return false;
2769 }
2770
Corentin Wallez0dc97812017-06-22 14:38:44 -04002771 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002772}
2773
Jamie Madill5b772312018-03-08 20:28:32 -05002774bool ValidateDrawElementsBase(Context *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002775{
Jamie Madill250d33f2014-06-06 17:09:03 -04002776 switch (type)
2777 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002778 case GL_UNSIGNED_BYTE:
2779 case GL_UNSIGNED_SHORT:
2780 break;
2781 case GL_UNSIGNED_INT:
2782 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2783 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002784 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002785 return false;
2786 }
2787 break;
2788 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002789 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002790 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002791 }
2792
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002793 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002794
2795 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002796 if (curTransformFeedback && curTransformFeedback->isActive() &&
2797 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002798 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002799 // It is an invalid operation to call DrawElements, DrawRangeElements or
2800 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002801 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002802 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002803 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002804 }
2805
Jiajia Qind9671222016-11-29 16:30:31 +08002806 return true;
2807}
2808
Jamie Madill5b772312018-03-08 20:28:32 -05002809bool ValidateDrawElementsCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002810 GLenum mode,
2811 GLsizei count,
2812 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002813 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002814 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002815{
2816 if (!ValidateDrawElementsBase(context, type))
2817 return false;
2818
2819 const State &state = context->getGLState();
2820
Corentin Wallez170efbf2017-05-02 13:45:01 -04002821 if (!ValidateDrawBase(context, mode, count))
2822 {
2823 return false;
2824 }
2825
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002826 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2827 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2828 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2829 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002830 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002831 // Check for mapped buffers
2832 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002833 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002834 {
2835 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2836 return false;
2837 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002838 }
2839
He Yunchaoced53ae2016-11-29 15:00:51 +08002840 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002841 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002842
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002843 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2844
2845 if (context->getExtensions().webglCompatibility)
2846 {
2847 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2848 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2849 {
2850 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2851 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2852 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002853 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002854 return false;
2855 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002856
2857 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2858 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2859 // error is generated.
2860 if (reinterpret_cast<intptr_t>(indices) < 0)
2861 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002862 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002863 return false;
2864 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002865 }
2866
2867 if (context->getExtensions().webglCompatibility ||
2868 !context->getGLState().areClientArraysEnabled())
2869 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002870 if (!elementArrayBuffer && count > 0)
2871 {
2872 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2873 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2874 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002875 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002876 return false;
2877 }
2878 }
2879
Jamie Madill9fdaa492018-02-16 10:52:11 -05002880 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04002881 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002882 // This is an application error that would normally result in a crash, but we catch it and
2883 // return an error
2884 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
2885 return false;
2886 }
2887
2888 if (count > 0 && elementArrayBuffer)
2889 {
2890 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2891 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2892 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2893 constexpr uint64_t kMaxTypeSize = 8;
2894 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2895 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2896 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
2897
2898 uint64_t typeSize = typeBytes;
2899 uint64_t elementCount = static_cast<uint64_t>(count);
2900 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2901
2902 // Doing the multiplication here is overflow-safe
2903 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2904
2905 // The offset can be any value, check for overflows
2906 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2907 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04002908 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002909 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2910 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002911 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05002912
2913 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2914 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002915 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002916 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
2917 return false;
2918 }
2919
2920 ASSERT(isPow2(typeSize) && typeSize > 0);
2921 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
2922 {
2923 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04002924 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002925 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002926
2927 if (context->getExtensions().webglCompatibility &&
2928 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
2929 {
2930 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2931 ElementArrayBufferBoundForTransformFeedback);
2932 return false;
2933 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002934 }
2935
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002936 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002937 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002938 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2939 // access is enabled.
2940 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2941 {
2942 return false;
2943 }
2944 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05002945 else if (count == 0)
2946 {
2947 // ValidateDrawAttribs also does some extra validation that is independent of the vertex
2948 // count.
2949 if (!ValidateDrawAttribs(context, 0, 0, 0))
2950 {
2951 return false;
2952 }
2953 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002954 else
2955 {
2956 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04002957 const DrawCallParams &params = context->getParams<DrawCallParams>();
2958 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
2959 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002960
2961 // If we use an index greater than our maximum supported index range, return an error.
2962 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2963 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04002964 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002965 {
2966 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2967 return false;
2968 }
2969
Jamie Madill6f5444d2018-03-14 10:08:11 -04002970 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end),
2971 static_cast<GLint>(indexRange.vertexCount())))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002972 {
2973 return false;
2974 }
2975
2976 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04002977 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002978 }
2979
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002980 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002981}
2982
Jamie Madill5b772312018-03-08 20:28:32 -05002983bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002984 GLenum mode,
2985 GLsizei count,
2986 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002987 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002988 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002989{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002990 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002991}
2992
Geoff Lang3edfe032015-09-04 16:38:24 -04002993bool ValidateDrawElementsInstancedANGLE(Context *context,
2994 GLenum mode,
2995 GLsizei count,
2996 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002997 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002998 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002999{
Geoff Lang63c5a592017-09-27 14:08:16 -04003000 if (!context->getExtensions().instancedArrays)
3001 {
3002 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3003 return false;
3004 }
3005
Corentin Wallez170efbf2017-05-02 13:45:01 -04003006 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003007 {
3008 return false;
3009 }
3010
Corentin Wallez0dc97812017-06-22 14:38:44 -04003011 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003012}
3013
He Yunchaoced53ae2016-11-29 15:00:51 +08003014bool ValidateFramebufferTextureBase(Context *context,
3015 GLenum target,
3016 GLenum attachment,
3017 GLuint texture,
3018 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003019{
Geoff Lange8afa902017-09-27 15:00:43 -04003020 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003021 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003022 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003023 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003024 }
3025
3026 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003027 {
3028 return false;
3029 }
3030
Jamie Madill55ec3b12014-07-03 10:38:57 -04003031 if (texture != 0)
3032 {
3033 gl::Texture *tex = context->getTexture(texture);
3034
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003035 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003036 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003037 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003038 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003039 }
3040
3041 if (level < 0)
3042 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003043 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003044 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003045 }
3046 }
3047
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003048 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003049 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003050
Jamie Madill84115c92015-04-23 15:00:07 -04003051 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003052 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003053 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003054 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003055 }
3056
3057 return true;
3058}
3059
Geoff Langb1196682014-07-23 13:47:29 -04003060bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003061{
3062 if (program == 0)
3063 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003064 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003065 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003066 }
3067
Dian Xiang769769a2015-09-09 15:20:08 -07003068 gl::Program *programObject = GetValidProgram(context, program);
3069 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003070 {
3071 return false;
3072 }
3073
Jamie Madill0063c512014-08-25 15:47:53 -04003074 if (!programObject || !programObject->isLinked())
3075 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003076 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003077 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003078 }
3079
Geoff Lang7dd2e102014-11-10 15:19:26 -05003080 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003081 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003082 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003083 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003084 }
3085
Jamie Madill0063c512014-08-25 15:47:53 -04003086 return true;
3087}
3088
Geoff Langf41d0ee2016-10-07 13:04:23 -04003089static bool ValidateSizedGetUniform(Context *context,
3090 GLuint program,
3091 GLint location,
3092 GLsizei bufSize,
3093 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003094{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003095 if (length)
3096 {
3097 *length = 0;
3098 }
3099
Jamie Madill78f41802014-08-25 15:47:55 -04003100 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003101 {
Jamie Madill78f41802014-08-25 15:47:55 -04003102 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003103 }
3104
Geoff Langf41d0ee2016-10-07 13:04:23 -04003105 if (bufSize < 0)
3106 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003107 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003108 return false;
3109 }
3110
Jamie Madilla502c742014-08-28 17:19:13 -04003111 gl::Program *programObject = context->getProgram(program);
3112 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003113
Jamie Madill78f41802014-08-25 15:47:55 -04003114 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003115 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003116 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003117 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003118 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003119 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003120 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003121 }
3122
Geoff Langf41d0ee2016-10-07 13:04:23 -04003123 if (length)
3124 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003125 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003126 }
3127
Jamie Madill0063c512014-08-25 15:47:53 -04003128 return true;
3129}
3130
He Yunchaoced53ae2016-11-29 15:00:51 +08003131bool ValidateGetnUniformfvEXT(Context *context,
3132 GLuint program,
3133 GLint location,
3134 GLsizei bufSize,
3135 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003136{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003137 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003138}
3139
He Yunchaoced53ae2016-11-29 15:00:51 +08003140bool ValidateGetnUniformivEXT(Context *context,
3141 GLuint program,
3142 GLint location,
3143 GLsizei bufSize,
3144 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003145{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003146 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3147}
3148
3149bool ValidateGetUniformfvRobustANGLE(Context *context,
3150 GLuint program,
3151 GLint location,
3152 GLsizei bufSize,
3153 GLsizei *length,
3154 GLfloat *params)
3155{
3156 if (!ValidateRobustEntryPoint(context, bufSize))
3157 {
3158 return false;
3159 }
3160
3161 // bufSize is validated in ValidateSizedGetUniform
3162 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3163}
3164
3165bool ValidateGetUniformivRobustANGLE(Context *context,
3166 GLuint program,
3167 GLint location,
3168 GLsizei bufSize,
3169 GLsizei *length,
3170 GLint *params)
3171{
3172 if (!ValidateRobustEntryPoint(context, bufSize))
3173 {
3174 return false;
3175 }
3176
3177 // bufSize is validated in ValidateSizedGetUniform
3178 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3179}
3180
3181bool ValidateGetUniformuivRobustANGLE(Context *context,
3182 GLuint program,
3183 GLint location,
3184 GLsizei bufSize,
3185 GLsizei *length,
3186 GLuint *params)
3187{
3188 if (!ValidateRobustEntryPoint(context, bufSize))
3189 {
3190 return false;
3191 }
3192
3193 if (context->getClientMajorVersion() < 3)
3194 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003195 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003196 return false;
3197 }
3198
3199 // bufSize is validated in ValidateSizedGetUniform
3200 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003201}
3202
He Yunchaoced53ae2016-11-29 15:00:51 +08003203bool ValidateDiscardFramebufferBase(Context *context,
3204 GLenum target,
3205 GLsizei numAttachments,
3206 const GLenum *attachments,
3207 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003208{
3209 if (numAttachments < 0)
3210 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003211 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003212 return false;
3213 }
3214
3215 for (GLsizei i = 0; i < numAttachments; ++i)
3216 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003217 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003218 {
3219 if (defaultFramebuffer)
3220 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003221 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003222 return false;
3223 }
3224
3225 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3226 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003227 context->handleError(InvalidOperation() << "Requested color attachment is "
3228 "greater than the maximum supported "
3229 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003230 return false;
3231 }
3232 }
3233 else
3234 {
3235 switch (attachments[i])
3236 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003237 case GL_DEPTH_ATTACHMENT:
3238 case GL_STENCIL_ATTACHMENT:
3239 case GL_DEPTH_STENCIL_ATTACHMENT:
3240 if (defaultFramebuffer)
3241 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003242 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3243 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003244 return false;
3245 }
3246 break;
3247 case GL_COLOR:
3248 case GL_DEPTH:
3249 case GL_STENCIL:
3250 if (!defaultFramebuffer)
3251 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003252 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3253 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003254 return false;
3255 }
3256 break;
3257 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003258 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003259 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003260 }
3261 }
3262 }
3263
3264 return true;
3265}
3266
Austin Kinross6ee1e782015-05-29 17:05:37 -07003267bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3268{
Jamie Madill007530e2017-12-28 14:27:04 -05003269 if (!context->getExtensions().debugMarker)
3270 {
3271 // The debug marker calls should not set error state
3272 // However, it seems reasonable to set an error state if the extension is not enabled
3273 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3274 return false;
3275 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003276
Jamie Madill007530e2017-12-28 14:27:04 -05003277 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003278 if (length < 0)
3279 {
3280 return false;
3281 }
3282
3283 if (marker == nullptr)
3284 {
3285 return false;
3286 }
3287
3288 return true;
3289}
3290
3291bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3292{
Jamie Madill007530e2017-12-28 14:27:04 -05003293 if (!context->getExtensions().debugMarker)
3294 {
3295 // The debug marker calls should not set error state
3296 // However, it seems reasonable to set an error state if the extension is not enabled
3297 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3298 return false;
3299 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003300
Jamie Madill007530e2017-12-28 14:27:04 -05003301 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003302 if (length < 0)
3303 {
3304 return false;
3305 }
3306
3307 if (length > 0 && marker == nullptr)
3308 {
3309 return false;
3310 }
3311
3312 return true;
3313}
3314
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003315bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003316{
Geoff Langa8406172015-07-21 16:53:39 -04003317 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3318 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003319 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003320 return false;
3321 }
3322
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003323 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003324 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003325 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003326 if (!context->getExtensions().eglImage)
3327 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003328 context->handleError(InvalidEnum()
3329 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003330 }
3331 break;
3332
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003333 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003334 if (!context->getExtensions().eglImageExternal)
3335 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003336 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3337 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003338 }
Geoff Langa8406172015-07-21 16:53:39 -04003339 break;
3340
3341 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003342 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003343 return false;
3344 }
3345
Jamie Madill007530e2017-12-28 14:27:04 -05003346 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3347
Jamie Madill61e16b42017-06-19 11:13:23 -04003348 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003349 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003350 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003351 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003352 return false;
3353 }
3354
Jamie Madill007530e2017-12-28 14:27:04 -05003355 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003356 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003357 context->handleError(InvalidOperation()
3358 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003359 return false;
3360 }
3361
Geoff Langca271392017-04-05 12:30:00 -04003362 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003363 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003364 if (!textureCaps.texturable)
3365 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003366 context->handleError(InvalidOperation()
3367 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003368 return false;
3369 }
3370
Geoff Langdcab33b2015-07-21 13:03:16 -04003371 return true;
3372}
3373
3374bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003375 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003376 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003377{
Geoff Langa8406172015-07-21 16:53:39 -04003378 if (!context->getExtensions().eglImage)
3379 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003380 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003381 return false;
3382 }
3383
3384 switch (target)
3385 {
3386 case GL_RENDERBUFFER:
3387 break;
3388
3389 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003390 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003391 return false;
3392 }
3393
Jamie Madill007530e2017-12-28 14:27:04 -05003394 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3395
Jamie Madill61e16b42017-06-19 11:13:23 -04003396 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003397 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003398 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003399 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003400 return false;
3401 }
3402
Geoff Langca271392017-04-05 12:30:00 -04003403 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003404 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003405 if (!textureCaps.renderable)
3406 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003407 context->handleError(InvalidOperation()
3408 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003409 return false;
3410 }
3411
Geoff Langdcab33b2015-07-21 13:03:16 -04003412 return true;
3413}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003414
3415bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3416{
Geoff Lang36167ab2015-12-07 10:27:14 -05003417 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003418 {
3419 // The default VAO should always exist
3420 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003421 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003422 return false;
3423 }
3424
3425 return true;
3426}
3427
Geoff Langc5629752015-12-07 16:29:04 -05003428bool ValidateProgramBinaryBase(Context *context,
3429 GLuint program,
3430 GLenum binaryFormat,
3431 const void *binary,
3432 GLint length)
3433{
3434 Program *programObject = GetValidProgram(context, program);
3435 if (programObject == nullptr)
3436 {
3437 return false;
3438 }
3439
3440 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3441 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3442 programBinaryFormats.end())
3443 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003444 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003445 return false;
3446 }
3447
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003448 if (context->hasActiveTransformFeedback(program))
3449 {
3450 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003451 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3452 "is associated with an active transform "
3453 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003454 return false;
3455 }
3456
Geoff Langc5629752015-12-07 16:29:04 -05003457 return true;
3458}
3459
3460bool ValidateGetProgramBinaryBase(Context *context,
3461 GLuint program,
3462 GLsizei bufSize,
3463 GLsizei *length,
3464 GLenum *binaryFormat,
3465 void *binary)
3466{
3467 Program *programObject = GetValidProgram(context, program);
3468 if (programObject == nullptr)
3469 {
3470 return false;
3471 }
3472
3473 if (!programObject->isLinked())
3474 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003475 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003476 return false;
3477 }
3478
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003479 if (context->getCaps().programBinaryFormats.empty())
3480 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003481 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003482 return false;
3483 }
3484
Geoff Langc5629752015-12-07 16:29:04 -05003485 return true;
3486}
Jamie Madillc29968b2016-01-20 11:17:23 -05003487
Jamie Madill5b772312018-03-08 20:28:32 -05003488bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003489{
3490 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003491 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003492 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003493 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3494 return false;
3495 }
3496 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3497 {
3498 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003499 return false;
3500 }
3501
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003502 ASSERT(context->getGLState().getDrawFramebuffer());
3503 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003504 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3505
3506 // This should come first before the check for the default frame buffer
3507 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3508 // rather than INVALID_OPERATION
3509 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3510 {
3511 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3512
3513 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003514 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3515 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003516 {
3517 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003518 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3519 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3520 // 3.1 is still a bit ambiguous about the error, but future specs are
3521 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003522 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003523 return false;
3524 }
3525 else if (bufs[colorAttachment] >= maxColorAttachment)
3526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003527 context->handleError(InvalidOperation()
3528 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003529 return false;
3530 }
3531 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3532 frameBufferId != 0)
3533 {
3534 // INVALID_OPERATION-GL is bound to buffer and ith argument
3535 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003536 context->handleError(InvalidOperation()
3537 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003538 return false;
3539 }
3540 }
3541
3542 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3543 // and n is not 1 or bufs is bound to value other than BACK and NONE
3544 if (frameBufferId == 0)
3545 {
3546 if (n != 1)
3547 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003548 context->handleError(InvalidOperation()
3549 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003550 return false;
3551 }
3552
3553 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3554 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003555 context->handleError(
3556 InvalidOperation()
3557 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003558 return false;
3559 }
3560 }
3561
3562 return true;
3563}
3564
Geoff Lang496c02d2016-10-20 11:38:11 -07003565bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003566 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003567 GLenum pname,
3568 GLsizei *length,
3569 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003570{
Geoff Lang496c02d2016-10-20 11:38:11 -07003571 if (length)
3572 {
3573 *length = 0;
3574 }
3575
3576 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3577 {
3578 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003579 InvalidOperation()
3580 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003581 return false;
3582 }
3583
Corentin Walleze4477002017-12-01 14:39:58 -05003584 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003585 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003586 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003587 return false;
3588 }
3589
Geoff Lang496c02d2016-10-20 11:38:11 -07003590 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003591 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003592 case GL_BUFFER_MAP_POINTER:
3593 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003594
Geoff Lang496c02d2016-10-20 11:38:11 -07003595 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003596 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003597 return false;
3598 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003599
3600 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3601 // target bound to zero generate an INVALID_OPERATION error."
3602 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003603 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003604 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003605 context->handleError(InvalidOperation()
3606 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003607 return false;
3608 }
3609
Geoff Lang496c02d2016-10-20 11:38:11 -07003610 if (length)
3611 {
3612 *length = 1;
3613 }
3614
Olli Etuaho4f667482016-03-30 15:56:35 +03003615 return true;
3616}
3617
Corentin Wallez336129f2017-10-17 15:55:40 -04003618bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003619{
Corentin Walleze4477002017-12-01 14:39:58 -05003620 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003621 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003622 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003623 return false;
3624 }
3625
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003626 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003627
3628 if (buffer == nullptr || !buffer->isMapped())
3629 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003630 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003631 return false;
3632 }
3633
3634 return true;
3635}
3636
3637bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003638 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003639 GLintptr offset,
3640 GLsizeiptr length,
3641 GLbitfield access)
3642{
Corentin Walleze4477002017-12-01 14:39:58 -05003643 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003644 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003645 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003646 return false;
3647 }
3648
Brandon Jones6cad5662017-06-14 13:25:13 -07003649 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003650 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003651 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3652 return false;
3653 }
3654
3655 if (length < 0)
3656 {
3657 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003658 return false;
3659 }
3660
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003661 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003662
3663 if (!buffer)
3664 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003665 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003666 return false;
3667 }
3668
3669 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003670 CheckedNumeric<size_t> checkedOffset(offset);
3671 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003672
Jamie Madille2e406c2016-06-02 13:04:10 -04003673 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003674 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003675 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003676 return false;
3677 }
3678
3679 // Check for invalid bits in the mask
3680 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3681 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3682 GL_MAP_UNSYNCHRONIZED_BIT;
3683
3684 if (access & ~(allAccessBits))
3685 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003686 context->handleError(InvalidValue()
3687 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003688 return false;
3689 }
3690
3691 if (length == 0)
3692 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003693 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003694 return false;
3695 }
3696
3697 if (buffer->isMapped())
3698 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003699 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003700 return false;
3701 }
3702
3703 // Check for invalid bit combinations
3704 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3705 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003706 context->handleError(InvalidOperation()
3707 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003708 return false;
3709 }
3710
3711 GLbitfield writeOnlyBits =
3712 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3713
3714 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3715 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003716 context->handleError(InvalidOperation()
3717 << "Invalid access bits when mapping buffer for reading: 0x"
3718 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003719 return false;
3720 }
3721
3722 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003724 context->handleError(
3725 InvalidOperation()
3726 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003727 return false;
3728 }
Geoff Lang79f71042017-08-14 16:43:43 -04003729
3730 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003731}
3732
3733bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003734 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003735 GLintptr offset,
3736 GLsizeiptr length)
3737{
Brandon Jones6cad5662017-06-14 13:25:13 -07003738 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003739 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003740 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3741 return false;
3742 }
3743
3744 if (length < 0)
3745 {
3746 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003747 return false;
3748 }
3749
Corentin Walleze4477002017-12-01 14:39:58 -05003750 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003751 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003752 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003753 return false;
3754 }
3755
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003756 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003757
3758 if (buffer == nullptr)
3759 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003760 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003761 return false;
3762 }
3763
3764 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3765 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003766 context->handleError(InvalidOperation()
3767 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003768 return false;
3769 }
3770
3771 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003772 CheckedNumeric<size_t> checkedOffset(offset);
3773 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003774
Jamie Madille2e406c2016-06-02 13:04:10 -04003775 if (!checkedSize.IsValid() ||
3776 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003777 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003778 context->handleError(InvalidValue()
3779 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003780 return false;
3781 }
3782
3783 return true;
3784}
3785
Olli Etuaho41997e72016-03-10 13:38:39 +02003786bool ValidateGenOrDelete(Context *context, GLint n)
3787{
3788 if (n < 0)
3789 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003790 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003791 return false;
3792 }
3793 return true;
3794}
3795
Jamie Madill5b772312018-03-08 20:28:32 -05003796bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003797{
3798 if (!context->getExtensions().robustClientMemory)
3799 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003800 context->handleError(InvalidOperation()
3801 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003802 return false;
3803 }
3804
3805 if (bufSize < 0)
3806 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003807 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003808 return false;
3809 }
3810
3811 return true;
3812}
3813
Jamie Madill5b772312018-03-08 20:28:32 -05003814bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003815{
3816 if (bufSize < numParams)
3817 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003818 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3819 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003820 return false;
3821 }
3822
3823 return true;
3824}
3825
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003826bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04003827 GLenum target,
3828 GLenum attachment,
3829 GLenum pname,
3830 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003831{
Geoff Lange8afa902017-09-27 15:00:43 -04003832 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003833 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003834 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003835 return false;
3836 }
3837
3838 int clientVersion = context->getClientMajorVersion();
3839
3840 switch (pname)
3841 {
3842 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3843 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3844 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3845 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3846 break;
3847
Martin Radeve5285d22017-07-14 16:23:53 +03003848 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3849 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3850 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3851 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3852 if (clientVersion < 3 || !context->getExtensions().multiview)
3853 {
3854 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3855 return false;
3856 }
3857 break;
3858
Geoff Langff5b2d52016-09-07 11:32:23 -04003859 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3860 if (clientVersion < 3 && !context->getExtensions().sRGB)
3861 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003862 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003863 return false;
3864 }
3865 break;
3866
3867 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3868 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3869 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3870 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3871 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3872 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3873 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3874 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3875 if (clientVersion < 3)
3876 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003877 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003878 return false;
3879 }
3880 break;
3881
3882 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003883 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003884 return false;
3885 }
3886
3887 // Determine if the attachment is a valid enum
3888 switch (attachment)
3889 {
3890 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04003891 case GL_DEPTH:
3892 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04003893 if (clientVersion < 3)
3894 {
Geoff Langfa125c92017-10-24 13:01:46 -04003895 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003896 return false;
3897 }
3898 break;
3899
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003900 case GL_DEPTH_STENCIL_ATTACHMENT:
3901 if (clientVersion < 3 && !context->isWebGL1())
3902 {
3903 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3904 return false;
3905 }
3906 break;
3907
Geoff Langfa125c92017-10-24 13:01:46 -04003908 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003909 case GL_DEPTH_ATTACHMENT:
3910 case GL_STENCIL_ATTACHMENT:
3911 break;
3912
3913 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003914 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3915 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003916 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3917 {
Geoff Langfa125c92017-10-24 13:01:46 -04003918 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003919 return false;
3920 }
3921 break;
3922 }
3923
3924 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3925 ASSERT(framebuffer);
3926
3927 if (framebuffer->id() == 0)
3928 {
3929 if (clientVersion < 3)
3930 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003931 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003932 return false;
3933 }
3934
3935 switch (attachment)
3936 {
3937 case GL_BACK:
3938 case GL_DEPTH:
3939 case GL_STENCIL:
3940 break;
3941
3942 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003943 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003944 return false;
3945 }
3946 }
3947 else
3948 {
3949 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3950 {
3951 // Valid attachment query
3952 }
3953 else
3954 {
3955 switch (attachment)
3956 {
3957 case GL_DEPTH_ATTACHMENT:
3958 case GL_STENCIL_ATTACHMENT:
3959 break;
3960
3961 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003962 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04003963 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003964 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003965 return false;
3966 }
3967 break;
3968
3969 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003970 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003971 return false;
3972 }
3973 }
3974 }
3975
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003976 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003977 if (attachmentObject)
3978 {
3979 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3980 attachmentObject->type() == GL_TEXTURE ||
3981 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3982
3983 switch (pname)
3984 {
3985 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3986 if (attachmentObject->type() != GL_RENDERBUFFER &&
3987 attachmentObject->type() != GL_TEXTURE)
3988 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003989 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003990 return false;
3991 }
3992 break;
3993
3994 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3995 if (attachmentObject->type() != GL_TEXTURE)
3996 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003997 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003998 return false;
3999 }
4000 break;
4001
4002 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4003 if (attachmentObject->type() != GL_TEXTURE)
4004 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004005 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004006 return false;
4007 }
4008 break;
4009
4010 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4011 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4012 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004013 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004014 return false;
4015 }
4016 break;
4017
4018 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4019 if (attachmentObject->type() != GL_TEXTURE)
4020 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004021 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004022 return false;
4023 }
4024 break;
4025
4026 default:
4027 break;
4028 }
4029 }
4030 else
4031 {
4032 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4033 // is NONE, then querying any other pname will generate INVALID_ENUM.
4034
4035 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4036 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4037 // INVALID_OPERATION for all other pnames
4038
4039 switch (pname)
4040 {
4041 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4042 break;
4043
4044 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4045 if (clientVersion < 3)
4046 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004047 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004048 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004049 return false;
4050 }
4051 break;
4052
4053 default:
4054 if (clientVersion < 3)
4055 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004056 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004057 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004058 return false;
4059 }
4060 else
4061 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004062 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004063 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004064 return false;
4065 }
4066 }
4067 }
4068
Martin Radeve5285d22017-07-14 16:23:53 +03004069 if (numParams)
4070 {
4071 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4072 {
4073 // Only when the viewport offsets are queried we can have a varying number of output
4074 // parameters.
4075 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4076 *numParams = numViews * 2;
4077 }
4078 else
4079 {
4080 // For all other queries we can have only one output parameter.
4081 *numParams = 1;
4082 }
4083 }
4084
Geoff Langff5b2d52016-09-07 11:32:23 -04004085 return true;
4086}
4087
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004088bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004089 GLenum target,
4090 GLenum attachment,
4091 GLenum pname,
4092 GLsizei bufSize,
4093 GLsizei *numParams)
4094{
4095 if (!ValidateRobustEntryPoint(context, bufSize))
4096 {
4097 return false;
4098 }
4099
Jamie Madillbe849e42017-05-02 15:49:00 -04004100 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4101 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004102 {
4103 return false;
4104 }
4105
4106 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4107 {
4108 return false;
4109 }
4110
4111 return true;
4112}
4113
Jamie Madill5b772312018-03-08 20:28:32 -05004114bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004115 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004116 GLenum pname,
4117 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004118 GLsizei *length,
4119 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004120{
4121 if (!ValidateRobustEntryPoint(context, bufSize))
4122 {
4123 return false;
4124 }
4125
Geoff Langebebe1c2016-10-14 12:01:31 -04004126 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004127 {
4128 return false;
4129 }
4130
Geoff Langebebe1c2016-10-14 12:01:31 -04004131 if (!ValidateRobustBufferSize(context, bufSize, *length))
4132 {
4133 return false;
4134 }
4135
4136 return true;
4137}
4138
Jamie Madill5b772312018-03-08 20:28:32 -05004139bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004140 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004141 GLenum pname,
4142 GLsizei bufSize,
4143 GLsizei *length,
4144 GLint64 *params)
4145{
4146 if (!ValidateRobustEntryPoint(context, bufSize))
4147 {
4148 return false;
4149 }
4150
4151 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4152 {
4153 return false;
4154 }
4155
4156 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004157 {
4158 return false;
4159 }
4160
4161 return true;
4162}
4163
Jamie Madill5b772312018-03-08 20:28:32 -05004164bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004165{
4166 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004167 if (numParams)
4168 {
4169 *numParams = 1;
4170 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004171
4172 Program *programObject = GetValidProgram(context, program);
4173 if (!programObject)
4174 {
4175 return false;
4176 }
4177
4178 switch (pname)
4179 {
4180 case GL_DELETE_STATUS:
4181 case GL_LINK_STATUS:
4182 case GL_VALIDATE_STATUS:
4183 case GL_INFO_LOG_LENGTH:
4184 case GL_ATTACHED_SHADERS:
4185 case GL_ACTIVE_ATTRIBUTES:
4186 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4187 case GL_ACTIVE_UNIFORMS:
4188 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4189 break;
4190
4191 case GL_PROGRAM_BINARY_LENGTH:
4192 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4193 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004194 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4195 "requires GL_OES_get_program_binary or "
4196 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004197 return false;
4198 }
4199 break;
4200
4201 case GL_ACTIVE_UNIFORM_BLOCKS:
4202 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4203 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4204 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4205 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4206 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4207 if (context->getClientMajorVersion() < 3)
4208 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004209 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004210 return false;
4211 }
4212 break;
4213
Yunchao He61afff12017-03-14 15:34:03 +08004214 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004215 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004216 if (context->getClientVersion() < Version(3, 1))
4217 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004218 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004219 return false;
4220 }
4221 break;
4222
Jiawei Shao6ae51612018-02-23 14:03:25 +08004223 case GL_COMPUTE_WORK_GROUP_SIZE:
4224 if (context->getClientVersion() < Version(3, 1))
4225 {
4226 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4227 return false;
4228 }
4229
4230 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4231 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4232 // program which has not been linked successfully, or which does not contain objects to
4233 // form a compute shader.
4234 if (!programObject->isLinked())
4235 {
4236 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4237 return false;
4238 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004239 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004240 {
4241 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4242 return false;
4243 }
4244 break;
4245
Jiawei Shao447bfac2018-03-14 14:23:40 +08004246 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4247 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4248 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4249 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4250 if (!context->getExtensions().geometryShader)
4251 {
4252 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4253 return false;
4254 }
4255
4256 // [EXT_geometry_shader] Chapter 7.12
4257 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4258 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4259 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4260 // successfully, or which does not contain objects to form a geometry shader.
4261 if (!programObject->isLinked())
4262 {
4263 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4264 return false;
4265 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004266 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004267 {
4268 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4269 return false;
4270 }
4271 break;
4272
Geoff Langff5b2d52016-09-07 11:32:23 -04004273 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004274 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004275 return false;
4276 }
4277
4278 return true;
4279}
4280
4281bool ValidateGetProgramivRobustANGLE(Context *context,
4282 GLuint program,
4283 GLenum pname,
4284 GLsizei bufSize,
4285 GLsizei *numParams)
4286{
4287 if (!ValidateRobustEntryPoint(context, bufSize))
4288 {
4289 return false;
4290 }
4291
Jamie Madillbe849e42017-05-02 15:49:00 -04004292 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004293 {
4294 return false;
4295 }
4296
4297 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4298 {
4299 return false;
4300 }
4301
4302 return true;
4303}
4304
Geoff Lang740d9022016-10-07 11:20:52 -04004305bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4306 GLenum target,
4307 GLenum pname,
4308 GLsizei bufSize,
4309 GLsizei *length,
4310 GLint *params)
4311{
4312 if (!ValidateRobustEntryPoint(context, bufSize))
4313 {
4314 return false;
4315 }
4316
4317 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4318 {
4319 return false;
4320 }
4321
4322 if (!ValidateRobustBufferSize(context, bufSize, *length))
4323 {
4324 return false;
4325 }
4326
4327 return true;
4328}
4329
Geoff Langd7d0ed32016-10-07 11:33:51 -04004330bool ValidateGetShaderivRobustANGLE(Context *context,
4331 GLuint shader,
4332 GLenum pname,
4333 GLsizei bufSize,
4334 GLsizei *length,
4335 GLint *params)
4336{
4337 if (!ValidateRobustEntryPoint(context, bufSize))
4338 {
4339 return false;
4340 }
4341
4342 if (!ValidateGetShaderivBase(context, shader, pname, length))
4343 {
4344 return false;
4345 }
4346
4347 if (!ValidateRobustBufferSize(context, bufSize, *length))
4348 {
4349 return false;
4350 }
4351
4352 return true;
4353}
4354
Geoff Langc1984ed2016-10-07 12:41:00 -04004355bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004356 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004357 GLenum pname,
4358 GLsizei bufSize,
4359 GLsizei *length,
4360 GLfloat *params)
4361{
4362 if (!ValidateRobustEntryPoint(context, bufSize))
4363 {
4364 return false;
4365 }
4366
4367 if (!ValidateGetTexParameterBase(context, target, pname, length))
4368 {
4369 return false;
4370 }
4371
4372 if (!ValidateRobustBufferSize(context, bufSize, *length))
4373 {
4374 return false;
4375 }
4376
4377 return true;
4378}
4379
Geoff Langc1984ed2016-10-07 12:41:00 -04004380bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004381 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004382 GLenum pname,
4383 GLsizei bufSize,
4384 GLsizei *length,
4385 GLint *params)
4386{
4387 if (!ValidateRobustEntryPoint(context, bufSize))
4388 {
4389 return false;
4390 }
4391
4392 if (!ValidateGetTexParameterBase(context, target, pname, length))
4393 {
4394 return false;
4395 }
4396
4397 if (!ValidateRobustBufferSize(context, bufSize, *length))
4398 {
4399 return false;
4400 }
4401
4402 return true;
4403}
4404
Geoff Langc1984ed2016-10-07 12:41:00 -04004405bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004406 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004407 GLenum pname,
4408 GLsizei bufSize,
4409 const GLfloat *params)
4410{
4411 if (!ValidateRobustEntryPoint(context, bufSize))
4412 {
4413 return false;
4414 }
4415
4416 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4417}
4418
Geoff Langc1984ed2016-10-07 12:41:00 -04004419bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004420 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004421 GLenum pname,
4422 GLsizei bufSize,
4423 const GLint *params)
4424{
4425 if (!ValidateRobustEntryPoint(context, bufSize))
4426 {
4427 return false;
4428 }
4429
4430 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4431}
4432
Geoff Langc1984ed2016-10-07 12:41:00 -04004433bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4434 GLuint sampler,
4435 GLenum pname,
4436 GLuint bufSize,
4437 GLsizei *length,
4438 GLfloat *params)
4439{
4440 if (!ValidateRobustEntryPoint(context, bufSize))
4441 {
4442 return false;
4443 }
4444
4445 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4446 {
4447 return false;
4448 }
4449
4450 if (!ValidateRobustBufferSize(context, bufSize, *length))
4451 {
4452 return false;
4453 }
4454
4455 return true;
4456}
4457
Geoff Langc1984ed2016-10-07 12:41:00 -04004458bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4459 GLuint sampler,
4460 GLenum pname,
4461 GLuint bufSize,
4462 GLsizei *length,
4463 GLint *params)
4464{
4465 if (!ValidateRobustEntryPoint(context, bufSize))
4466 {
4467 return false;
4468 }
4469
4470 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4471 {
4472 return false;
4473 }
4474
4475 if (!ValidateRobustBufferSize(context, bufSize, *length))
4476 {
4477 return false;
4478 }
4479
4480 return true;
4481}
4482
Geoff Langc1984ed2016-10-07 12:41:00 -04004483bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4484 GLuint sampler,
4485 GLenum pname,
4486 GLsizei bufSize,
4487 const GLfloat *params)
4488{
4489 if (!ValidateRobustEntryPoint(context, bufSize))
4490 {
4491 return false;
4492 }
4493
4494 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4495}
4496
Geoff Langc1984ed2016-10-07 12:41:00 -04004497bool ValidateSamplerParameterivRobustANGLE(Context *context,
4498 GLuint sampler,
4499 GLenum pname,
4500 GLsizei bufSize,
4501 const GLint *params)
4502{
4503 if (!ValidateRobustEntryPoint(context, bufSize))
4504 {
4505 return false;
4506 }
4507
4508 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4509}
4510
Geoff Lang0b031062016-10-13 14:30:04 -04004511bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4512 GLuint index,
4513 GLenum pname,
4514 GLsizei bufSize,
4515 GLsizei *length,
4516 GLfloat *params)
4517{
4518 if (!ValidateRobustEntryPoint(context, bufSize))
4519 {
4520 return false;
4521 }
4522
4523 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4524 {
4525 return false;
4526 }
4527
4528 if (!ValidateRobustBufferSize(context, bufSize, *length))
4529 {
4530 return false;
4531 }
4532
4533 return true;
4534}
4535
Geoff Lang0b031062016-10-13 14:30:04 -04004536bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4537 GLuint index,
4538 GLenum pname,
4539 GLsizei bufSize,
4540 GLsizei *length,
4541 GLint *params)
4542{
4543 if (!ValidateRobustEntryPoint(context, bufSize))
4544 {
4545 return false;
4546 }
4547
4548 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4549 {
4550 return false;
4551 }
4552
4553 if (!ValidateRobustBufferSize(context, bufSize, *length))
4554 {
4555 return false;
4556 }
4557
4558 return true;
4559}
4560
Geoff Lang0b031062016-10-13 14:30:04 -04004561bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4562 GLuint index,
4563 GLenum pname,
4564 GLsizei bufSize,
4565 GLsizei *length,
4566 void **pointer)
4567{
4568 if (!ValidateRobustEntryPoint(context, bufSize))
4569 {
4570 return false;
4571 }
4572
4573 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4574 {
4575 return false;
4576 }
4577
4578 if (!ValidateRobustBufferSize(context, bufSize, *length))
4579 {
4580 return false;
4581 }
4582
4583 return true;
4584}
4585
Geoff Lang0b031062016-10-13 14:30:04 -04004586bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4587 GLuint index,
4588 GLenum pname,
4589 GLsizei bufSize,
4590 GLsizei *length,
4591 GLint *params)
4592{
4593 if (!ValidateRobustEntryPoint(context, bufSize))
4594 {
4595 return false;
4596 }
4597
4598 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4599 {
4600 return false;
4601 }
4602
4603 if (!ValidateRobustBufferSize(context, bufSize, *length))
4604 {
4605 return false;
4606 }
4607
4608 return true;
4609}
4610
Geoff Lang0b031062016-10-13 14:30:04 -04004611bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4612 GLuint index,
4613 GLenum pname,
4614 GLsizei bufSize,
4615 GLsizei *length,
4616 GLuint *params)
4617{
4618 if (!ValidateRobustEntryPoint(context, bufSize))
4619 {
4620 return false;
4621 }
4622
4623 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4624 {
4625 return false;
4626 }
4627
4628 if (!ValidateRobustBufferSize(context, bufSize, *length))
4629 {
4630 return false;
4631 }
4632
4633 return true;
4634}
4635
Geoff Lang6899b872016-10-14 11:30:13 -04004636bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4637 GLuint program,
4638 GLuint uniformBlockIndex,
4639 GLenum pname,
4640 GLsizei bufSize,
4641 GLsizei *length,
4642 GLint *params)
4643{
4644 if (!ValidateRobustEntryPoint(context, bufSize))
4645 {
4646 return false;
4647 }
4648
4649 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4650 {
4651 return false;
4652 }
4653
4654 if (!ValidateRobustBufferSize(context, bufSize, *length))
4655 {
4656 return false;
4657 }
4658
4659 return true;
4660}
4661
Geoff Lang0a9661f2016-10-20 10:59:20 -07004662bool ValidateGetInternalFormativRobustANGLE(Context *context,
4663 GLenum target,
4664 GLenum internalformat,
4665 GLenum pname,
4666 GLsizei bufSize,
4667 GLsizei *length,
4668 GLint *params)
4669{
4670 if (!ValidateRobustEntryPoint(context, bufSize))
4671 {
4672 return false;
4673 }
4674
4675 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4676 {
4677 return false;
4678 }
4679
4680 if (!ValidateRobustBufferSize(context, bufSize, *length))
4681 {
4682 return false;
4683 }
4684
4685 return true;
4686}
4687
Jamie Madill5b772312018-03-08 20:28:32 -05004688bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08004689 GLuint attribIndex,
4690 GLint size,
4691 GLenum type,
4692 GLboolean pureInteger)
4693{
4694 const Caps &caps = context->getCaps();
4695 if (attribIndex >= caps.maxVertexAttributes)
4696 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004697 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004698 return false;
4699 }
4700
4701 if (size < 1 || size > 4)
4702 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004703 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004704 return false;
Shao80957d92017-02-20 21:25:59 +08004705 }
4706
4707 switch (type)
4708 {
4709 case GL_BYTE:
4710 case GL_UNSIGNED_BYTE:
4711 case GL_SHORT:
4712 case GL_UNSIGNED_SHORT:
4713 break;
4714
4715 case GL_INT:
4716 case GL_UNSIGNED_INT:
4717 if (context->getClientMajorVersion() < 3)
4718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004719 context->handleError(InvalidEnum()
4720 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004721 return false;
4722 }
4723 break;
4724
4725 case GL_FIXED:
4726 case GL_FLOAT:
4727 if (pureInteger)
4728 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004729 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004730 return false;
4731 }
4732 break;
4733
4734 case GL_HALF_FLOAT:
4735 if (context->getClientMajorVersion() < 3)
4736 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004737 context->handleError(InvalidEnum()
4738 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004739 return false;
4740 }
4741 if (pureInteger)
4742 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004743 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004744 return false;
4745 }
4746 break;
4747
4748 case GL_INT_2_10_10_10_REV:
4749 case GL_UNSIGNED_INT_2_10_10_10_REV:
4750 if (context->getClientMajorVersion() < 3)
4751 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004752 context->handleError(InvalidEnum()
4753 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004754 return false;
4755 }
4756 if (pureInteger)
4757 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004758 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004759 return false;
4760 }
4761 if (size != 4)
4762 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004763 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4764 "UNSIGNED_INT_2_10_10_10_REV and "
4765 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004766 return false;
4767 }
4768 break;
4769
4770 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004771 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004772 return false;
4773 }
4774
4775 return true;
4776}
4777
Geoff Lang76e65652017-03-27 14:58:02 -04004778// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4779// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4780// specified clear value and the type of a buffer that is being cleared generates an
4781// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05004782bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04004783 GLint drawbuffer,
4784 const GLenum *validComponentTypes,
4785 size_t validComponentTypeCount)
4786{
4787 const FramebufferAttachment *attachment =
4788 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4789 if (attachment)
4790 {
4791 GLenum componentType = attachment->getFormat().info->componentType;
4792 const GLenum *end = validComponentTypes + validComponentTypeCount;
4793 if (std::find(validComponentTypes, end, componentType) == end)
4794 {
4795 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004796 InvalidOperation()
4797 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004798 return false;
4799 }
4800 }
4801
4802 return true;
4803}
4804
Jamie Madill5b772312018-03-08 20:28:32 -05004805bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04004806{
4807 if (!ValidateRobustEntryPoint(context, dataSize))
4808 {
4809 return false;
4810 }
4811
Corentin Wallez336129f2017-10-17 15:55:40 -04004812 gl::Buffer *pixelUnpackBuffer =
4813 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004814 if (pixelUnpackBuffer == nullptr)
4815 {
4816 if (dataSize < imageSize)
4817 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004818 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004819 }
4820 }
4821 return true;
4822}
4823
Jamie Madill5b772312018-03-08 20:28:32 -05004824bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004825 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004826 GLenum pname,
4827 bool pointerVersion,
4828 GLsizei *numParams)
4829{
4830 if (numParams)
4831 {
4832 *numParams = 0;
4833 }
4834
Corentin Walleze4477002017-12-01 14:39:58 -05004835 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004836 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004837 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004838 return false;
4839 }
4840
4841 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4842 if (!buffer)
4843 {
4844 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004845 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004846 return false;
4847 }
4848
4849 const Extensions &extensions = context->getExtensions();
4850
4851 switch (pname)
4852 {
4853 case GL_BUFFER_USAGE:
4854 case GL_BUFFER_SIZE:
4855 break;
4856
4857 case GL_BUFFER_ACCESS_OES:
4858 if (!extensions.mapBuffer)
4859 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004860 context->handleError(InvalidEnum()
4861 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004862 return false;
4863 }
4864 break;
4865
4866 case GL_BUFFER_MAPPED:
4867 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4868 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4869 !extensions.mapBufferRange)
4870 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004871 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4872 "GL_OES_mapbuffer or "
4873 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004874 return false;
4875 }
4876 break;
4877
4878 case GL_BUFFER_MAP_POINTER:
4879 if (!pointerVersion)
4880 {
4881 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004882 InvalidEnum()
4883 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004884 return false;
4885 }
4886 break;
4887
4888 case GL_BUFFER_ACCESS_FLAGS:
4889 case GL_BUFFER_MAP_OFFSET:
4890 case GL_BUFFER_MAP_LENGTH:
4891 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4892 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004893 context->handleError(InvalidEnum()
4894 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004895 return false;
4896 }
4897 break;
4898
4899 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004900 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004901 return false;
4902 }
4903
4904 // All buffer parameter queries return one value.
4905 if (numParams)
4906 {
4907 *numParams = 1;
4908 }
4909
4910 return true;
4911}
4912
4913bool ValidateGetRenderbufferParameterivBase(Context *context,
4914 GLenum target,
4915 GLenum pname,
4916 GLsizei *length)
4917{
4918 if (length)
4919 {
4920 *length = 0;
4921 }
4922
4923 if (target != GL_RENDERBUFFER)
4924 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004925 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004926 return false;
4927 }
4928
4929 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4930 if (renderbuffer == nullptr)
4931 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004932 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004933 return false;
4934 }
4935
4936 switch (pname)
4937 {
4938 case GL_RENDERBUFFER_WIDTH:
4939 case GL_RENDERBUFFER_HEIGHT:
4940 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4941 case GL_RENDERBUFFER_RED_SIZE:
4942 case GL_RENDERBUFFER_GREEN_SIZE:
4943 case GL_RENDERBUFFER_BLUE_SIZE:
4944 case GL_RENDERBUFFER_ALPHA_SIZE:
4945 case GL_RENDERBUFFER_DEPTH_SIZE:
4946 case GL_RENDERBUFFER_STENCIL_SIZE:
4947 break;
4948
4949 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4950 if (!context->getExtensions().framebufferMultisample)
4951 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004952 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004953 return false;
4954 }
4955 break;
4956
4957 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004958 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004959 return false;
4960 }
4961
4962 if (length)
4963 {
4964 *length = 1;
4965 }
4966 return true;
4967}
4968
4969bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4970{
4971 if (length)
4972 {
4973 *length = 0;
4974 }
4975
4976 if (GetValidShader(context, shader) == nullptr)
4977 {
4978 return false;
4979 }
4980
4981 switch (pname)
4982 {
4983 case GL_SHADER_TYPE:
4984 case GL_DELETE_STATUS:
4985 case GL_COMPILE_STATUS:
4986 case GL_INFO_LOG_LENGTH:
4987 case GL_SHADER_SOURCE_LENGTH:
4988 break;
4989
4990 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4991 if (!context->getExtensions().translatedShaderSource)
4992 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004993 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004994 return false;
4995 }
4996 break;
4997
4998 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004999 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005000 return false;
5001 }
5002
5003 if (length)
5004 {
5005 *length = 1;
5006 }
5007 return true;
5008}
5009
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005010bool ValidateGetTexParameterBase(Context *context,
5011 TextureType target,
5012 GLenum pname,
5013 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005014{
5015 if (length)
5016 {
5017 *length = 0;
5018 }
5019
5020 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5021 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005022 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005023 return false;
5024 }
5025
5026 if (context->getTargetTexture(target) == nullptr)
5027 {
5028 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005029 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005030 return false;
5031 }
5032
5033 switch (pname)
5034 {
5035 case GL_TEXTURE_MAG_FILTER:
5036 case GL_TEXTURE_MIN_FILTER:
5037 case GL_TEXTURE_WRAP_S:
5038 case GL_TEXTURE_WRAP_T:
5039 break;
5040
5041 case GL_TEXTURE_USAGE_ANGLE:
5042 if (!context->getExtensions().textureUsage)
5043 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005044 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005045 return false;
5046 }
5047 break;
5048
5049 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005050 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005051 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005052 return false;
5053 }
5054 break;
5055
5056 case GL_TEXTURE_IMMUTABLE_FORMAT:
5057 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5058 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005059 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005060 return false;
5061 }
5062 break;
5063
5064 case GL_TEXTURE_WRAP_R:
5065 case GL_TEXTURE_IMMUTABLE_LEVELS:
5066 case GL_TEXTURE_SWIZZLE_R:
5067 case GL_TEXTURE_SWIZZLE_G:
5068 case GL_TEXTURE_SWIZZLE_B:
5069 case GL_TEXTURE_SWIZZLE_A:
5070 case GL_TEXTURE_BASE_LEVEL:
5071 case GL_TEXTURE_MAX_LEVEL:
5072 case GL_TEXTURE_MIN_LOD:
5073 case GL_TEXTURE_MAX_LOD:
5074 case GL_TEXTURE_COMPARE_MODE:
5075 case GL_TEXTURE_COMPARE_FUNC:
5076 if (context->getClientMajorVersion() < 3)
5077 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005078 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005079 return false;
5080 }
5081 break;
5082
5083 case GL_TEXTURE_SRGB_DECODE_EXT:
5084 if (!context->getExtensions().textureSRGBDecode)
5085 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005086 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005087 return false;
5088 }
5089 break;
5090
Yunchao Hebacaa712018-01-30 14:01:39 +08005091 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5092 if (context->getClientVersion() < Version(3, 1))
5093 {
5094 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5095 return false;
5096 }
5097 break;
5098
Jamie Madillbe849e42017-05-02 15:49:00 -04005099 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005100 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005101 return false;
5102 }
5103
5104 if (length)
5105 {
5106 *length = 1;
5107 }
5108 return true;
5109}
5110
5111bool ValidateGetVertexAttribBase(Context *context,
5112 GLuint index,
5113 GLenum pname,
5114 GLsizei *length,
5115 bool pointer,
5116 bool pureIntegerEntryPoint)
5117{
5118 if (length)
5119 {
5120 *length = 0;
5121 }
5122
5123 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5124 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005125 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005126 return false;
5127 }
5128
5129 if (index >= context->getCaps().maxVertexAttributes)
5130 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005131 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005132 return false;
5133 }
5134
5135 if (pointer)
5136 {
5137 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5138 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005139 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005140 return false;
5141 }
5142 }
5143 else
5144 {
5145 switch (pname)
5146 {
5147 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5148 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5149 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5150 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5151 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5152 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5153 case GL_CURRENT_VERTEX_ATTRIB:
5154 break;
5155
5156 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5157 static_assert(
5158 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5159 "ANGLE extension enums not equal to GL enums.");
5160 if (context->getClientMajorVersion() < 3 &&
5161 !context->getExtensions().instancedArrays)
5162 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005163 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5164 "requires OpenGL ES 3.0 or "
5165 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005166 return false;
5167 }
5168 break;
5169
5170 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5171 if (context->getClientMajorVersion() < 3)
5172 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005173 context->handleError(
5174 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005175 return false;
5176 }
5177 break;
5178
5179 case GL_VERTEX_ATTRIB_BINDING:
5180 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5181 if (context->getClientVersion() < ES_3_1)
5182 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005183 context->handleError(InvalidEnum()
5184 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005185 return false;
5186 }
5187 break;
5188
5189 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005190 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005191 return false;
5192 }
5193 }
5194
5195 if (length)
5196 {
5197 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5198 {
5199 *length = 4;
5200 }
5201 else
5202 {
5203 *length = 1;
5204 }
5205 }
5206
5207 return true;
5208}
5209
Jamie Madill4928b7c2017-06-20 12:57:39 -04005210bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005211 GLint x,
5212 GLint y,
5213 GLsizei width,
5214 GLsizei height,
5215 GLenum format,
5216 GLenum type,
5217 GLsizei bufSize,
5218 GLsizei *length,
5219 GLsizei *columns,
5220 GLsizei *rows,
5221 void *pixels)
5222{
5223 if (length != nullptr)
5224 {
5225 *length = 0;
5226 }
5227 if (rows != nullptr)
5228 {
5229 *rows = 0;
5230 }
5231 if (columns != nullptr)
5232 {
5233 *columns = 0;
5234 }
5235
5236 if (width < 0 || height < 0)
5237 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005238 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005239 return false;
5240 }
5241
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005242 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005243
Jamie Madille98b1b52018-03-08 09:47:23 -05005244 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madillbe849e42017-05-02 15:49:00 -04005245 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005246 return false;
5247 }
5248
Jamie Madille98b1b52018-03-08 09:47:23 -05005249 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005250 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005251 return false;
5252 }
5253
Jamie Madill690c8eb2018-03-12 15:20:03 -04005254 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005255 ASSERT(framebuffer);
5256
5257 if (framebuffer->getReadBufferState() == GL_NONE)
5258 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005259 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005260 return false;
5261 }
5262
5263 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5264 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5265 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5266 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5267 // situation is an application error that would lead to a crash in ANGLE.
5268 if (readBuffer == nullptr)
5269 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005270 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005271 return false;
5272 }
5273
Martin Radev28031682017-07-28 14:47:56 +03005274 // ANGLE_multiview, Revision 1:
5275 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5276 // current read framebuffer is not NONE.
5277 if (readBuffer->getMultiviewLayout() != GL_NONE)
5278 {
5279 context->handleError(InvalidFramebufferOperation()
5280 << "Attempting to read from a multi-view framebuffer.");
5281 return false;
5282 }
5283
Geoff Lang280ba992017-04-18 16:30:58 -04005284 if (context->getExtensions().webglCompatibility)
5285 {
5286 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5287 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5288 // and type before validating the combination of format and type. However, the
5289 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5290 // verifies that GL_INVALID_OPERATION is generated.
5291 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5292 // dEQP/WebGL.
5293 if (!ValidReadPixelsFormatEnum(context, format))
5294 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005295 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005296 return false;
5297 }
5298
5299 if (!ValidReadPixelsTypeEnum(context, type))
5300 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005301 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005302 return false;
5303 }
5304 }
5305
Jamie Madill690c8eb2018-03-12 15:20:03 -04005306 GLenum currentFormat = GL_NONE;
5307 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5308
5309 GLenum currentType = GL_NONE;
5310 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5311
Jamie Madillbe849e42017-05-02 15:49:00 -04005312 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5313
5314 bool validFormatTypeCombination =
5315 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5316
5317 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5318 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005319 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005320 return false;
5321 }
5322
5323 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005324 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005325 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5326 {
5327 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005328 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005329 return false;
5330 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005331 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5332 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5333 {
5334 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5335 return false;
5336 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005337
5338 // .. the data would be packed to the buffer object such that the memory writes required
5339 // would exceed the data store size.
5340 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5341 const gl::Extents size(width, height, 1);
5342 const auto &pack = context->getGLState().getPackState();
5343
5344 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5345 if (endByteOrErr.isError())
5346 {
5347 context->handleError(endByteOrErr.getError());
5348 return false;
5349 }
5350
5351 size_t endByte = endByteOrErr.getResult();
5352 if (bufSize >= 0)
5353 {
5354 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5355 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005356 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005357 return false;
5358 }
5359 }
5360
5361 if (pixelPackBuffer != nullptr)
5362 {
5363 CheckedNumeric<size_t> checkedEndByte(endByte);
5364 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5365 checkedEndByte += checkedOffset;
5366
5367 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5368 {
5369 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005370 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005371 return false;
5372 }
5373 }
5374
5375 if (pixelPackBuffer == nullptr && length != nullptr)
5376 {
5377 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5378 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005379 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005380 return false;
5381 }
5382
5383 *length = static_cast<GLsizei>(endByte);
5384 }
5385
Geoff Langa953b522018-02-21 16:56:23 -05005386 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005387 angle::CheckedNumeric<int> clippedExtent(length);
5388 if (start < 0)
5389 {
5390 // "subtract" the area that is less than 0
5391 clippedExtent += start;
5392 }
5393
Geoff Langa953b522018-02-21 16:56:23 -05005394 angle::CheckedNumeric<int> readExtent = start;
5395 readExtent += length;
5396 if (!readExtent.IsValid())
5397 {
5398 return false;
5399 }
5400
5401 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005402 {
5403 // Subtract the region to the right of the read buffer
5404 clippedExtent -= (readExtent - bufferSize);
5405 }
5406
5407 if (!clippedExtent.IsValid())
5408 {
Geoff Langa953b522018-02-21 16:56:23 -05005409 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005410 }
5411
Geoff Langa953b522018-02-21 16:56:23 -05005412 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5413 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005414 };
5415
Geoff Langa953b522018-02-21 16:56:23 -05005416 GLsizei writtenColumns = 0;
5417 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5418 {
5419 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5420 return false;
5421 }
5422
5423 GLsizei writtenRows = 0;
5424 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5425 {
5426 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5427 return false;
5428 }
5429
Jamie Madillbe849e42017-05-02 15:49:00 -04005430 if (columns != nullptr)
5431 {
Geoff Langa953b522018-02-21 16:56:23 -05005432 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005433 }
5434
5435 if (rows != nullptr)
5436 {
Geoff Langa953b522018-02-21 16:56:23 -05005437 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005438 }
5439
5440 return true;
5441}
5442
5443template <typename ParamType>
5444bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005445 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005446 GLenum pname,
5447 GLsizei bufSize,
5448 const ParamType *params)
5449{
5450 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5451 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005452 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005453 return false;
5454 }
5455
5456 if (context->getTargetTexture(target) == nullptr)
5457 {
5458 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005459 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005460 return false;
5461 }
5462
5463 const GLsizei minBufSize = 1;
5464 if (bufSize >= 0 && bufSize < minBufSize)
5465 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005466 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005467 return false;
5468 }
5469
5470 switch (pname)
5471 {
5472 case GL_TEXTURE_WRAP_R:
5473 case GL_TEXTURE_SWIZZLE_R:
5474 case GL_TEXTURE_SWIZZLE_G:
5475 case GL_TEXTURE_SWIZZLE_B:
5476 case GL_TEXTURE_SWIZZLE_A:
5477 case GL_TEXTURE_BASE_LEVEL:
5478 case GL_TEXTURE_MAX_LEVEL:
5479 case GL_TEXTURE_COMPARE_MODE:
5480 case GL_TEXTURE_COMPARE_FUNC:
5481 case GL_TEXTURE_MIN_LOD:
5482 case GL_TEXTURE_MAX_LOD:
5483 if (context->getClientMajorVersion() < 3)
5484 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005485 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005486 return false;
5487 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005488 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005489 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005490 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5491 "available without "
5492 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005493 return false;
5494 }
5495 break;
5496
5497 default:
5498 break;
5499 }
5500
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005501 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005502 {
5503 switch (pname)
5504 {
5505 case GL_TEXTURE_MIN_FILTER:
5506 case GL_TEXTURE_MAG_FILTER:
5507 case GL_TEXTURE_WRAP_S:
5508 case GL_TEXTURE_WRAP_T:
5509 case GL_TEXTURE_WRAP_R:
5510 case GL_TEXTURE_MIN_LOD:
5511 case GL_TEXTURE_MAX_LOD:
5512 case GL_TEXTURE_COMPARE_MODE:
5513 case GL_TEXTURE_COMPARE_FUNC:
5514 context->handleError(InvalidEnum()
5515 << "Invalid parameter for 2D multisampled textures.");
5516 return false;
5517 }
5518 }
5519
Jamie Madillbe849e42017-05-02 15:49:00 -04005520 switch (pname)
5521 {
5522 case GL_TEXTURE_WRAP_S:
5523 case GL_TEXTURE_WRAP_T:
5524 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005525 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005526 bool restrictedWrapModes =
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005527 target == TextureType::External || target == TextureType::Rectangle;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005528 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5529 {
5530 return false;
5531 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005532 }
5533 break;
5534
5535 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005536 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005537 bool restrictedMinFilter =
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005538 target == TextureType::External || target == TextureType::Rectangle;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005539 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5540 {
5541 return false;
5542 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005543 }
5544 break;
5545
5546 case GL_TEXTURE_MAG_FILTER:
5547 if (!ValidateTextureMagFilterValue(context, params))
5548 {
5549 return false;
5550 }
5551 break;
5552
5553 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005554 if (!context->getExtensions().textureUsage)
5555 {
5556 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5557 return false;
5558 }
5559
Jamie Madillbe849e42017-05-02 15:49:00 -04005560 switch (ConvertToGLenum(params[0]))
5561 {
5562 case GL_NONE:
5563 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5564 break;
5565
5566 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005567 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005568 return false;
5569 }
5570 break;
5571
5572 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Jamie Madillbe849e42017-05-02 15:49:00 -04005573 {
Luc Ferron1b1a8642018-01-23 15:12:01 -05005574 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5575 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5576 {
5577 return false;
5578 }
5579 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
Jamie Madillbe849e42017-05-02 15:49:00 -04005580 }
5581 break;
5582
5583 case GL_TEXTURE_MIN_LOD:
5584 case GL_TEXTURE_MAX_LOD:
5585 // any value is permissible
5586 break;
5587
5588 case GL_TEXTURE_COMPARE_MODE:
5589 if (!ValidateTextureCompareModeValue(context, params))
5590 {
5591 return false;
5592 }
5593 break;
5594
5595 case GL_TEXTURE_COMPARE_FUNC:
5596 if (!ValidateTextureCompareFuncValue(context, params))
5597 {
5598 return false;
5599 }
5600 break;
5601
5602 case GL_TEXTURE_SWIZZLE_R:
5603 case GL_TEXTURE_SWIZZLE_G:
5604 case GL_TEXTURE_SWIZZLE_B:
5605 case GL_TEXTURE_SWIZZLE_A:
5606 switch (ConvertToGLenum(params[0]))
5607 {
5608 case GL_RED:
5609 case GL_GREEN:
5610 case GL_BLUE:
5611 case GL_ALPHA:
5612 case GL_ZERO:
5613 case GL_ONE:
5614 break;
5615
5616 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005617 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005618 return false;
5619 }
5620 break;
5621
5622 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005623 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005625 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005626 return false;
5627 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005628 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005629 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005630 context->handleError(InvalidOperation()
5631 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005632 return false;
5633 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005634 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005635 {
5636 context->handleError(InvalidOperation()
5637 << "Base level must be 0 for multisampled textures.");
5638 return false;
5639 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005640 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005641 {
5642 context->handleError(InvalidOperation()
5643 << "Base level must be 0 for rectangle textures.");
5644 return false;
5645 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005646 break;
5647
5648 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005649 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005650 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005651 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005652 return false;
5653 }
5654 break;
5655
5656 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5657 if (context->getClientVersion() < Version(3, 1))
5658 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005659 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005660 return false;
5661 }
5662 switch (ConvertToGLenum(params[0]))
5663 {
5664 case GL_DEPTH_COMPONENT:
5665 case GL_STENCIL_INDEX:
5666 break;
5667
5668 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005669 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005670 return false;
5671 }
5672 break;
5673
5674 case GL_TEXTURE_SRGB_DECODE_EXT:
5675 if (!ValidateTextureSRGBDecodeValue(context, params))
5676 {
5677 return false;
5678 }
5679 break;
5680
5681 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005682 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005683 return false;
5684 }
5685
5686 return true;
5687}
5688
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005689template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
5690template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04005691
Jamie Madill5b772312018-03-08 20:28:32 -05005692bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04005693{
5694 if (index >= MAX_VERTEX_ATTRIBS)
5695 {
5696 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5697 return false;
5698 }
5699
5700 return true;
5701}
5702
5703bool ValidateGetActiveUniformBlockivBase(Context *context,
5704 GLuint program,
5705 GLuint uniformBlockIndex,
5706 GLenum pname,
5707 GLsizei *length)
5708{
5709 if (length)
5710 {
5711 *length = 0;
5712 }
5713
5714 if (context->getClientMajorVersion() < 3)
5715 {
5716 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5717 return false;
5718 }
5719
5720 Program *programObject = GetValidProgram(context, program);
5721 if (!programObject)
5722 {
5723 return false;
5724 }
5725
5726 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5727 {
5728 context->handleError(InvalidValue()
5729 << "uniformBlockIndex exceeds active uniform block count.");
5730 return false;
5731 }
5732
5733 switch (pname)
5734 {
5735 case GL_UNIFORM_BLOCK_BINDING:
5736 case GL_UNIFORM_BLOCK_DATA_SIZE:
5737 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5738 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5739 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5740 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5741 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5742 break;
5743
5744 default:
5745 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5746 return false;
5747 }
5748
5749 if (length)
5750 {
5751 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5752 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005753 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005754 programObject->getUniformBlockByIndex(uniformBlockIndex);
5755 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5756 }
5757 else
5758 {
5759 *length = 1;
5760 }
5761 }
5762
5763 return true;
5764}
5765
Jamie Madill9696d072017-08-26 23:19:57 -04005766template <typename ParamType>
5767bool ValidateSamplerParameterBase(Context *context,
5768 GLuint sampler,
5769 GLenum pname,
5770 GLsizei bufSize,
5771 ParamType *params)
5772{
5773 if (context->getClientMajorVersion() < 3)
5774 {
5775 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5776 return false;
5777 }
5778
5779 if (!context->isSampler(sampler))
5780 {
5781 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5782 return false;
5783 }
5784
5785 const GLsizei minBufSize = 1;
5786 if (bufSize >= 0 && bufSize < minBufSize)
5787 {
5788 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5789 return false;
5790 }
5791
5792 switch (pname)
5793 {
5794 case GL_TEXTURE_WRAP_S:
5795 case GL_TEXTURE_WRAP_T:
5796 case GL_TEXTURE_WRAP_R:
5797 if (!ValidateTextureWrapModeValue(context, params, false))
5798 {
5799 return false;
5800 }
5801 break;
5802
5803 case GL_TEXTURE_MIN_FILTER:
5804 if (!ValidateTextureMinFilterValue(context, params, false))
5805 {
5806 return false;
5807 }
5808 break;
5809
5810 case GL_TEXTURE_MAG_FILTER:
5811 if (!ValidateTextureMagFilterValue(context, params))
5812 {
5813 return false;
5814 }
5815 break;
5816
5817 case GL_TEXTURE_MIN_LOD:
5818 case GL_TEXTURE_MAX_LOD:
5819 // any value is permissible
5820 break;
5821
5822 case GL_TEXTURE_COMPARE_MODE:
5823 if (!ValidateTextureCompareModeValue(context, params))
5824 {
5825 return false;
5826 }
5827 break;
5828
5829 case GL_TEXTURE_COMPARE_FUNC:
5830 if (!ValidateTextureCompareFuncValue(context, params))
5831 {
5832 return false;
5833 }
5834 break;
5835
5836 case GL_TEXTURE_SRGB_DECODE_EXT:
5837 if (!ValidateTextureSRGBDecodeValue(context, params))
5838 {
5839 return false;
5840 }
5841 break;
5842
Luc Ferron1b1a8642018-01-23 15:12:01 -05005843 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5844 {
5845 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5846 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5847 {
5848 return false;
5849 }
5850 }
5851 break;
5852
Jamie Madill9696d072017-08-26 23:19:57 -04005853 default:
5854 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5855 return false;
5856 }
5857
5858 return true;
5859}
5860
5861template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5862template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5863
5864bool ValidateGetSamplerParameterBase(Context *context,
5865 GLuint sampler,
5866 GLenum pname,
5867 GLsizei *length)
5868{
5869 if (length)
5870 {
5871 *length = 0;
5872 }
5873
5874 if (context->getClientMajorVersion() < 3)
5875 {
5876 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5877 return false;
5878 }
5879
5880 if (!context->isSampler(sampler))
5881 {
5882 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5883 return false;
5884 }
5885
5886 switch (pname)
5887 {
5888 case GL_TEXTURE_WRAP_S:
5889 case GL_TEXTURE_WRAP_T:
5890 case GL_TEXTURE_WRAP_R:
5891 case GL_TEXTURE_MIN_FILTER:
5892 case GL_TEXTURE_MAG_FILTER:
5893 case GL_TEXTURE_MIN_LOD:
5894 case GL_TEXTURE_MAX_LOD:
5895 case GL_TEXTURE_COMPARE_MODE:
5896 case GL_TEXTURE_COMPARE_FUNC:
5897 break;
5898
Luc Ferron1b1a8642018-01-23 15:12:01 -05005899 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5900 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
5901 {
5902 return false;
5903 }
5904 break;
5905
Jamie Madill9696d072017-08-26 23:19:57 -04005906 case GL_TEXTURE_SRGB_DECODE_EXT:
5907 if (!context->getExtensions().textureSRGBDecode)
5908 {
5909 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5910 return false;
5911 }
5912 break;
5913
5914 default:
5915 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5916 return false;
5917 }
5918
5919 if (length)
5920 {
5921 *length = 1;
5922 }
5923 return true;
5924}
5925
5926bool ValidateGetInternalFormativBase(Context *context,
5927 GLenum target,
5928 GLenum internalformat,
5929 GLenum pname,
5930 GLsizei bufSize,
5931 GLsizei *numParams)
5932{
5933 if (numParams)
5934 {
5935 *numParams = 0;
5936 }
5937
5938 if (context->getClientMajorVersion() < 3)
5939 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005940 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005941 return false;
5942 }
5943
5944 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5945 if (!formatCaps.renderable)
5946 {
5947 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5948 return false;
5949 }
5950
5951 switch (target)
5952 {
5953 case GL_RENDERBUFFER:
5954 break;
5955
5956 case GL_TEXTURE_2D_MULTISAMPLE:
5957 if (context->getClientVersion() < ES_3_1)
5958 {
5959 context->handleError(InvalidOperation()
5960 << "Texture target requires at least OpenGL ES 3.1.");
5961 return false;
5962 }
5963 break;
5964
5965 default:
5966 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5967 return false;
5968 }
5969
5970 if (bufSize < 0)
5971 {
5972 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5973 return false;
5974 }
5975
5976 GLsizei maxWriteParams = 0;
5977 switch (pname)
5978 {
5979 case GL_NUM_SAMPLE_COUNTS:
5980 maxWriteParams = 1;
5981 break;
5982
5983 case GL_SAMPLES:
5984 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5985 break;
5986
5987 default:
5988 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5989 return false;
5990 }
5991
5992 if (numParams)
5993 {
5994 // glGetInternalFormativ will not overflow bufSize
5995 *numParams = std::min(bufSize, maxWriteParams);
5996 }
5997
5998 return true;
5999}
6000
Jamie Madille98b1b52018-03-08 09:47:23 -05006001// We should check with Khronos if returning INVALID_FRAMEBUFFER_OPERATION is OK when querying
6002// implementation format info for incomplete framebuffers. It seems like these queries are
6003// incongruent with the other errors.
6004bool ValidateFramebufferComplete(Context *context, Framebuffer *framebuffer, bool isFramebufferOp)
6005{
6006 bool complete = false;
6007 ANGLE_VALIDATION_TRY(framebuffer->isComplete(context, &complete));
6008 if (!complete)
6009 {
6010 if (isFramebufferOp)
6011 {
6012 context->handleError(InvalidFramebufferOperation());
6013 }
6014 else
6015 {
6016 context->handleError(InvalidOperation());
6017 }
6018 return false;
6019 }
6020 return true;
6021}
6022
6023bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6024{
6025 GLint samples = 0;
6026 ANGLE_VALIDATION_TRY(framebuffer->getSamples(context, &samples));
6027 if (samples != 0)
6028 {
6029 context->handleError(InvalidOperation());
6030 return false;
6031 }
6032 return true;
6033}
6034
Jamie Madillc29968b2016-01-20 11:17:23 -05006035} // namespace gl