blob: 90a65de0481a1d614f017b82665e0bef25e8677f [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040012#include "libANGLE/Display.h"
Brandon Jones6cad5662017-06-14 13:25:13 -070013#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Framebuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
Geoff Langa8406172015-07-21 16:53:39 -040016#include "libANGLE/Image.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050017#include "libANGLE/Program.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Query.h"
19#include "libANGLE/Texture.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/TransformFeedback.h"
21#include "libANGLE/VertexArray.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040022#include "libANGLE/formatutils.h"
jchen10a99ed552017-09-22 08:10:32 +080023#include "libANGLE/queryconversions.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040024#include "libANGLE/validationES2.h"
25#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040026
27#include "common/mathutil.h"
28#include "common/utilities.h"
29
Jamie Madille2e406c2016-06-02 13:04:10 -040030using namespace angle;
31
Geoff Lange8ebe7f2013-08-05 15:03:13 -040032namespace gl
33{
Jamie Madill1ca74672015-07-21 15:14:11 -040034namespace
35{
Luc Ferron9dbaeba2018-02-01 07:26:59 -050036bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
37{
38 // List of compressed format that require that the texture size is smaller than or a multiple of
39 // the compressed block size.
40 switch (internalFormat)
41 {
42 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
43 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
44 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
45 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
46 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
47 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
48 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
49 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
50 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
51 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
52 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
53 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
54 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
55 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
56 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
57 return true;
jchen10a99ed552017-09-22 08:10:32 +080058
Luc Ferron9dbaeba2018-02-01 07:26:59 -050059 default:
60 return false;
61 }
62}
63bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
64{
65 // Compressed sub textures have additional formats that requires exact size.
66 // ES 3.1, Section 8.7, Page 171
67 return CompressedTextureFormatRequiresExactSize(internalFormat) ||
68 IsETC2EACFormat(internalFormat);
69}
Corentin Wallez92db6942016-12-09 13:10:36 -050070bool ValidateDrawAttribs(ValidationContext *context,
71 GLint primcount,
72 GLint maxVertex,
73 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040074{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070075 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040076 const gl::Program *program = state.getProgram();
77
Corentin Wallez327411e2016-12-09 11:09:17 -050078 bool webglCompatibility = context->getExtensions().webglCompatibility;
79
Jamie Madill231c7f52017-04-26 13:45:37 -040080 const VertexArray *vao = state.getVertexArray();
81 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080082 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madilld078c682018-01-02 11:50:24 -050083 for (size_t attributeIndex : vao->getEnabledAttributesMask())
Jamie Madill1ca74672015-07-21 15:14:11 -040084 {
85 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallez672f7f32017-06-15 17:42:17 -040086
87 // No need to range check for disabled attribs.
88 if (!attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040089 {
Corentin Wallezfd456442016-12-21 17:57:00 -050090 continue;
91 }
Jamie Madill1ca74672015-07-21 15:14:11 -040092
Jamie Madill231c7f52017-04-26 13:45:37 -040093 // If we have no buffer, then we either get an error, or there are no more checks to be
94 // done.
Corentin Wallez672f7f32017-06-15 17:42:17 -040095 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
96 gl::Buffer *buffer = binding.getBuffer().get();
Corentin Wallezfd456442016-12-21 17:57:00 -050097 if (!buffer)
98 {
Geoff Langfeb8c682017-02-13 16:07:35 -050099 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -0500100 {
101 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -0500102 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
103 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
104 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
105 // error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700106 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
Corentin Wallezfd456442016-12-21 17:57:00 -0500107 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -0500108 }
Corentin Wallezfd456442016-12-21 17:57:00 -0500109 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -0400110 {
111 // This is an application error that would normally result in a crash,
112 // but we catch it and return an error
Brandon Jonesafa75152017-07-21 13:11:29 -0700113 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
Jamie Madill1ca74672015-07-21 15:14:11 -0400114 return false;
115 }
Corentin Wallezfd456442016-12-21 17:57:00 -0500116 continue;
117 }
118
Corentin Wallez672f7f32017-06-15 17:42:17 -0400119 // This needs to come after the check for client arrays as even unused attributes cannot use
120 // client-side arrays
121 if (!program->isAttribLocationActive(attributeIndex))
122 {
123 continue;
124 }
125
Corentin Wallezfd456442016-12-21 17:57:00 -0500126 // If we're drawing zero vertices, we have enough data.
127 if (vertexCount <= 0 || primcount <= 0)
128 {
129 continue;
130 }
131
132 GLint maxVertexElement = 0;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300133 GLuint divisor = binding.getDivisor();
134 if (divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500135 {
136 maxVertexElement = maxVertex;
137 }
138 else
139 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300140 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500141 }
142
143 // We do manual overflow checks here instead of using safe_math.h because it was
144 // a bottleneck. Thanks to some properties of GL we know inequalities that can
145 // help us make the overflow checks faster.
146
147 // The max possible attribSize is 16 for a vector of 4 32 bit values.
148 constexpr uint64_t kMaxAttribSize = 16;
149 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
150 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
151
152 // We know attribStride is given as a GLsizei which is typedefed to int.
153 // We also know an upper bound for attribSize.
154 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800155 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500156 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
157 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
158
159 // Computing the max offset using uint64_t without attrib.offset is overflow
160 // safe. Note: Last vertex element does not take the full stride!
161 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
162 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
163
164 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800165 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
166 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500167 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700168 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500169 return false;
170 }
171 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
172
173 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
174 // We can return INVALID_OPERATION if our vertex attribute does not have
175 // enough backing data.
176 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
177 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700178 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500179 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400180 }
181 }
182
183 return true;
184}
185
Geoff Lang280ba992017-04-18 16:30:58 -0400186bool ValidReadPixelsTypeEnum(ValidationContext *context, GLenum type)
187{
188 switch (type)
189 {
190 // Types referenced in Table 3.4 of the ES 2.0.25 spec
191 case GL_UNSIGNED_BYTE:
192 case GL_UNSIGNED_SHORT_4_4_4_4:
193 case GL_UNSIGNED_SHORT_5_5_5_1:
194 case GL_UNSIGNED_SHORT_5_6_5:
195 return context->getClientVersion() >= ES_2_0;
196
197 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
198 case GL_BYTE:
199 case GL_INT:
200 case GL_SHORT:
201 case GL_UNSIGNED_INT:
202 case GL_UNSIGNED_INT_10F_11F_11F_REV:
203 case GL_UNSIGNED_INT_24_8:
204 case GL_UNSIGNED_INT_2_10_10_10_REV:
205 case GL_UNSIGNED_INT_5_9_9_9_REV:
206 case GL_UNSIGNED_SHORT:
207 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
208 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
209 return context->getClientVersion() >= ES_3_0;
210
211 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400212 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
213 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400214
215 case GL_HALF_FLOAT:
216 return context->getClientVersion() >= ES_3_0 ||
217 context->getExtensions().textureHalfFloat;
218
219 case GL_HALF_FLOAT_OES:
220 return context->getExtensions().colorBufferHalfFloat;
221
222 default:
223 return false;
224 }
225}
226
227bool ValidReadPixelsFormatEnum(ValidationContext *context, GLenum format)
228{
229 switch (format)
230 {
231 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
232 case GL_RGBA:
233 case GL_RGB:
234 case GL_ALPHA:
235 return context->getClientVersion() >= ES_2_0;
236
237 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
238 case GL_RG:
239 case GL_RED:
240 case GL_RGBA_INTEGER:
241 case GL_RGB_INTEGER:
242 case GL_RG_INTEGER:
243 case GL_RED_INTEGER:
244 return context->getClientVersion() >= ES_3_0;
245
246 case GL_SRGB_ALPHA_EXT:
247 case GL_SRGB_EXT:
248 return context->getExtensions().sRGB;
249
250 case GL_BGRA_EXT:
251 return context->getExtensions().readFormatBGRA;
252
253 default:
254 return false;
255 }
256}
257
Geoff Langf607c602016-09-21 11:46:48 -0400258bool ValidReadPixelsFormatType(ValidationContext *context,
259 GLenum framebufferComponentType,
260 GLenum format,
261 GLenum type)
262{
263 switch (framebufferComponentType)
264 {
265 case GL_UNSIGNED_NORMALIZED:
266 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
267 // ReadPixels with BGRA even if the extension is not present
268 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
269 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
270 type == GL_UNSIGNED_BYTE);
271
272 case GL_SIGNED_NORMALIZED:
273 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
274
275 case GL_INT:
276 return (format == GL_RGBA_INTEGER && type == GL_INT);
277
278 case GL_UNSIGNED_INT:
279 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
280
281 case GL_FLOAT:
282 return (format == GL_RGBA && type == GL_FLOAT);
283
284 default:
285 UNREACHABLE();
286 return false;
287 }
288}
289
Geoff Langc1984ed2016-10-07 12:41:00 -0400290template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400291bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400292{
293 switch (ConvertToGLenum(params[0]))
294 {
295 case GL_CLAMP_TO_EDGE:
296 break;
297
298 case GL_REPEAT:
299 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400300 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400301 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400302 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700303 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400304 return false;
305 }
306 break;
307
308 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700309 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400310 return false;
311 }
312
313 return true;
314}
315
316template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400317bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400318{
319 switch (ConvertToGLenum(params[0]))
320 {
321 case GL_NEAREST:
322 case GL_LINEAR:
323 break;
324
325 case GL_NEAREST_MIPMAP_NEAREST:
326 case GL_LINEAR_MIPMAP_NEAREST:
327 case GL_NEAREST_MIPMAP_LINEAR:
328 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400329 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400330 {
331 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700332 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400333 return false;
334 }
335 break;
336
337 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700338 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400339 return false;
340 }
341
342 return true;
343}
344
345template <typename ParamType>
346bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
347{
348 switch (ConvertToGLenum(params[0]))
349 {
350 case GL_NEAREST:
351 case GL_LINEAR:
352 break;
353
354 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700355 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400356 return false;
357 }
358
359 return true;
360}
361
362template <typename ParamType>
363bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
364{
365 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
366 switch (ConvertToGLenum(params[0]))
367 {
368 case GL_NONE:
369 case GL_COMPARE_REF_TO_TEXTURE:
370 break;
371
372 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700373 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400374 return false;
375 }
376
377 return true;
378}
379
380template <typename ParamType>
381bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
382{
383 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
384 switch (ConvertToGLenum(params[0]))
385 {
386 case GL_LEQUAL:
387 case GL_GEQUAL:
388 case GL_LESS:
389 case GL_GREATER:
390 case GL_EQUAL:
391 case GL_NOTEQUAL:
392 case GL_ALWAYS:
393 case GL_NEVER:
394 break;
395
396 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700397 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400398 return false;
399 }
400
401 return true;
402}
403
404template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700405bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
406{
407 if (!context->getExtensions().textureSRGBDecode)
408 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700409 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700410 return false;
411 }
412
413 switch (ConvertToGLenum(params[0]))
414 {
415 case GL_DECODE_EXT:
416 case GL_SKIP_DECODE_EXT:
417 break;
418
419 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700420 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700421 return false;
422 }
423
424 return true;
425}
426
Luc Ferron1b1a8642018-01-23 15:12:01 -0500427bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
428{
429 if (!context->getExtensions().textureFilterAnisotropic)
430 {
431 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
432 return false;
433 }
434
435 return true;
436}
437
438bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
439{
440 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
441 {
442 return false;
443 }
444
445 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
446
447 if (paramValue < 1 || paramValue > largest)
448 {
449 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
450 return false;
451 }
452
453 return true;
454}
455
Geoff Lange0cff192017-05-30 13:04:56 -0400456bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
457{
458 const Program *program = context->getGLState().getProgram();
459 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
460
Brandon Jonesc405ae72017-12-06 14:15:03 -0800461 if (!ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
462 framebuffer->getDrawBufferTypeMask().to_ulong(),
463 program->getActiveOutputVariables().to_ulong(),
464 framebuffer->getDrawBufferMask().to_ulong()))
Geoff Lange0cff192017-05-30 13:04:56 -0400465 {
Brandon Jones76746f92017-11-22 11:44:41 -0800466 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
467 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400468 }
469
470 return true;
471}
472
Geoff Lang9ab5b822017-05-30 16:19:23 -0400473bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
474{
Jamie Madillcac94a92017-11-10 10:09:32 -0500475 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400476 const Program *program = context->getGLState().getProgram();
477 const VertexArray *vao = context->getGLState().getVertexArray();
478
Brandon Jonesc405ae72017-12-06 14:15:03 -0800479 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
480 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
481 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
482
483 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
484 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
485 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
486
487 if (!ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
488 program->getAttributesMask().to_ulong(), 0xFFFF))
Geoff Lang9ab5b822017-05-30 16:19:23 -0400489 {
Brandon Jonesc405ae72017-12-06 14:15:03 -0800490 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexShaderTypeMismatch);
491 return false;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400492 }
Geoff Lang9ab5b822017-05-30 16:19:23 -0400493 return true;
494}
495
Geoff Langf41a7152016-09-19 15:11:17 -0400496} // anonymous namespace
497
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500498bool IsETC2EACFormat(const GLenum format)
499{
500 // ES 3.1, Table 8.19
501 switch (format)
502 {
503 case GL_COMPRESSED_R11_EAC:
504 case GL_COMPRESSED_SIGNED_R11_EAC:
505 case GL_COMPRESSED_RG11_EAC:
506 case GL_COMPRESSED_SIGNED_RG11_EAC:
507 case GL_COMPRESSED_RGB8_ETC2:
508 case GL_COMPRESSED_SRGB8_ETC2:
509 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
510 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
511 case GL_COMPRESSED_RGBA8_ETC2_EAC:
512 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
513 return true;
514
515 default:
516 return false;
517 }
518}
519
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500520bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400521{
Jamie Madilld7460c72014-01-21 16:38:14 -0500522 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400523 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800524 case GL_TEXTURE_2D:
525 case GL_TEXTURE_CUBE_MAP:
526 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400527
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400528 case GL_TEXTURE_RECTANGLE_ANGLE:
529 return context->getExtensions().textureRectangle;
530
He Yunchaoced53ae2016-11-29 15:00:51 +0800531 case GL_TEXTURE_3D:
532 case GL_TEXTURE_2D_ARRAY:
533 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500534
He Yunchaoced53ae2016-11-29 15:00:51 +0800535 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800536 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400537
He Yunchaoced53ae2016-11-29 15:00:51 +0800538 default:
539 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500540 }
Jamie Madill35d15012013-10-07 10:46:37 -0400541}
542
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500543bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
544{
545 switch (target)
546 {
547 case GL_TEXTURE_2D:
548 case GL_TEXTURE_CUBE_MAP:
549 return true;
550
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400551 case GL_TEXTURE_RECTANGLE_ANGLE:
552 return context->getExtensions().textureRectangle;
553
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500554 default:
555 return false;
556 }
557}
558
559bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
560{
561 switch (target)
562 {
563 case GL_TEXTURE_3D:
564 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300565 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500566
567 default:
568 return false;
569 }
570}
571
Ian Ewellbda75592016-04-18 17:25:54 -0400572// Most texture GL calls are not compatible with external textures, so we have a separate validation
573// function for use in the GL calls that do
574bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
575{
576 return (target == GL_TEXTURE_EXTERNAL_OES) &&
577 (context->getExtensions().eglImageExternal ||
578 context->getExtensions().eglStreamConsumerExternal);
579}
580
Shannon Woods4dfed832014-03-17 20:03:39 -0400581// This function differs from ValidTextureTarget in that the target must be
582// usable as the destination of a 2D operation-- so a cube face is valid, but
583// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400584// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500585bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400586{
587 switch (target)
588 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800589 case GL_TEXTURE_2D:
590 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
591 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
592 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
593 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
594 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
595 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
596 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400597 case GL_TEXTURE_RECTANGLE_ANGLE:
598 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800599 default:
600 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500601 }
602}
603
Jamie Madillbe849e42017-05-02 15:49:00 -0400604bool ValidateDrawElementsInstancedBase(ValidationContext *context,
605 GLenum mode,
606 GLsizei count,
607 GLenum type,
608 const GLvoid *indices,
609 GLsizei primcount)
610{
611 if (primcount < 0)
612 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700613 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400614 return false;
615 }
616
617 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
618 {
619 return false;
620 }
621
Jamie Madill9fdaa492018-02-16 10:52:11 -0500622 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400623}
624
625bool ValidateDrawArraysInstancedBase(Context *context,
626 GLenum mode,
627 GLint first,
628 GLsizei count,
629 GLsizei primcount)
630{
631 if (primcount < 0)
632 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700633 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400634 return false;
635 }
636
637 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
638 {
639 return false;
640 }
641
Jamie Madill9fdaa492018-02-16 10:52:11 -0500642 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400643}
644
Corentin Wallez0dc97812017-06-22 14:38:44 -0400645bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400646{
647 // Verify there is at least one active attribute with a divisor of zero
648 const State &state = context->getGLState();
649
650 Program *program = state.getProgram();
651
652 const auto &attribs = state.getVertexArray()->getVertexAttributes();
653 const auto &bindings = state.getVertexArray()->getVertexBindings();
654 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
655 {
656 const VertexAttribute &attrib = attribs[attributeIndex];
657 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300658 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400659 {
660 return true;
661 }
662 }
663
Brandon Jonesafa75152017-07-21 13:11:29 -0700664 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400665 return false;
666}
667
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500668bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
669{
670 switch (target)
671 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800672 case GL_TEXTURE_3D:
673 case GL_TEXTURE_2D_ARRAY:
674 return true;
675 default:
676 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400677 }
678}
679
He Yunchao11b038b2016-11-22 21:24:04 +0800680bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
681{
682 switch (target)
683 {
684 case GL_TEXTURE_2D:
685 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
686 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
687 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
688 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
689 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
690 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
691 case GL_TEXTURE_3D:
692 case GL_TEXTURE_2D_ARRAY:
693 case GL_TEXTURE_2D_MULTISAMPLE:
694 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400695 case GL_TEXTURE_RECTANGLE_ANGLE:
696 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800697 default:
698 return false;
699 }
700}
701
Geoff Lange8afa902017-09-27 15:00:43 -0400702bool ValidFramebufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500703{
He Yunchaoced53ae2016-11-29 15:00:51 +0800704 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
705 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400706 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500707
708 switch (target)
709 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800710 case GL_FRAMEBUFFER:
711 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400712
He Yunchaoced53ae2016-11-29 15:00:51 +0800713 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800714 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400715 return (context->getExtensions().framebufferBlit ||
716 context->getClientMajorVersion() >= 3);
717
He Yunchaoced53ae2016-11-29 15:00:51 +0800718 default:
719 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500720 }
721}
722
Jamie Madillc29968b2016-01-20 11:17:23 -0500723bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400724{
Jamie Madillc29968b2016-01-20 11:17:23 -0500725 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400726 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -0400727 switch (target)
728 {
Jamie Madillc29968b2016-01-20 11:17:23 -0500729 case GL_TEXTURE_2D:
730 maxDimension = caps.max2DTextureSize;
731 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800732 case GL_TEXTURE_CUBE_MAP:
733 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
734 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
735 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
736 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
737 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
738 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
739 maxDimension = caps.maxCubeMapTextureSize;
740 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400741 case GL_TEXTURE_RECTANGLE_ANGLE:
742 return level == 0;
He Yunchaoced53ae2016-11-29 15:00:51 +0800743 case GL_TEXTURE_3D:
744 maxDimension = caps.max3DTextureSize;
745 break;
746 case GL_TEXTURE_2D_ARRAY:
747 maxDimension = caps.max2DTextureSize;
748 break;
He Yunchao11b038b2016-11-22 21:24:04 +0800749 case GL_TEXTURE_2D_MULTISAMPLE:
750 maxDimension = caps.max2DTextureSize;
751 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800752 default:
753 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400754 }
755
Brandon Jones6cad5662017-06-14 13:25:13 -0700756 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400757}
758
Brandon Jones6cad5662017-06-14 13:25:13 -0700759bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -0700760 GLenum target,
761 GLint level,
762 GLsizei width,
763 GLsizei height,
764 GLsizei depth,
765 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400766{
Brandon Jones6cad5662017-06-14 13:25:13 -0700767 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400768 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700769 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400770 return false;
771 }
Austin Kinross08528e12015-10-07 16:24:40 -0700772 // TexSubImage parameters can be NPOT without textureNPOT extension,
773 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500774 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500775 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500776 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400777 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400778 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700779 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400780 return false;
781 }
782
783 if (!ValidMipLevel(context, target, level))
784 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700785 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400786 return false;
787 }
788
789 return true;
790}
791
Geoff Lang966c9402017-04-18 12:38:27 -0400792bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
793{
794 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
795 (size % blockSize == 0);
796}
797
Jamie Madillc29968b2016-01-20 11:17:23 -0500798bool ValidCompressedImageSize(const ValidationContext *context,
799 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400800 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500801 GLsizei width,
802 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400803{
Geoff Langca271392017-04-05 12:30:00 -0400804 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400805 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400806 {
807 return false;
808 }
809
Geoff Lang966c9402017-04-18 12:38:27 -0400810 if (width < 0 || height < 0)
811 {
812 return false;
813 }
814
815 if (CompressedTextureFormatRequiresExactSize(internalFormat))
816 {
817 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
818 // block size for level 0 but WebGL disallows this.
819 bool smallerThanBlockSizeAllowed =
820 level > 0 || !context->getExtensions().webglCompatibility;
821
822 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
823 smallerThanBlockSizeAllowed) ||
824 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
825 smallerThanBlockSizeAllowed))
826 {
827 return false;
828 }
829 }
830
831 return true;
832}
833
834bool ValidCompressedSubImageSize(const ValidationContext *context,
835 GLenum internalFormat,
836 GLint xoffset,
837 GLint yoffset,
838 GLsizei width,
839 GLsizei height,
840 size_t textureWidth,
841 size_t textureHeight)
842{
843 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
844 if (!formatInfo.compressed)
845 {
846 return false;
847 }
848
Geoff Lang44ff5a72017-02-03 15:15:43 -0500849 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400850 {
851 return false;
852 }
853
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500854 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400855 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500856 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400857 yoffset % formatInfo.compressedBlockHeight != 0)
858 {
859 return false;
860 }
861
862 // Allowed to either have data that is a multiple of block size or is smaller than the block
863 // size but fills the entire mip
864 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
865 static_cast<size_t>(width) == textureWidth &&
866 static_cast<size_t>(height) == textureHeight;
867 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
868 (height % formatInfo.compressedBlockHeight) == 0;
869 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400870 {
871 return false;
872 }
873 }
874
Geoff Langd4f180b2013-09-24 13:57:44 -0400875 return true;
876}
877
Geoff Langff5b2d52016-09-07 11:32:23 -0400878bool ValidImageDataSize(ValidationContext *context,
879 GLenum textureTarget,
880 GLsizei width,
881 GLsizei height,
882 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400883 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400884 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400885 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400886 GLsizei imageSize)
887{
Corentin Wallez336129f2017-10-17 15:55:40 -0400888 gl::Buffer *pixelUnpackBuffer =
889 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400890 if (pixelUnpackBuffer == nullptr && imageSize < 0)
891 {
892 // Checks are not required
893 return true;
894 }
895
896 // ...the data would be unpacked from the buffer object such that the memory reads required
897 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400898 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
899 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400900 const gl::Extents size(width, height, depth);
901 const auto &unpack = context->getGLState().getUnpackState();
902
903 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
904 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
905 if (endByteOrErr.isError())
906 {
907 context->handleError(endByteOrErr.getError());
908 return false;
909 }
910
911 GLuint endByte = endByteOrErr.getResult();
912
913 if (pixelUnpackBuffer)
914 {
915 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
916 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
917 checkedEndByte += checkedOffset;
918
919 if (!checkedEndByte.IsValid() ||
920 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
921 {
922 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500923 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -0400924 return false;
925 }
926 }
927 else
928 {
929 ASSERT(imageSize >= 0);
930 if (pixels == nullptr && imageSize != 0)
931 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500932 context->handleError(InvalidOperation()
933 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400934 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400935 }
936
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400937 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400938 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500939 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400940 return false;
941 }
942 }
943
944 return true;
945}
946
Geoff Lang37dde692014-01-31 16:34:54 -0500947bool ValidQueryType(const Context *context, GLenum queryType)
948{
He Yunchaoced53ae2016-11-29 15:00:51 +0800949 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
950 "GL extension enums not equal.");
951 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
952 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -0500953
954 switch (queryType)
955 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800956 case GL_ANY_SAMPLES_PASSED:
957 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400958 return context->getClientMajorVersion() >= 3 ||
959 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +0800960 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
961 return (context->getClientMajorVersion() >= 3);
962 case GL_TIME_ELAPSED_EXT:
963 return context->getExtensions().disjointTimerQuery;
964 case GL_COMMANDS_COMPLETED_CHROMIUM:
965 return context->getExtensions().syncQuery;
966 default:
967 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500968 }
969}
970
Geoff Lang2d62ab72017-03-23 16:54:40 -0400971bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
972 GLenum type,
973 GLboolean normalized,
974 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400975 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400976 bool pureInteger)
977{
978 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400979 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
980 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
981 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
982 // parameter exceeds 255.
983 constexpr GLsizei kMaxWebGLStride = 255;
984 if (stride > kMaxWebGLStride)
985 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500986 context->handleError(InvalidValue()
987 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -0400988 return false;
989 }
990
991 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
992 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
993 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
994 // or an INVALID_OPERATION error is generated.
995 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
996 size_t typeSize = GetVertexFormatTypeSize(internalType);
997
998 ASSERT(isPow2(typeSize) && typeSize > 0);
999 size_t sizeMask = (typeSize - 1);
1000 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1001 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001002 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001003 return false;
1004 }
1005
1006 if ((stride & sizeMask) != 0)
1007 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001008 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001009 return false;
1010 }
1011
1012 return true;
1013}
1014
Jamie Madillef300b12016-10-07 15:12:09 -04001015Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001016{
He Yunchaoced53ae2016-11-29 15:00:51 +08001017 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1018 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1019 // or program object and INVALID_OPERATION if the provided name identifies an object
1020 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001021
Dian Xiang769769a2015-09-09 15:20:08 -07001022 Program *validProgram = context->getProgram(id);
1023
1024 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001025 {
Dian Xiang769769a2015-09-09 15:20:08 -07001026 if (context->getShader(id))
1027 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001028 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001029 }
1030 else
1031 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001032 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001033 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001034 }
Dian Xiang769769a2015-09-09 15:20:08 -07001035
1036 return validProgram;
1037}
1038
Jamie Madillef300b12016-10-07 15:12:09 -04001039Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001040{
1041 // See ValidProgram for spec details.
1042
1043 Shader *validShader = context->getShader(id);
1044
1045 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001046 {
Dian Xiang769769a2015-09-09 15:20:08 -07001047 if (context->getProgram(id))
1048 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001049 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001050 }
1051 else
1052 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001053 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001054 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001055 }
Dian Xiang769769a2015-09-09 15:20:08 -07001056
1057 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001058}
1059
Geoff Langb1196682014-07-23 13:47:29 -04001060bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001061{
Geoff Langfa125c92017-10-24 13:01:46 -04001062 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001063 {
Geoff Langfa125c92017-10-24 13:01:46 -04001064 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1065 {
1066 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1067 return false;
1068 }
Jamie Madillb4472272014-07-03 10:38:55 -04001069
Geoff Langfa125c92017-10-24 13:01:46 -04001070 // Color attachment 0 is validated below because it is always valid
1071 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001072 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001073 {
Geoff Langfa125c92017-10-24 13:01:46 -04001074 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001075 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001076 }
1077 }
1078 else
1079 {
1080 switch (attachment)
1081 {
Geoff Langfa125c92017-10-24 13:01:46 -04001082 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001083 case GL_DEPTH_ATTACHMENT:
1084 case GL_STENCIL_ATTACHMENT:
1085 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001086
He Yunchaoced53ae2016-11-29 15:00:51 +08001087 case GL_DEPTH_STENCIL_ATTACHMENT:
1088 if (!context->getExtensions().webglCompatibility &&
1089 context->getClientMajorVersion() < 3)
1090 {
Geoff Langfa125c92017-10-24 13:01:46 -04001091 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001092 return false;
1093 }
1094 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001095
He Yunchaoced53ae2016-11-29 15:00:51 +08001096 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001097 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001098 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001099 }
1100 }
1101
1102 return true;
1103}
1104
Jamie Madille8fb6402017-02-14 17:56:40 -05001105bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001106 GLenum target,
1107 GLsizei samples,
1108 GLenum internalformat,
1109 GLsizei width,
1110 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001111{
1112 switch (target)
1113 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001114 case GL_RENDERBUFFER:
1115 break;
1116 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001117 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001118 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001119 }
1120
1121 if (width < 0 || height < 0 || samples < 0)
1122 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001123 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001124 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001125 }
1126
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001127 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1128 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1129
1130 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001131 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001132 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001133 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001134 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001135 }
1136
1137 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1138 // 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 -08001139 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001140 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1141 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001142 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001143 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001144 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001145 }
1146
Geoff Langaae65a42014-05-26 12:43:44 -04001147 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001148 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001149 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001150 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001151 }
1152
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001153 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001154 if (handle == 0)
1155 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001156 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001157 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001158 }
1159
1160 return true;
1161}
1162
He Yunchaoced53ae2016-11-29 15:00:51 +08001163bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1164 GLenum target,
1165 GLenum attachment,
1166 GLenum renderbuffertarget,
1167 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001168{
Geoff Lange8afa902017-09-27 15:00:43 -04001169 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001170 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001171 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001172 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001173 }
1174
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001175 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001176
Jamie Madill84115c92015-04-23 15:00:07 -04001177 ASSERT(framebuffer);
1178 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001179 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001180 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001181 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001182 }
1183
Jamie Madillb4472272014-07-03 10:38:55 -04001184 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001185 {
Jamie Madillb4472272014-07-03 10:38:55 -04001186 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001187 }
1188
Jamie Madillab9d82c2014-01-21 16:38:14 -05001189 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1190 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1191 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1192 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1193 if (renderbuffer != 0)
1194 {
1195 if (!context->getRenderbuffer(renderbuffer))
1196 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001197 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001198 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001199 }
1200 }
1201
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001202 return true;
1203}
1204
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001205bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001206 GLint srcX0,
1207 GLint srcY0,
1208 GLint srcX1,
1209 GLint srcY1,
1210 GLint dstX0,
1211 GLint dstY0,
1212 GLint dstX1,
1213 GLint dstY1,
1214 GLbitfield mask,
1215 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001216{
1217 switch (filter)
1218 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001219 case GL_NEAREST:
1220 break;
1221 case GL_LINEAR:
1222 break;
1223 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001224 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001225 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001226 }
1227
1228 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1229 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001230 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001231 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001232 }
1233
1234 if (mask == 0)
1235 {
1236 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1237 // buffers are copied.
1238 return false;
1239 }
1240
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001241 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1242 // color buffer, leaving only nearest being unfiltered from above
1243 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1244 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001245 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001246 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001247 }
1248
Jamie Madill51f40ec2016-06-15 14:06:00 -04001249 const auto &glState = context->getGLState();
1250 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1251 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001252
1253 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001254 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001255 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001256 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001257 }
1258
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001259 if (readFramebuffer->id() == drawFramebuffer->id())
1260 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001261 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001262 return false;
1263 }
1264
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001265 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001266 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001267 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001268 return false;
1269 }
1270
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001271 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001272 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001273 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001274 return false;
1275 }
1276
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001277 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001278 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001279 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001280 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001281 }
1282
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001283 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1284
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001285 if (mask & GL_COLOR_BUFFER_BIT)
1286 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001287 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001288 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001289
He Yunchao66a41a22016-12-15 16:45:05 +08001290 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001291 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001292 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001293
Geoff Langa15472a2015-08-11 11:48:03 -04001294 for (size_t drawbufferIdx = 0;
1295 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001296 {
Geoff Langa15472a2015-08-11 11:48:03 -04001297 const FramebufferAttachment *attachment =
1298 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1299 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001300 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001301 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001302
Geoff Langb2f3d052013-08-13 12:49:27 -04001303 // The GL ES 3.0.2 spec (pg 193) states that:
1304 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001305 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1306 // as well
1307 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1308 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001309 // Changes with EXT_color_buffer_float:
1310 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001311 GLenum readComponentType = readFormat.info->componentType;
1312 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001313 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001314 readComponentType == GL_SIGNED_NORMALIZED);
1315 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1316 drawComponentType == GL_SIGNED_NORMALIZED);
1317
1318 if (extensions.colorBufferFloat)
1319 {
1320 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1321 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1322
1323 if (readFixedOrFloat != drawFixedOrFloat)
1324 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001325 context->handleError(InvalidOperation()
1326 << "If the read buffer contains fixed-point or "
1327 "floating-point values, the draw buffer must "
1328 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001329 return false;
1330 }
1331 }
1332 else if (readFixedPoint != drawFixedPoint)
1333 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001334 context->handleError(InvalidOperation()
1335 << "If the read buffer contains fixed-point values, "
1336 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001337 return false;
1338 }
1339
1340 if (readComponentType == GL_UNSIGNED_INT &&
1341 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001342 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001343 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001344 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001345 }
1346
Jamie Madill6163c752015-12-07 16:32:59 -05001347 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001348 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001349 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001350 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001351 }
1352
Jamie Madilla3944d42016-07-22 22:13:26 -04001353 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001354 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001355 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001356 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001357 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001358 }
Geoff Lange4915782017-04-12 15:19:07 -04001359
1360 if (context->getExtensions().webglCompatibility &&
1361 *readColorBuffer == *attachment)
1362 {
1363 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001364 InvalidOperation()
1365 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001366 return false;
1367 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001368 }
1369 }
1370
Jamie Madilla3944d42016-07-22 22:13:26 -04001371 if ((readFormat.info->componentType == GL_INT ||
1372 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1373 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001374 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001375 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001376 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001377 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001378 }
He Yunchao66a41a22016-12-15 16:45:05 +08001379 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1380 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1381 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1382 // situation is an application error that would lead to a crash in ANGLE.
1383 else if (drawFramebuffer->hasEnabledDrawBuffer())
1384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001385 context->handleError(
1386 InvalidOperation()
1387 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001388 return false;
1389 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001390 }
1391
He Yunchaoced53ae2016-11-29 15:00:51 +08001392 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001393 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1394 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001395 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001396 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001397 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001398 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001399 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001400 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001401 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001402
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001403 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001404 {
Kenneth Russell69382852017-07-21 16:38:44 -04001405 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001406 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001407 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001408 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001409 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001410
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001411 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001412 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001413 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001414 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001415 }
Geoff Lange4915782017-04-12 15:19:07 -04001416
1417 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1418 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001419 context->handleError(
1420 InvalidOperation()
1421 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001422 return false;
1423 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001424 }
He Yunchao66a41a22016-12-15 16:45:05 +08001425 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1426 else if (drawBuffer)
1427 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001428 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1429 "depth/stencil attachment of a "
1430 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001431 return false;
1432 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001433 }
1434 }
1435
Martin Radeva3ed4572017-07-27 18:29:37 +03001436 // ANGLE_multiview, Revision 1:
1437 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1438 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1439 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1440 {
1441 context->handleError(InvalidFramebufferOperation()
1442 << "Attempt to read from a multi-view framebuffer.");
1443 return false;
1444 }
1445 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1446 {
1447 context->handleError(InvalidFramebufferOperation()
1448 << "Attempt to write to a multi-view framebuffer.");
1449 return false;
1450 }
1451
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001452 return true;
1453}
1454
Jamie Madill4928b7c2017-06-20 12:57:39 -04001455bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001456 GLint x,
1457 GLint y,
1458 GLsizei width,
1459 GLsizei height,
1460 GLenum format,
1461 GLenum type,
1462 GLsizei bufSize,
1463 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001464 GLsizei *columns,
1465 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001466 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001467{
1468 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001469 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001470 return false;
1471 }
1472
Geoff Lang62fce5b2016-09-30 10:46:35 -04001473 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001474 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001475 {
Geoff Langb1196682014-07-23 13:47:29 -04001476 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001477 }
1478
Geoff Lang62fce5b2016-09-30 10:46:35 -04001479 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001480 {
Geoff Langb1196682014-07-23 13:47:29 -04001481 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001482 }
1483
Jamie Madillc29968b2016-01-20 11:17:23 -05001484 return true;
1485}
1486
1487bool ValidateReadnPixelsEXT(Context *context,
1488 GLint x,
1489 GLint y,
1490 GLsizei width,
1491 GLsizei height,
1492 GLenum format,
1493 GLenum type,
1494 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001495 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001496{
1497 if (bufSize < 0)
1498 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001499 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001500 return false;
1501 }
1502
Geoff Lang62fce5b2016-09-30 10:46:35 -04001503 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001504 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001505}
Jamie Madill26e91952014-03-05 15:01:27 -05001506
Jamie Madill4928b7c2017-06-20 12:57:39 -04001507bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001508 GLint x,
1509 GLint y,
1510 GLsizei width,
1511 GLsizei height,
1512 GLenum format,
1513 GLenum type,
1514 GLsizei bufSize,
1515 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001516 GLsizei *columns,
1517 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001518 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001519{
1520 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001521 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001522 return false;
1523 }
1524
Geoff Lange93daba2017-03-30 13:54:40 -04001525 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1526 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001527 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001528 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001529 }
1530
Geoff Lang62fce5b2016-09-30 10:46:35 -04001531 if (!ValidateRobustBufferSize(context, bufSize, *length))
1532 {
1533 return false;
1534 }
1535
1536 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001537}
1538
Jamie Madillf0e04492017-08-26 15:28:42 -04001539bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001540{
1541 if (!context->getExtensions().occlusionQueryBoolean &&
1542 !context->getExtensions().disjointTimerQuery)
1543 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001544 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001545 return false;
1546 }
1547
Olli Etuaho41997e72016-03-10 13:38:39 +02001548 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001549}
1550
Jamie Madillf0e04492017-08-26 15:28:42 -04001551bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const 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 ValidateIsQueryEXT(gl::Context *context, GLuint id)
1564{
1565 if (!context->getExtensions().occlusionQueryBoolean &&
1566 !context->getExtensions().disjointTimerQuery)
1567 {
1568 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1569 return false;
1570 }
1571
1572 return true;
1573}
1574
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001575bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001576{
1577 if (!ValidQueryType(context, target))
1578 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001579 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001580 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001581 }
1582
1583 if (id == 0)
1584 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001585 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001586 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001587 }
1588
1589 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1590 // of zero, if the active query object name for <target> is non-zero (for the
1591 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1592 // the active query for either target is non-zero), if <id> is the name of an
1593 // existing query object whose type does not match <target>, or if <id> is the
1594 // active query object name for any query type, the error INVALID_OPERATION is
1595 // generated.
1596
1597 // Ensure no other queries are active
1598 // NOTE: If other queries than occlusion are supported, we will need to check
1599 // separately that:
1600 // a) The query ID passed is not the current active query for any target/type
1601 // b) There are no active queries for the requested target (and in the case
1602 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1603 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001604
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001605 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001606 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001607 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001608 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001609 }
1610
1611 Query *queryObject = context->getQuery(id, true, target);
1612
1613 // check that name was obtained with glGenQueries
1614 if (!queryObject)
1615 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001616 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001617 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001618 }
1619
1620 // check for type mismatch
1621 if (queryObject->getType() != target)
1622 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001623 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001624 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001625 }
1626
1627 return true;
1628}
1629
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001630bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1631{
1632 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001633 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001634 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001635 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001636 return false;
1637 }
1638
1639 return ValidateBeginQueryBase(context, target, id);
1640}
1641
1642bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001643{
1644 if (!ValidQueryType(context, target))
1645 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001646 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001647 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001648 }
1649
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001650 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001651
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001652 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001653 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001654 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001655 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001656 }
1657
Jamie Madill45c785d2014-05-13 14:09:34 -04001658 return true;
1659}
1660
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001661bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1662{
1663 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001664 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001665 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001666 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001667 return false;
1668 }
1669
1670 return ValidateEndQueryBase(context, target);
1671}
1672
1673bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1674{
1675 if (!context->getExtensions().disjointTimerQuery)
1676 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001677 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001678 return false;
1679 }
1680
1681 if (target != GL_TIMESTAMP_EXT)
1682 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001683 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001684 return false;
1685 }
1686
1687 Query *queryObject = context->getQuery(id, true, target);
1688 if (queryObject == nullptr)
1689 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001690 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001691 return false;
1692 }
1693
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001694 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001695 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001696 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001697 return false;
1698 }
1699
1700 return true;
1701}
1702
Geoff Lang2186c382016-10-14 10:54:54 -04001703bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001704{
Geoff Lang2186c382016-10-14 10:54:54 -04001705 if (numParams)
1706 {
1707 *numParams = 0;
1708 }
1709
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001710 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1711 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001712 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001713 return false;
1714 }
1715
1716 switch (pname)
1717 {
1718 case GL_CURRENT_QUERY_EXT:
1719 if (target == GL_TIMESTAMP_EXT)
1720 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001721 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001722 return false;
1723 }
1724 break;
1725 case GL_QUERY_COUNTER_BITS_EXT:
1726 if (!context->getExtensions().disjointTimerQuery ||
1727 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1728 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001729 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001730 return false;
1731 }
1732 break;
1733 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001734 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001735 return false;
1736 }
1737
Geoff Lang2186c382016-10-14 10:54:54 -04001738 if (numParams)
1739 {
1740 // All queries return only one value
1741 *numParams = 1;
1742 }
1743
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001744 return true;
1745}
1746
1747bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1748{
1749 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001750 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001751 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001752 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001753 return false;
1754 }
1755
Geoff Lang2186c382016-10-14 10:54:54 -04001756 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001757}
1758
Geoff Lang2186c382016-10-14 10:54:54 -04001759bool ValidateGetQueryivRobustANGLE(Context *context,
1760 GLenum target,
1761 GLenum pname,
1762 GLsizei bufSize,
1763 GLsizei *length,
1764 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001765{
Geoff Lang2186c382016-10-14 10:54:54 -04001766 if (!ValidateRobustEntryPoint(context, bufSize))
1767 {
1768 return false;
1769 }
1770
1771 if (!ValidateGetQueryivBase(context, target, pname, length))
1772 {
1773 return false;
1774 }
1775
1776 if (!ValidateRobustBufferSize(context, bufSize, *length))
1777 {
1778 return false;
1779 }
1780
1781 return true;
1782}
1783
1784bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1785{
1786 if (numParams)
1787 {
1788 *numParams = 0;
1789 }
1790
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001791 Query *queryObject = context->getQuery(id, false, GL_NONE);
1792
1793 if (!queryObject)
1794 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001795 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001796 return false;
1797 }
1798
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001799 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001800 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001801 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001802 return false;
1803 }
1804
1805 switch (pname)
1806 {
1807 case GL_QUERY_RESULT_EXT:
1808 case GL_QUERY_RESULT_AVAILABLE_EXT:
1809 break;
1810
1811 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001812 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001813 return false;
1814 }
1815
Geoff Lang2186c382016-10-14 10:54:54 -04001816 if (numParams)
1817 {
1818 *numParams = 1;
1819 }
1820
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001821 return true;
1822}
1823
1824bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1825{
1826 if (!context->getExtensions().disjointTimerQuery)
1827 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001828 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001829 return false;
1830 }
Geoff Lang2186c382016-10-14 10:54:54 -04001831 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1832}
1833
1834bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1835 GLuint id,
1836 GLenum pname,
1837 GLsizei bufSize,
1838 GLsizei *length,
1839 GLint *params)
1840{
1841 if (!context->getExtensions().disjointTimerQuery)
1842 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001843 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001844 return false;
1845 }
1846
1847 if (!ValidateRobustEntryPoint(context, bufSize))
1848 {
1849 return false;
1850 }
1851
1852 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1853 {
1854 return false;
1855 }
1856
1857 if (!ValidateRobustBufferSize(context, bufSize, *length))
1858 {
1859 return false;
1860 }
1861
1862 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001863}
1864
1865bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1866{
1867 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001868 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001869 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001870 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001871 return false;
1872 }
Geoff Lang2186c382016-10-14 10:54:54 -04001873 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1874}
1875
1876bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1877 GLuint id,
1878 GLenum pname,
1879 GLsizei bufSize,
1880 GLsizei *length,
1881 GLuint *params)
1882{
1883 if (!context->getExtensions().disjointTimerQuery &&
1884 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1885 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001886 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001887 return false;
1888 }
1889
1890 if (!ValidateRobustEntryPoint(context, bufSize))
1891 {
1892 return false;
1893 }
1894
1895 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1896 {
1897 return false;
1898 }
1899
1900 if (!ValidateRobustBufferSize(context, bufSize, *length))
1901 {
1902 return false;
1903 }
1904
1905 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001906}
1907
1908bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1909{
1910 if (!context->getExtensions().disjointTimerQuery)
1911 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001912 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001913 return false;
1914 }
Geoff Lang2186c382016-10-14 10:54:54 -04001915 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1916}
1917
1918bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1919 GLuint id,
1920 GLenum pname,
1921 GLsizei bufSize,
1922 GLsizei *length,
1923 GLint64 *params)
1924{
1925 if (!context->getExtensions().disjointTimerQuery)
1926 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001927 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001928 return false;
1929 }
1930
1931 if (!ValidateRobustEntryPoint(context, bufSize))
1932 {
1933 return false;
1934 }
1935
1936 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1937 {
1938 return false;
1939 }
1940
1941 if (!ValidateRobustBufferSize(context, bufSize, *length))
1942 {
1943 return false;
1944 }
1945
1946 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001947}
1948
1949bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1950{
1951 if (!context->getExtensions().disjointTimerQuery)
1952 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001953 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001954 return false;
1955 }
Geoff Lang2186c382016-10-14 10:54:54 -04001956 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1957}
1958
1959bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1960 GLuint id,
1961 GLenum pname,
1962 GLsizei bufSize,
1963 GLsizei *length,
1964 GLuint64 *params)
1965{
1966 if (!context->getExtensions().disjointTimerQuery)
1967 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001968 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001969 return false;
1970 }
1971
1972 if (!ValidateRobustEntryPoint(context, bufSize))
1973 {
1974 return false;
1975 }
1976
1977 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1978 {
1979 return false;
1980 }
1981
1982 if (!ValidateRobustBufferSize(context, bufSize, *length))
1983 {
1984 return false;
1985 }
1986
1987 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001988}
1989
Jiajia Qin5451d532017-11-16 17:16:34 +08001990bool ValidateUniformCommonBase(ValidationContext *context,
1991 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05001992 GLint location,
1993 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08001994 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05001995{
Jiajia Qin5451d532017-11-16 17:16:34 +08001996 // TODO(Jiajia): Add image uniform check in future.
1997 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05001998 {
Jiajia Qin5451d532017-11-16 17:16:34 +08001999 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002000 return false;
2001 }
2002
Jiajia Qin5451d532017-11-16 17:16:34 +08002003 if (!program)
2004 {
2005 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2006 return false;
2007 }
2008
2009 if (!program->isLinked())
2010 {
2011 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2012 return false;
2013 }
2014
2015 if (location == -1)
2016 {
2017 // Silently ignore the uniform command
2018 return false;
2019 }
2020
2021 const auto &uniformLocations = program->getUniformLocations();
2022 size_t castedLocation = static_cast<size_t>(location);
2023 if (castedLocation >= uniformLocations.size())
2024 {
2025 context->handleError(InvalidOperation() << "Invalid uniform location");
2026 return false;
2027 }
2028
2029 const auto &uniformLocation = uniformLocations[castedLocation];
2030 if (uniformLocation.ignored)
2031 {
2032 // Silently ignore the uniform command
2033 return false;
2034 }
2035
2036 if (!uniformLocation.used())
2037 {
2038 context->handleError(InvalidOperation());
2039 return false;
2040 }
2041
2042 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2043
2044 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2045 if (!uniform.isArray() && count > 1)
2046 {
2047 context->handleError(InvalidOperation());
2048 return false;
2049 }
2050
2051 *uniformOut = &uniform;
2052 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002053}
2054
Jiajia Qin5451d532017-11-16 17:16:34 +08002055bool ValidateUniform1ivValue(ValidationContext *context,
2056 GLenum uniformType,
2057 GLsizei count,
2058 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002059{
Jiajia Qin5451d532017-11-16 17:16:34 +08002060 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2061 // It is compatible with INT or BOOL.
2062 // Do these cheap tests first, for a little extra speed.
2063 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002064 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002065 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002066 }
2067
Jiajia Qin5451d532017-11-16 17:16:34 +08002068 if (IsSamplerType(uniformType))
2069 {
2070 // Check that the values are in range.
2071 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2072 for (GLsizei i = 0; i < count; ++i)
2073 {
2074 if (value[i] < 0 || value[i] >= max)
2075 {
2076 context->handleError(InvalidValue() << "sampler uniform value out of range");
2077 return false;
2078 }
2079 }
2080 return true;
2081 }
2082
2083 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2084 return false;
2085}
2086
2087bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2088{
2089 // Check that the value type is compatible with uniform type.
2090 // Do the cheaper test first, for a little extra speed.
2091 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2092 {
2093 return true;
2094 }
2095
2096 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2097 return false;
2098}
2099
2100bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2101{
2102 // Check that the value type is compatible with uniform type.
2103 if (valueType == uniformType)
2104 {
2105 return true;
2106 }
2107
2108 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2109 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002110}
2111
Jamie Madillc1d770e2017-04-13 17:31:24 -04002112bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002113{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002114 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002115 gl::Program *programObject = context->getGLState().getProgram();
2116 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2117 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002118}
2119
Jamie Madillbe849e42017-05-02 15:49:00 -04002120bool ValidateUniform1iv(ValidationContext *context,
2121 GLint location,
2122 GLsizei count,
2123 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002124{
2125 const LinkedUniform *uniform = nullptr;
2126 gl::Program *programObject = context->getGLState().getProgram();
2127 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2128 ValidateUniform1ivValue(context, uniform->type, count, value);
2129}
2130
Jamie Madillc1d770e2017-04-13 17:31:24 -04002131bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002132 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002133 GLint location,
2134 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002135 GLboolean transpose)
2136{
Geoff Lang92019432017-11-20 13:09:34 -05002137 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002138 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002139 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002140 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002141 }
2142
Jamie Madill62d31cb2015-09-11 13:25:51 -04002143 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002144 gl::Program *programObject = context->getGLState().getProgram();
2145 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2146 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002147}
2148
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002149bool ValidateStateQuery(ValidationContext *context,
2150 GLenum pname,
2151 GLenum *nativeType,
2152 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002153{
2154 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2155 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002156 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002157 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002158 }
2159
Jamie Madill0af26e12015-03-05 19:54:33 -05002160 const Caps &caps = context->getCaps();
2161
Jamie Madill893ab082014-05-16 16:56:10 -04002162 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2163 {
2164 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2165
Jamie Madill0af26e12015-03-05 19:54:33 -05002166 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002167 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002168 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002169 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002170 }
2171 }
2172
2173 switch (pname)
2174 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002175 case GL_TEXTURE_BINDING_2D:
2176 case GL_TEXTURE_BINDING_CUBE_MAP:
2177 case GL_TEXTURE_BINDING_3D:
2178 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002179 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002180 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002181 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2182 if (!context->getExtensions().textureRectangle)
2183 {
2184 context->handleError(InvalidEnum()
2185 << "ANGLE_texture_rectangle extension not present");
2186 return false;
2187 }
2188 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002189 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2190 if (!context->getExtensions().eglStreamConsumerExternal &&
2191 !context->getExtensions().eglImageExternal)
2192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002193 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2194 "nor GL_OES_EGL_image_external "
2195 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002196 return false;
2197 }
2198 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002199
He Yunchaoced53ae2016-11-29 15:00:51 +08002200 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2201 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002202 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002203 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2204 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002205 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002206 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002207 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002208 }
2209
Jamie Madill51f40ec2016-06-15 14:06:00 -04002210 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2211 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002212
2213 if (framebuffer->getReadBufferState() == GL_NONE)
2214 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002215 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002216 return false;
2217 }
2218
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002219 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002220 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002221 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002222 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002223 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002224 }
2225 }
2226 break;
2227
He Yunchaoced53ae2016-11-29 15:00:51 +08002228 default:
2229 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002230 }
2231
2232 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002233 if (*numParams == 0)
2234 {
2235 return false;
2236 }
2237
2238 return true;
2239}
2240
2241bool ValidateRobustStateQuery(ValidationContext *context,
2242 GLenum pname,
2243 GLsizei bufSize,
2244 GLenum *nativeType,
2245 unsigned int *numParams)
2246{
2247 if (!ValidateRobustEntryPoint(context, bufSize))
2248 {
2249 return false;
2250 }
2251
2252 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2253 {
2254 return false;
2255 }
2256
2257 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002258 {
2259 return false;
2260 }
2261
2262 return true;
2263}
2264
Jamie Madillc29968b2016-01-20 11:17:23 -05002265bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2266 GLenum target,
2267 GLint level,
2268 GLenum internalformat,
2269 bool isSubImage,
2270 GLint xoffset,
2271 GLint yoffset,
2272 GLint zoffset,
2273 GLint x,
2274 GLint y,
2275 GLsizei width,
2276 GLsizei height,
2277 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002278 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002279{
Brandon Jones6cad5662017-06-14 13:25:13 -07002280 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002281 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002282 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2283 return false;
2284 }
2285
2286 if (width < 0 || height < 0)
2287 {
2288 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002289 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002290 }
2291
He Yunchaoced53ae2016-11-29 15:00:51 +08002292 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2293 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002294 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002295 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002296 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002297 }
2298
2299 if (border != 0)
2300 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002301 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002302 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002303 }
2304
2305 if (!ValidMipLevel(context, target, level))
2306 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002307 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002308 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002309 }
2310
Jamie Madill51f40ec2016-06-15 14:06:00 -04002311 const auto &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002312 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002313 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002314 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002315 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002316 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002317 }
2318
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002319 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002320 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002321 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002322 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002323 }
2324
Martin Radev138064f2016-07-15 12:03:41 +03002325 if (readFramebuffer->getReadBufferState() == GL_NONE)
2326 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002327 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002328 return false;
2329 }
2330
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002331 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2332 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002333 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002334 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002335 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2336 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002337 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002338 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002339 return false;
2340 }
2341
Martin Radev04e2c3b2017-07-27 16:54:35 +03002342 // ANGLE_multiview spec, Revision 1:
2343 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2344 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2345 // is not NONE.
2346 if (source->getMultiviewLayout() != GL_NONE)
2347 {
2348 context->handleError(InvalidFramebufferOperation()
2349 << "The active read framebuffer object has multiview attachments.");
2350 return false;
2351 }
2352
Geoff Langaae65a42014-05-26 12:43:44 -04002353 const gl::Caps &caps = context->getCaps();
2354
Geoff Langaae65a42014-05-26 12:43:44 -04002355 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002356 switch (target)
2357 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002358 case GL_TEXTURE_2D:
2359 maxDimension = caps.max2DTextureSize;
2360 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002361
He Yunchaoced53ae2016-11-29 15:00:51 +08002362 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2363 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2364 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2365 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2366 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2367 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2368 maxDimension = caps.maxCubeMapTextureSize;
2369 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002370
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002371 case GL_TEXTURE_RECTANGLE_ANGLE:
2372 maxDimension = caps.maxRectangleTextureSize;
2373 break;
2374
He Yunchaoced53ae2016-11-29 15:00:51 +08002375 case GL_TEXTURE_2D_ARRAY:
2376 maxDimension = caps.max2DTextureSize;
2377 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002378
He Yunchaoced53ae2016-11-29 15:00:51 +08002379 case GL_TEXTURE_3D:
2380 maxDimension = caps.max3DTextureSize;
2381 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002382
He Yunchaoced53ae2016-11-29 15:00:51 +08002383 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002384 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002385 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002386 }
2387
Jamie Madillc29968b2016-01-20 11:17:23 -05002388 gl::Texture *texture =
2389 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002390 if (!texture)
2391 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002392 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002393 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002394 }
2395
Geoff Lang69cce582015-09-17 13:20:36 -04002396 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002397 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002398 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002399 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002400 }
2401
Geoff Langca271392017-04-05 12:30:00 -04002402 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002403 isSubImage ? *texture->getFormat(target, level).info
2404 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002405
Geoff Lang966c9402017-04-18 12:38:27 -04002406 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002407 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002408 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002409 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002410 }
2411
2412 if (isSubImage)
2413 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002414 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2415 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2416 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002417 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002418 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002419 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002420 }
2421 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002422 else
2423 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002424 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002425 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002426 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002427 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002428 }
2429
Geoff Langeb66a6e2016-10-31 13:06:12 -04002430 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002431 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002432 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002433 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002434 }
2435
2436 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002437 if (static_cast<int>(width) > maxLevelDimension ||
2438 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002439 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002440 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002441 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002442 }
2443 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002444
Jamie Madill0c8abca2016-07-22 20:21:26 -04002445 if (textureFormatOut)
2446 {
2447 *textureFormatOut = texture->getFormat(target, level);
2448 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002449
2450 // Detect texture copying feedback loops for WebGL.
2451 if (context->getExtensions().webglCompatibility)
2452 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002453 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002454 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002455 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002456 return false;
2457 }
2458 }
2459
Jamie Madill560a8d82014-05-21 13:06:20 -04002460 return true;
2461}
2462
Jiajia Qind9671222016-11-29 16:30:31 +08002463bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002464{
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;
2475 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002476 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002477 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002478 }
2479
Jamie Madill250d33f2014-06-06 17:09:03 -04002480 if (count < 0)
2481 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002482 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002483 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002484 }
2485
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002486 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002487
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002488 const Extensions &extensions = context->getExtensions();
2489
2490 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2491 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2492 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2493 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002494 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002495 // Check for mapped buffers
2496 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002497 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002498 {
2499 context->handleError(InvalidOperation());
2500 return false;
2501 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002502 }
2503
Jamie Madillcbcde722017-01-06 14:50:00 -05002504 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2505 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002506 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002507 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002508 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002509 const FramebufferAttachment *dsAttachment =
2510 framebuffer->getStencilOrDepthStencilAttachment();
2511 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002512 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002513 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002514
2515 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2516 bool differentWritemasks =
2517 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2518 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2519 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2520 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2521
2522 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002523 {
Martin Radevffe754b2017-07-31 10:38:07 +03002524 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002525 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002526 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2527 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002528 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002529 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002530 return false;
2531 }
Jamie Madillac528012014-06-20 13:21:23 -04002532 }
2533
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002534 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002535 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002536 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002537 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002538 }
2539
Geoff Lang7dd2e102014-11-10 15:19:26 -05002540 gl::Program *program = state.getProgram();
2541 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002542 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002543 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002544 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002545 }
2546
Yunchao Hecddcb592017-11-13 15:27:35 +08002547 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2548 // vertex shader stage or fragment shader stage is a undefined behaviour.
2549 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2550 // produce undefined result.
Yunchao Heece12532017-11-21 15:50:21 +08002551 if (!program->hasLinkedVertexShader() || !program->hasLinkedFragmentShader())
Yunchao Hecddcb592017-11-13 15:27:35 +08002552 {
2553 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2554 "vertex shader stage or fragment shader stage.");
2555 return false;
2556 }
2557
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002558 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002559 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002560 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002561 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002562 }
2563
Martin Radevffe754b2017-07-31 10:38:07 +03002564 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002565 {
Martin Radevda8e2572017-09-12 17:21:16 +03002566 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002567 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002568 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002569 {
2570 context->handleError(InvalidOperation() << "The number of views in the active program "
2571 "and draw framebuffer does not match.");
2572 return false;
2573 }
Martin Radev7e69f762017-07-27 14:54:13 +03002574
2575 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2576 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2577 framebufferNumViews > 1)
2578 {
2579 context->handleError(InvalidOperation()
2580 << "There is an active transform feedback object "
2581 "when the number of views in the active draw "
2582 "framebuffer is greater than 1.");
2583 return false;
2584 }
Martin Radevffe754b2017-07-31 10:38:07 +03002585
2586 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2587 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2588 {
2589 context->handleError(InvalidOperation() << "There is an active query for target "
2590 "GL_TIME_ELAPSED_EXT when the number of "
2591 "views in the active draw framebuffer is "
2592 "greater than 1.");
2593 return false;
2594 }
Martin Radev7cf61662017-07-26 17:10:53 +03002595 }
2596
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002597 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002598 for (unsigned int uniformBlockIndex = 0;
2599 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002600 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002601 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002602 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002603 const OffsetBindingPointer<Buffer> &uniformBuffer =
2604 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002605
Geoff Lang5d124a62015-09-15 13:03:27 -04002606 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002607 {
2608 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002609 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002610 InvalidOperation()
2611 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002612 return false;
2613 }
2614
Geoff Lang5d124a62015-09-15 13:03:27 -04002615 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002616 if (uniformBufferSize == 0)
2617 {
2618 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002619 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002620 }
2621
Jamie Madill62d31cb2015-09-11 13:25:51 -04002622 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002623 {
2624 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002625 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002626 InvalidOperation()
2627 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002628 return false;
2629 }
2630 }
2631
Geoff Lange0cff192017-05-30 13:04:56 -04002632 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002633 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002634 {
Geoff Lange0cff192017-05-30 13:04:56 -04002635 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002636 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2637 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002638 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002639 return false;
2640 }
Geoff Lange0cff192017-05-30 13:04:56 -04002641
Geoff Lang9ab5b822017-05-30 16:19:23 -04002642 // Detect that the vertex shader input types match the attribute types
2643 if (!ValidateVertexShaderAttributeTypeMatch(context))
2644 {
2645 return false;
2646 }
2647
Geoff Lange0cff192017-05-30 13:04:56 -04002648 // Detect that the color buffer types match the fragment shader output types
2649 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2650 {
2651 return false;
2652 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002653 }
2654
Jamie Madill9fdaa492018-02-16 10:52:11 -05002655 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002656}
2657
Jamie Madillc1d770e2017-04-13 17:31:24 -04002658bool ValidateDrawArraysCommon(ValidationContext *context,
2659 GLenum mode,
2660 GLint first,
2661 GLsizei count,
2662 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002663{
Jamie Madillfd716582014-06-06 17:09:04 -04002664 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002665 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002666 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002667 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002668 }
2669
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002670 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002671 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002672 if (curTransformFeedback && curTransformFeedback->isActive() &&
2673 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002674 {
2675 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002676 // that does not match the current transform feedback object's draw mode (if transform
2677 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002678 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002679 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002680 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002681 }
2682
Jiajia Qind9671222016-11-29 16:30:31 +08002683 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002684 {
2685 return false;
2686 }
2687
Corentin Wallez71168a02016-12-19 15:11:18 -08002688 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002689 // - first < 0 has been checked as an error condition.
2690 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002691 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002692 ASSERT(first >= 0);
2693 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002694 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002695 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2696 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2697 {
2698 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2699 return false;
2700 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002701
Jamie Madill9fdaa492018-02-16 10:52:11 -05002702 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2703 {
2704 return false;
2705 }
Jamie Madillfd716582014-06-06 17:09:04 -04002706 }
2707
2708 return true;
2709}
2710
He Yunchaoced53ae2016-11-29 15:00:51 +08002711bool ValidateDrawArraysInstancedANGLE(Context *context,
2712 GLenum mode,
2713 GLint first,
2714 GLsizei count,
2715 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002716{
Geoff Lang63c5a592017-09-27 14:08:16 -04002717 if (!context->getExtensions().instancedArrays)
2718 {
2719 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2720 return false;
2721 }
2722
Corentin Wallez170efbf2017-05-02 13:45:01 -04002723 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002724 {
2725 return false;
2726 }
2727
Corentin Wallez0dc97812017-06-22 14:38:44 -04002728 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002729}
2730
Jiajia Qind9671222016-11-29 16:30:31 +08002731bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002732{
Jamie Madill250d33f2014-06-06 17:09:03 -04002733 switch (type)
2734 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002735 case GL_UNSIGNED_BYTE:
2736 case GL_UNSIGNED_SHORT:
2737 break;
2738 case GL_UNSIGNED_INT:
2739 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2740 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002741 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002742 return false;
2743 }
2744 break;
2745 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002746 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002747 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002748 }
2749
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002750 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002751
2752 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002753 if (curTransformFeedback && curTransformFeedback->isActive() &&
2754 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002755 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002756 // It is an invalid operation to call DrawElements, DrawRangeElements or
2757 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002758 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002759 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002760 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002761 }
2762
Jiajia Qind9671222016-11-29 16:30:31 +08002763 return true;
2764}
2765
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002766bool ValidateDrawElementsCommon(ValidationContext *context,
2767 GLenum mode,
2768 GLsizei count,
2769 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002770 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002771 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002772{
2773 if (!ValidateDrawElementsBase(context, type))
2774 return false;
2775
2776 const State &state = context->getGLState();
2777
Corentin Wallez170efbf2017-05-02 13:45:01 -04002778 if (!ValidateDrawBase(context, mode, count))
2779 {
2780 return false;
2781 }
2782
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002783 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2784 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2785 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2786 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002787 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002788 // Check for mapped buffers
2789 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002790 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002791 {
2792 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2793 return false;
2794 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002795 }
2796
He Yunchaoced53ae2016-11-29 15:00:51 +08002797 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002798 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002799
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002800 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2801
2802 if (context->getExtensions().webglCompatibility)
2803 {
2804 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2805 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2806 {
2807 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2808 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2809 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002810 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002811 return false;
2812 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002813
2814 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2815 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2816 // error is generated.
2817 if (reinterpret_cast<intptr_t>(indices) < 0)
2818 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002819 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002820 return false;
2821 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002822 }
2823
2824 if (context->getExtensions().webglCompatibility ||
2825 !context->getGLState().areClientArraysEnabled())
2826 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002827 if (!elementArrayBuffer && count > 0)
2828 {
2829 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2830 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2831 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002832 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002833 return false;
2834 }
2835 }
2836
Jamie Madill9fdaa492018-02-16 10:52:11 -05002837 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04002838 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002839 // This is an application error that would normally result in a crash, but we catch it and
2840 // return an error
2841 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
2842 return false;
2843 }
2844
2845 if (count > 0 && elementArrayBuffer)
2846 {
2847 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2848 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2849 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2850 constexpr uint64_t kMaxTypeSize = 8;
2851 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2852 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2853 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
2854
2855 uint64_t typeSize = typeBytes;
2856 uint64_t elementCount = static_cast<uint64_t>(count);
2857 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2858
2859 // Doing the multiplication here is overflow-safe
2860 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2861
2862 // The offset can be any value, check for overflows
2863 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2864 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04002865 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002866 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2867 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002868 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05002869
2870 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2871 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002872 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002873 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
2874 return false;
2875 }
2876
2877 ASSERT(isPow2(typeSize) && typeSize > 0);
2878 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
2879 {
2880 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04002881 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002882 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002883 }
2884
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002885 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002886 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002887 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2888 // access is enabled.
2889 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2890 {
2891 return false;
2892 }
2893 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05002894 else if (count == 0)
2895 {
2896 // ValidateDrawAttribs also does some extra validation that is independent of the vertex
2897 // count.
2898 if (!ValidateDrawAttribs(context, 0, 0, 0))
2899 {
2900 return false;
2901 }
2902 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002903 else
2904 {
2905 // Use the parameter buffer to retrieve and cache the index range.
2906 const auto &params = context->getParams<HasIndexRange>();
2907 const auto &indexRangeOpt = params.getIndexRange();
2908 if (!indexRangeOpt.valid())
2909 {
2910 // Unexpected error.
2911 return false;
2912 }
2913
2914 // If we use an index greater than our maximum supported index range, return an error.
2915 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2916 // return an error if possible here.
2917 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2918 {
2919 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2920 return false;
2921 }
2922
2923 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2924 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2925 {
2926 return false;
2927 }
2928
2929 // No op if there are no real indices in the index data (all are primitive restart).
2930 return (indexRangeOpt.value().vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002931 }
2932
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002933 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002934}
2935
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002936bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2937 GLenum mode,
2938 GLsizei count,
2939 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002940 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002941 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002942{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002943 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002944}
2945
Geoff Lang3edfe032015-09-04 16:38:24 -04002946bool ValidateDrawElementsInstancedANGLE(Context *context,
2947 GLenum mode,
2948 GLsizei count,
2949 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002950 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002951 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002952{
Geoff Lang63c5a592017-09-27 14:08:16 -04002953 if (!context->getExtensions().instancedArrays)
2954 {
2955 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2956 return false;
2957 }
2958
Corentin Wallez170efbf2017-05-02 13:45:01 -04002959 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002960 {
2961 return false;
2962 }
2963
Corentin Wallez0dc97812017-06-22 14:38:44 -04002964 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002965}
2966
He Yunchaoced53ae2016-11-29 15:00:51 +08002967bool ValidateFramebufferTextureBase(Context *context,
2968 GLenum target,
2969 GLenum attachment,
2970 GLuint texture,
2971 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002972{
Geoff Lange8afa902017-09-27 15:00:43 -04002973 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002974 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002975 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002976 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002977 }
2978
2979 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002980 {
2981 return false;
2982 }
2983
Jamie Madill55ec3b12014-07-03 10:38:57 -04002984 if (texture != 0)
2985 {
2986 gl::Texture *tex = context->getTexture(texture);
2987
Luc Ferronadcf0ae2018-01-24 08:27:37 -05002988 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002989 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002990 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002991 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002992 }
2993
2994 if (level < 0)
2995 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002996 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002997 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002998 }
2999 }
3000
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003001 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003002 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003003
Jamie Madill84115c92015-04-23 15:00:07 -04003004 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003005 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003006 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003007 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003008 }
3009
3010 return true;
3011}
3012
Geoff Langb1196682014-07-23 13:47:29 -04003013bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003014{
3015 if (program == 0)
3016 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003017 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003018 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003019 }
3020
Dian Xiang769769a2015-09-09 15:20:08 -07003021 gl::Program *programObject = GetValidProgram(context, program);
3022 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003023 {
3024 return false;
3025 }
3026
Jamie Madill0063c512014-08-25 15:47:53 -04003027 if (!programObject || !programObject->isLinked())
3028 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003029 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003030 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003031 }
3032
Geoff Lang7dd2e102014-11-10 15:19:26 -05003033 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003034 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003035 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003036 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003037 }
3038
Jamie Madill0063c512014-08-25 15:47:53 -04003039 return true;
3040}
3041
Geoff Langf41d0ee2016-10-07 13:04:23 -04003042static bool ValidateSizedGetUniform(Context *context,
3043 GLuint program,
3044 GLint location,
3045 GLsizei bufSize,
3046 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003047{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003048 if (length)
3049 {
3050 *length = 0;
3051 }
3052
Jamie Madill78f41802014-08-25 15:47:55 -04003053 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003054 {
Jamie Madill78f41802014-08-25 15:47:55 -04003055 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003056 }
3057
Geoff Langf41d0ee2016-10-07 13:04:23 -04003058 if (bufSize < 0)
3059 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003060 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003061 return false;
3062 }
3063
Jamie Madilla502c742014-08-28 17:19:13 -04003064 gl::Program *programObject = context->getProgram(program);
3065 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003066
Jamie Madill78f41802014-08-25 15:47:55 -04003067 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003068 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003069 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003070 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003071 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003072 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003073 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003074 }
3075
Geoff Langf41d0ee2016-10-07 13:04:23 -04003076 if (length)
3077 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003078 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003079 }
3080
Jamie Madill0063c512014-08-25 15:47:53 -04003081 return true;
3082}
3083
He Yunchaoced53ae2016-11-29 15:00:51 +08003084bool ValidateGetnUniformfvEXT(Context *context,
3085 GLuint program,
3086 GLint location,
3087 GLsizei bufSize,
3088 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003089{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003090 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003091}
3092
He Yunchaoced53ae2016-11-29 15:00:51 +08003093bool ValidateGetnUniformivEXT(Context *context,
3094 GLuint program,
3095 GLint location,
3096 GLsizei bufSize,
3097 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003098{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003099 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3100}
3101
3102bool ValidateGetUniformfvRobustANGLE(Context *context,
3103 GLuint program,
3104 GLint location,
3105 GLsizei bufSize,
3106 GLsizei *length,
3107 GLfloat *params)
3108{
3109 if (!ValidateRobustEntryPoint(context, bufSize))
3110 {
3111 return false;
3112 }
3113
3114 // bufSize is validated in ValidateSizedGetUniform
3115 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3116}
3117
3118bool ValidateGetUniformivRobustANGLE(Context *context,
3119 GLuint program,
3120 GLint location,
3121 GLsizei bufSize,
3122 GLsizei *length,
3123 GLint *params)
3124{
3125 if (!ValidateRobustEntryPoint(context, bufSize))
3126 {
3127 return false;
3128 }
3129
3130 // bufSize is validated in ValidateSizedGetUniform
3131 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3132}
3133
3134bool ValidateGetUniformuivRobustANGLE(Context *context,
3135 GLuint program,
3136 GLint location,
3137 GLsizei bufSize,
3138 GLsizei *length,
3139 GLuint *params)
3140{
3141 if (!ValidateRobustEntryPoint(context, bufSize))
3142 {
3143 return false;
3144 }
3145
3146 if (context->getClientMajorVersion() < 3)
3147 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003148 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003149 return false;
3150 }
3151
3152 // bufSize is validated in ValidateSizedGetUniform
3153 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003154}
3155
He Yunchaoced53ae2016-11-29 15:00:51 +08003156bool ValidateDiscardFramebufferBase(Context *context,
3157 GLenum target,
3158 GLsizei numAttachments,
3159 const GLenum *attachments,
3160 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003161{
3162 if (numAttachments < 0)
3163 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003164 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003165 return false;
3166 }
3167
3168 for (GLsizei i = 0; i < numAttachments; ++i)
3169 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003170 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003171 {
3172 if (defaultFramebuffer)
3173 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003174 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003175 return false;
3176 }
3177
3178 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3179 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003180 context->handleError(InvalidOperation() << "Requested color attachment is "
3181 "greater than the maximum supported "
3182 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003183 return false;
3184 }
3185 }
3186 else
3187 {
3188 switch (attachments[i])
3189 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003190 case GL_DEPTH_ATTACHMENT:
3191 case GL_STENCIL_ATTACHMENT:
3192 case GL_DEPTH_STENCIL_ATTACHMENT:
3193 if (defaultFramebuffer)
3194 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003195 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3196 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003197 return false;
3198 }
3199 break;
3200 case GL_COLOR:
3201 case GL_DEPTH:
3202 case GL_STENCIL:
3203 if (!defaultFramebuffer)
3204 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003205 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3206 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003207 return false;
3208 }
3209 break;
3210 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003211 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003212 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003213 }
3214 }
3215 }
3216
3217 return true;
3218}
3219
Austin Kinross6ee1e782015-05-29 17:05:37 -07003220bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3221{
Jamie Madill007530e2017-12-28 14:27:04 -05003222 if (!context->getExtensions().debugMarker)
3223 {
3224 // The debug marker calls should not set error state
3225 // However, it seems reasonable to set an error state if the extension is not enabled
3226 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3227 return false;
3228 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003229
Jamie Madill007530e2017-12-28 14:27:04 -05003230 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003231 if (length < 0)
3232 {
3233 return false;
3234 }
3235
3236 if (marker == nullptr)
3237 {
3238 return false;
3239 }
3240
3241 return true;
3242}
3243
3244bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3245{
Jamie Madill007530e2017-12-28 14:27:04 -05003246 if (!context->getExtensions().debugMarker)
3247 {
3248 // The debug marker calls should not set error state
3249 // However, it seems reasonable to set an error state if the extension is not enabled
3250 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3251 return false;
3252 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003253
Jamie Madill007530e2017-12-28 14:27:04 -05003254 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003255 if (length < 0)
3256 {
3257 return false;
3258 }
3259
3260 if (length > 0 && marker == nullptr)
3261 {
3262 return false;
3263 }
3264
3265 return true;
3266}
3267
Jamie Madill007530e2017-12-28 14:27:04 -05003268bool ValidateEGLImageTargetTexture2DOES(Context *context, GLenum target, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003269{
Geoff Langa8406172015-07-21 16:53:39 -04003270 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3271 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003272 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003273 return false;
3274 }
3275
3276 switch (target)
3277 {
3278 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003279 if (!context->getExtensions().eglImage)
3280 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003281 context->handleError(InvalidEnum()
3282 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003283 }
3284 break;
3285
3286 case GL_TEXTURE_EXTERNAL_OES:
3287 if (!context->getExtensions().eglImageExternal)
3288 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003289 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3290 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003291 }
Geoff Langa8406172015-07-21 16:53:39 -04003292 break;
3293
3294 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003295 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003296 return false;
3297 }
3298
Jamie Madill007530e2017-12-28 14:27:04 -05003299 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3300
Jamie Madill61e16b42017-06-19 11:13:23 -04003301 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003302 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003303 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003304 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003305 return false;
3306 }
3307
Jamie Madill007530e2017-12-28 14:27:04 -05003308 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003309 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003310 context->handleError(InvalidOperation()
3311 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003312 return false;
3313 }
3314
Geoff Langca271392017-04-05 12:30:00 -04003315 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003316 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003317 if (!textureCaps.texturable)
3318 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003319 context->handleError(InvalidOperation()
3320 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003321 return false;
3322 }
3323
Geoff Langdcab33b2015-07-21 13:03:16 -04003324 return true;
3325}
3326
3327bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003328 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003329 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003330{
Geoff Langa8406172015-07-21 16:53:39 -04003331 if (!context->getExtensions().eglImage)
3332 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003333 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003334 return false;
3335 }
3336
3337 switch (target)
3338 {
3339 case GL_RENDERBUFFER:
3340 break;
3341
3342 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003343 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003344 return false;
3345 }
3346
Jamie Madill007530e2017-12-28 14:27:04 -05003347 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3348
Jamie Madill61e16b42017-06-19 11:13:23 -04003349 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003350 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003351 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003352 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003353 return false;
3354 }
3355
Geoff Langca271392017-04-05 12:30:00 -04003356 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003357 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003358 if (!textureCaps.renderable)
3359 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003360 context->handleError(InvalidOperation()
3361 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003362 return false;
3363 }
3364
Geoff Langdcab33b2015-07-21 13:03:16 -04003365 return true;
3366}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003367
3368bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3369{
Geoff Lang36167ab2015-12-07 10:27:14 -05003370 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003371 {
3372 // The default VAO should always exist
3373 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003374 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003375 return false;
3376 }
3377
3378 return true;
3379}
3380
Geoff Langc5629752015-12-07 16:29:04 -05003381bool ValidateProgramBinaryBase(Context *context,
3382 GLuint program,
3383 GLenum binaryFormat,
3384 const void *binary,
3385 GLint length)
3386{
3387 Program *programObject = GetValidProgram(context, program);
3388 if (programObject == nullptr)
3389 {
3390 return false;
3391 }
3392
3393 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3394 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3395 programBinaryFormats.end())
3396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003397 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003398 return false;
3399 }
3400
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003401 if (context->hasActiveTransformFeedback(program))
3402 {
3403 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003404 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3405 "is associated with an active transform "
3406 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003407 return false;
3408 }
3409
Geoff Langc5629752015-12-07 16:29:04 -05003410 return true;
3411}
3412
3413bool ValidateGetProgramBinaryBase(Context *context,
3414 GLuint program,
3415 GLsizei bufSize,
3416 GLsizei *length,
3417 GLenum *binaryFormat,
3418 void *binary)
3419{
3420 Program *programObject = GetValidProgram(context, program);
3421 if (programObject == nullptr)
3422 {
3423 return false;
3424 }
3425
3426 if (!programObject->isLinked())
3427 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003428 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003429 return false;
3430 }
3431
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003432 if (context->getCaps().programBinaryFormats.empty())
3433 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003434 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003435 return false;
3436 }
3437
Geoff Langc5629752015-12-07 16:29:04 -05003438 return true;
3439}
Jamie Madillc29968b2016-01-20 11:17:23 -05003440
Jamie Madillc29968b2016-01-20 11:17:23 -05003441bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3442{
3443 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003444 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003445 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003446 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3447 return false;
3448 }
3449 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3450 {
3451 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003452 return false;
3453 }
3454
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003455 ASSERT(context->getGLState().getDrawFramebuffer());
3456 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003457 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3458
3459 // This should come first before the check for the default frame buffer
3460 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3461 // rather than INVALID_OPERATION
3462 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3463 {
3464 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3465
3466 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003467 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3468 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003469 {
3470 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003471 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3472 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3473 // 3.1 is still a bit ambiguous about the error, but future specs are
3474 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003475 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003476 return false;
3477 }
3478 else if (bufs[colorAttachment] >= maxColorAttachment)
3479 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003480 context->handleError(InvalidOperation()
3481 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003482 return false;
3483 }
3484 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3485 frameBufferId != 0)
3486 {
3487 // INVALID_OPERATION-GL is bound to buffer and ith argument
3488 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003489 context->handleError(InvalidOperation()
3490 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003491 return false;
3492 }
3493 }
3494
3495 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3496 // and n is not 1 or bufs is bound to value other than BACK and NONE
3497 if (frameBufferId == 0)
3498 {
3499 if (n != 1)
3500 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003501 context->handleError(InvalidOperation()
3502 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003503 return false;
3504 }
3505
3506 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3507 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003508 context->handleError(
3509 InvalidOperation()
3510 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003511 return false;
3512 }
3513 }
3514
3515 return true;
3516}
3517
Geoff Lang496c02d2016-10-20 11:38:11 -07003518bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003519 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003520 GLenum pname,
3521 GLsizei *length,
3522 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003523{
Geoff Lang496c02d2016-10-20 11:38:11 -07003524 if (length)
3525 {
3526 *length = 0;
3527 }
3528
3529 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3530 {
3531 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003532 InvalidOperation()
3533 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003534 return false;
3535 }
3536
Corentin Walleze4477002017-12-01 14:39:58 -05003537 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003538 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003539 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003540 return false;
3541 }
3542
Geoff Lang496c02d2016-10-20 11:38:11 -07003543 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003544 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003545 case GL_BUFFER_MAP_POINTER:
3546 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003547
Geoff Lang496c02d2016-10-20 11:38:11 -07003548 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003549 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003550 return false;
3551 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003552
3553 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3554 // target bound to zero generate an INVALID_OPERATION error."
3555 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003556 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003557 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003558 context->handleError(InvalidOperation()
3559 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003560 return false;
3561 }
3562
Geoff Lang496c02d2016-10-20 11:38:11 -07003563 if (length)
3564 {
3565 *length = 1;
3566 }
3567
Olli Etuaho4f667482016-03-30 15:56:35 +03003568 return true;
3569}
3570
Corentin Wallez336129f2017-10-17 15:55:40 -04003571bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003572{
Corentin Walleze4477002017-12-01 14:39:58 -05003573 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003574 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003575 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003576 return false;
3577 }
3578
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003579 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003580
3581 if (buffer == nullptr || !buffer->isMapped())
3582 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003583 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003584 return false;
3585 }
3586
3587 return true;
3588}
3589
3590bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003591 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003592 GLintptr offset,
3593 GLsizeiptr length,
3594 GLbitfield access)
3595{
Corentin Walleze4477002017-12-01 14:39:58 -05003596 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003597 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003598 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003599 return false;
3600 }
3601
Brandon Jones6cad5662017-06-14 13:25:13 -07003602 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003603 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003604 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3605 return false;
3606 }
3607
3608 if (length < 0)
3609 {
3610 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003611 return false;
3612 }
3613
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003614 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003615
3616 if (!buffer)
3617 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003618 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003619 return false;
3620 }
3621
3622 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003623 CheckedNumeric<size_t> checkedOffset(offset);
3624 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003625
Jamie Madille2e406c2016-06-02 13:04:10 -04003626 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003627 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003628 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003629 return false;
3630 }
3631
3632 // Check for invalid bits in the mask
3633 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3634 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3635 GL_MAP_UNSYNCHRONIZED_BIT;
3636
3637 if (access & ~(allAccessBits))
3638 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003639 context->handleError(InvalidValue()
3640 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003641 return false;
3642 }
3643
3644 if (length == 0)
3645 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003646 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003647 return false;
3648 }
3649
3650 if (buffer->isMapped())
3651 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003652 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003653 return false;
3654 }
3655
3656 // Check for invalid bit combinations
3657 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003659 context->handleError(InvalidOperation()
3660 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003661 return false;
3662 }
3663
3664 GLbitfield writeOnlyBits =
3665 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3666
3667 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3668 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003669 context->handleError(InvalidOperation()
3670 << "Invalid access bits when mapping buffer for reading: 0x"
3671 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003672 return false;
3673 }
3674
3675 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3676 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003677 context->handleError(
3678 InvalidOperation()
3679 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003680 return false;
3681 }
Geoff Lang79f71042017-08-14 16:43:43 -04003682
3683 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003684}
3685
3686bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003687 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003688 GLintptr offset,
3689 GLsizeiptr length)
3690{
Brandon Jones6cad5662017-06-14 13:25:13 -07003691 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003692 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003693 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3694 return false;
3695 }
3696
3697 if (length < 0)
3698 {
3699 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003700 return false;
3701 }
3702
Corentin Walleze4477002017-12-01 14:39:58 -05003703 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003704 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003705 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003706 return false;
3707 }
3708
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003709 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003710
3711 if (buffer == nullptr)
3712 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003713 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003714 return false;
3715 }
3716
3717 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003719 context->handleError(InvalidOperation()
3720 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003721 return false;
3722 }
3723
3724 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003725 CheckedNumeric<size_t> checkedOffset(offset);
3726 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003727
Jamie Madille2e406c2016-06-02 13:04:10 -04003728 if (!checkedSize.IsValid() ||
3729 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003730 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003731 context->handleError(InvalidValue()
3732 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003733 return false;
3734 }
3735
3736 return true;
3737}
3738
Olli Etuaho41997e72016-03-10 13:38:39 +02003739bool ValidateGenOrDelete(Context *context, GLint n)
3740{
3741 if (n < 0)
3742 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003743 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003744 return false;
3745 }
3746 return true;
3747}
3748
Geoff Langff5b2d52016-09-07 11:32:23 -04003749bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3750{
3751 if (!context->getExtensions().robustClientMemory)
3752 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003753 context->handleError(InvalidOperation()
3754 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003755 return false;
3756 }
3757
3758 if (bufSize < 0)
3759 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003760 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003761 return false;
3762 }
3763
3764 return true;
3765}
3766
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003767bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3768{
3769 if (bufSize < numParams)
3770 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003771 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3772 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003773 return false;
3774 }
3775
3776 return true;
3777}
3778
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003779bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04003780 GLenum target,
3781 GLenum attachment,
3782 GLenum pname,
3783 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003784{
Geoff Lange8afa902017-09-27 15:00:43 -04003785 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003786 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003787 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003788 return false;
3789 }
3790
3791 int clientVersion = context->getClientMajorVersion();
3792
3793 switch (pname)
3794 {
3795 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3796 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3797 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3798 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3799 break;
3800
Martin Radeve5285d22017-07-14 16:23:53 +03003801 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3802 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3803 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3804 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3805 if (clientVersion < 3 || !context->getExtensions().multiview)
3806 {
3807 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3808 return false;
3809 }
3810 break;
3811
Geoff Langff5b2d52016-09-07 11:32:23 -04003812 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3813 if (clientVersion < 3 && !context->getExtensions().sRGB)
3814 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003815 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003816 return false;
3817 }
3818 break;
3819
3820 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3821 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3822 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3823 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3824 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3825 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3826 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3827 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3828 if (clientVersion < 3)
3829 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003830 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003831 return false;
3832 }
3833 break;
3834
3835 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003836 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003837 return false;
3838 }
3839
3840 // Determine if the attachment is a valid enum
3841 switch (attachment)
3842 {
3843 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04003844 case GL_DEPTH:
3845 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04003846 if (clientVersion < 3)
3847 {
Geoff Langfa125c92017-10-24 13:01:46 -04003848 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003849 return false;
3850 }
3851 break;
3852
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003853 case GL_DEPTH_STENCIL_ATTACHMENT:
3854 if (clientVersion < 3 && !context->isWebGL1())
3855 {
3856 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3857 return false;
3858 }
3859 break;
3860
Geoff Langfa125c92017-10-24 13:01:46 -04003861 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003862 case GL_DEPTH_ATTACHMENT:
3863 case GL_STENCIL_ATTACHMENT:
3864 break;
3865
3866 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003867 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3868 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003869 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3870 {
Geoff Langfa125c92017-10-24 13:01:46 -04003871 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003872 return false;
3873 }
3874 break;
3875 }
3876
3877 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3878 ASSERT(framebuffer);
3879
3880 if (framebuffer->id() == 0)
3881 {
3882 if (clientVersion < 3)
3883 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003884 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003885 return false;
3886 }
3887
3888 switch (attachment)
3889 {
3890 case GL_BACK:
3891 case GL_DEPTH:
3892 case GL_STENCIL:
3893 break;
3894
3895 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003896 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003897 return false;
3898 }
3899 }
3900 else
3901 {
3902 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3903 {
3904 // Valid attachment query
3905 }
3906 else
3907 {
3908 switch (attachment)
3909 {
3910 case GL_DEPTH_ATTACHMENT:
3911 case GL_STENCIL_ATTACHMENT:
3912 break;
3913
3914 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003915 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04003916 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003917 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003918 return false;
3919 }
3920 break;
3921
3922 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003923 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003924 return false;
3925 }
3926 }
3927 }
3928
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003929 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003930 if (attachmentObject)
3931 {
3932 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3933 attachmentObject->type() == GL_TEXTURE ||
3934 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3935
3936 switch (pname)
3937 {
3938 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3939 if (attachmentObject->type() != GL_RENDERBUFFER &&
3940 attachmentObject->type() != GL_TEXTURE)
3941 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003942 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003943 return false;
3944 }
3945 break;
3946
3947 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3948 if (attachmentObject->type() != GL_TEXTURE)
3949 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003950 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003951 return false;
3952 }
3953 break;
3954
3955 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3956 if (attachmentObject->type() != GL_TEXTURE)
3957 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003958 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003959 return false;
3960 }
3961 break;
3962
3963 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3964 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3965 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003966 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003967 return false;
3968 }
3969 break;
3970
3971 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3972 if (attachmentObject->type() != GL_TEXTURE)
3973 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003974 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003975 return false;
3976 }
3977 break;
3978
3979 default:
3980 break;
3981 }
3982 }
3983 else
3984 {
3985 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3986 // is NONE, then querying any other pname will generate INVALID_ENUM.
3987
3988 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3989 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3990 // INVALID_OPERATION for all other pnames
3991
3992 switch (pname)
3993 {
3994 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3995 break;
3996
3997 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3998 if (clientVersion < 3)
3999 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004000 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004001 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004002 return false;
4003 }
4004 break;
4005
4006 default:
4007 if (clientVersion < 3)
4008 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004009 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004010 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004011 return false;
4012 }
4013 else
4014 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004015 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004016 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004017 return false;
4018 }
4019 }
4020 }
4021
Martin Radeve5285d22017-07-14 16:23:53 +03004022 if (numParams)
4023 {
4024 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4025 {
4026 // Only when the viewport offsets are queried we can have a varying number of output
4027 // parameters.
4028 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4029 *numParams = numViews * 2;
4030 }
4031 else
4032 {
4033 // For all other queries we can have only one output parameter.
4034 *numParams = 1;
4035 }
4036 }
4037
Geoff Langff5b2d52016-09-07 11:32:23 -04004038 return true;
4039}
4040
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004041bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004042 GLenum target,
4043 GLenum attachment,
4044 GLenum pname,
4045 GLsizei bufSize,
4046 GLsizei *numParams)
4047{
4048 if (!ValidateRobustEntryPoint(context, bufSize))
4049 {
4050 return false;
4051 }
4052
Jamie Madillbe849e42017-05-02 15:49:00 -04004053 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4054 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004055 {
4056 return false;
4057 }
4058
4059 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4060 {
4061 return false;
4062 }
4063
4064 return true;
4065}
4066
Geoff Langff5b2d52016-09-07 11:32:23 -04004067bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004068 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004069 GLenum pname,
4070 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004071 GLsizei *length,
4072 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004073{
4074 if (!ValidateRobustEntryPoint(context, bufSize))
4075 {
4076 return false;
4077 }
4078
Geoff Langebebe1c2016-10-14 12:01:31 -04004079 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004080 {
4081 return false;
4082 }
4083
Geoff Langebebe1c2016-10-14 12:01:31 -04004084 if (!ValidateRobustBufferSize(context, bufSize, *length))
4085 {
4086 return false;
4087 }
4088
4089 return true;
4090}
4091
Geoff Langebebe1c2016-10-14 12:01:31 -04004092bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004093 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004094 GLenum pname,
4095 GLsizei bufSize,
4096 GLsizei *length,
4097 GLint64 *params)
4098{
4099 if (!ValidateRobustEntryPoint(context, bufSize))
4100 {
4101 return false;
4102 }
4103
4104 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4105 {
4106 return false;
4107 }
4108
4109 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004110 {
4111 return false;
4112 }
4113
4114 return true;
4115}
4116
Jamie Madillbe849e42017-05-02 15:49:00 -04004117bool ValidateGetProgramivBase(ValidationContext *context,
4118 GLuint program,
4119 GLenum pname,
4120 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004121{
4122 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004123 if (numParams)
4124 {
4125 *numParams = 1;
4126 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004127
4128 Program *programObject = GetValidProgram(context, program);
4129 if (!programObject)
4130 {
4131 return false;
4132 }
4133
4134 switch (pname)
4135 {
4136 case GL_DELETE_STATUS:
4137 case GL_LINK_STATUS:
4138 case GL_VALIDATE_STATUS:
4139 case GL_INFO_LOG_LENGTH:
4140 case GL_ATTACHED_SHADERS:
4141 case GL_ACTIVE_ATTRIBUTES:
4142 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4143 case GL_ACTIVE_UNIFORMS:
4144 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4145 break;
4146
4147 case GL_PROGRAM_BINARY_LENGTH:
4148 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4149 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004150 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4151 "requires GL_OES_get_program_binary or "
4152 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004153 return false;
4154 }
4155 break;
4156
4157 case GL_ACTIVE_UNIFORM_BLOCKS:
4158 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4159 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4160 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4161 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4162 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4163 if (context->getClientMajorVersion() < 3)
4164 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004165 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004166 return false;
4167 }
4168 break;
4169
Yunchao He61afff12017-03-14 15:34:03 +08004170 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004171 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004172 if (context->getClientVersion() < Version(3, 1))
4173 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004174 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004175 return false;
4176 }
4177 break;
4178
Jiawei Shao6ae51612018-02-23 14:03:25 +08004179 case GL_COMPUTE_WORK_GROUP_SIZE:
4180 if (context->getClientVersion() < Version(3, 1))
4181 {
4182 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4183 return false;
4184 }
4185
4186 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4187 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4188 // program which has not been linked successfully, or which does not contain objects to
4189 // form a compute shader.
4190 if (!programObject->isLinked())
4191 {
4192 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4193 return false;
4194 }
4195 if (!programObject->hasLinkedComputeShader())
4196 {
4197 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4198 return false;
4199 }
4200 break;
4201
Geoff Langff5b2d52016-09-07 11:32:23 -04004202 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004203 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004204 return false;
4205 }
4206
4207 return true;
4208}
4209
4210bool ValidateGetProgramivRobustANGLE(Context *context,
4211 GLuint program,
4212 GLenum pname,
4213 GLsizei bufSize,
4214 GLsizei *numParams)
4215{
4216 if (!ValidateRobustEntryPoint(context, bufSize))
4217 {
4218 return false;
4219 }
4220
Jamie Madillbe849e42017-05-02 15:49:00 -04004221 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004222 {
4223 return false;
4224 }
4225
4226 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4227 {
4228 return false;
4229 }
4230
4231 return true;
4232}
4233
Geoff Lang740d9022016-10-07 11:20:52 -04004234bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4235 GLenum target,
4236 GLenum pname,
4237 GLsizei bufSize,
4238 GLsizei *length,
4239 GLint *params)
4240{
4241 if (!ValidateRobustEntryPoint(context, bufSize))
4242 {
4243 return false;
4244 }
4245
4246 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4247 {
4248 return false;
4249 }
4250
4251 if (!ValidateRobustBufferSize(context, bufSize, *length))
4252 {
4253 return false;
4254 }
4255
4256 return true;
4257}
4258
Geoff Langd7d0ed32016-10-07 11:33:51 -04004259bool ValidateGetShaderivRobustANGLE(Context *context,
4260 GLuint shader,
4261 GLenum pname,
4262 GLsizei bufSize,
4263 GLsizei *length,
4264 GLint *params)
4265{
4266 if (!ValidateRobustEntryPoint(context, bufSize))
4267 {
4268 return false;
4269 }
4270
4271 if (!ValidateGetShaderivBase(context, shader, pname, length))
4272 {
4273 return false;
4274 }
4275
4276 if (!ValidateRobustBufferSize(context, bufSize, *length))
4277 {
4278 return false;
4279 }
4280
4281 return true;
4282}
4283
Geoff Langc1984ed2016-10-07 12:41:00 -04004284bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4285 GLenum target,
4286 GLenum pname,
4287 GLsizei bufSize,
4288 GLsizei *length,
4289 GLfloat *params)
4290{
4291 if (!ValidateRobustEntryPoint(context, bufSize))
4292 {
4293 return false;
4294 }
4295
4296 if (!ValidateGetTexParameterBase(context, target, pname, length))
4297 {
4298 return false;
4299 }
4300
4301 if (!ValidateRobustBufferSize(context, bufSize, *length))
4302 {
4303 return false;
4304 }
4305
4306 return true;
4307}
4308
Geoff Langc1984ed2016-10-07 12:41:00 -04004309bool ValidateGetTexParameterivRobustANGLE(Context *context,
4310 GLenum target,
4311 GLenum pname,
4312 GLsizei bufSize,
4313 GLsizei *length,
4314 GLint *params)
4315{
4316 if (!ValidateRobustEntryPoint(context, bufSize))
4317 {
4318 return false;
4319 }
4320
4321 if (!ValidateGetTexParameterBase(context, target, pname, length))
4322 {
4323 return false;
4324 }
4325
4326 if (!ValidateRobustBufferSize(context, bufSize, *length))
4327 {
4328 return false;
4329 }
4330
4331 return true;
4332}
4333
Geoff Langc1984ed2016-10-07 12:41:00 -04004334bool ValidateTexParameterfvRobustANGLE(Context *context,
4335 GLenum target,
4336 GLenum pname,
4337 GLsizei bufSize,
4338 const GLfloat *params)
4339{
4340 if (!ValidateRobustEntryPoint(context, bufSize))
4341 {
4342 return false;
4343 }
4344
4345 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4346}
4347
Geoff Langc1984ed2016-10-07 12:41:00 -04004348bool ValidateTexParameterivRobustANGLE(Context *context,
4349 GLenum target,
4350 GLenum pname,
4351 GLsizei bufSize,
4352 const GLint *params)
4353{
4354 if (!ValidateRobustEntryPoint(context, bufSize))
4355 {
4356 return false;
4357 }
4358
4359 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4360}
4361
Geoff Langc1984ed2016-10-07 12:41:00 -04004362bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4363 GLuint sampler,
4364 GLenum pname,
4365 GLuint bufSize,
4366 GLsizei *length,
4367 GLfloat *params)
4368{
4369 if (!ValidateRobustEntryPoint(context, bufSize))
4370 {
4371 return false;
4372 }
4373
4374 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4375 {
4376 return false;
4377 }
4378
4379 if (!ValidateRobustBufferSize(context, bufSize, *length))
4380 {
4381 return false;
4382 }
4383
4384 return true;
4385}
4386
Geoff Langc1984ed2016-10-07 12:41:00 -04004387bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4388 GLuint sampler,
4389 GLenum pname,
4390 GLuint bufSize,
4391 GLsizei *length,
4392 GLint *params)
4393{
4394 if (!ValidateRobustEntryPoint(context, bufSize))
4395 {
4396 return false;
4397 }
4398
4399 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4400 {
4401 return false;
4402 }
4403
4404 if (!ValidateRobustBufferSize(context, bufSize, *length))
4405 {
4406 return false;
4407 }
4408
4409 return true;
4410}
4411
Geoff Langc1984ed2016-10-07 12:41:00 -04004412bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4413 GLuint sampler,
4414 GLenum pname,
4415 GLsizei bufSize,
4416 const GLfloat *params)
4417{
4418 if (!ValidateRobustEntryPoint(context, bufSize))
4419 {
4420 return false;
4421 }
4422
4423 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4424}
4425
Geoff Langc1984ed2016-10-07 12:41:00 -04004426bool ValidateSamplerParameterivRobustANGLE(Context *context,
4427 GLuint sampler,
4428 GLenum pname,
4429 GLsizei bufSize,
4430 const GLint *params)
4431{
4432 if (!ValidateRobustEntryPoint(context, bufSize))
4433 {
4434 return false;
4435 }
4436
4437 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4438}
4439
Geoff Lang0b031062016-10-13 14:30:04 -04004440bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4441 GLuint index,
4442 GLenum pname,
4443 GLsizei bufSize,
4444 GLsizei *length,
4445 GLfloat *params)
4446{
4447 if (!ValidateRobustEntryPoint(context, bufSize))
4448 {
4449 return false;
4450 }
4451
4452 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4453 {
4454 return false;
4455 }
4456
4457 if (!ValidateRobustBufferSize(context, bufSize, *length))
4458 {
4459 return false;
4460 }
4461
4462 return true;
4463}
4464
Geoff Lang0b031062016-10-13 14:30:04 -04004465bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4466 GLuint index,
4467 GLenum pname,
4468 GLsizei bufSize,
4469 GLsizei *length,
4470 GLint *params)
4471{
4472 if (!ValidateRobustEntryPoint(context, bufSize))
4473 {
4474 return false;
4475 }
4476
4477 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4478 {
4479 return false;
4480 }
4481
4482 if (!ValidateRobustBufferSize(context, bufSize, *length))
4483 {
4484 return false;
4485 }
4486
4487 return true;
4488}
4489
Geoff Lang0b031062016-10-13 14:30:04 -04004490bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4491 GLuint index,
4492 GLenum pname,
4493 GLsizei bufSize,
4494 GLsizei *length,
4495 void **pointer)
4496{
4497 if (!ValidateRobustEntryPoint(context, bufSize))
4498 {
4499 return false;
4500 }
4501
4502 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4503 {
4504 return false;
4505 }
4506
4507 if (!ValidateRobustBufferSize(context, bufSize, *length))
4508 {
4509 return false;
4510 }
4511
4512 return true;
4513}
4514
Geoff Lang0b031062016-10-13 14:30:04 -04004515bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4516 GLuint index,
4517 GLenum pname,
4518 GLsizei bufSize,
4519 GLsizei *length,
4520 GLint *params)
4521{
4522 if (!ValidateRobustEntryPoint(context, bufSize))
4523 {
4524 return false;
4525 }
4526
4527 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4528 {
4529 return false;
4530 }
4531
4532 if (!ValidateRobustBufferSize(context, bufSize, *length))
4533 {
4534 return false;
4535 }
4536
4537 return true;
4538}
4539
Geoff Lang0b031062016-10-13 14:30:04 -04004540bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4541 GLuint index,
4542 GLenum pname,
4543 GLsizei bufSize,
4544 GLsizei *length,
4545 GLuint *params)
4546{
4547 if (!ValidateRobustEntryPoint(context, bufSize))
4548 {
4549 return false;
4550 }
4551
4552 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4553 {
4554 return false;
4555 }
4556
4557 if (!ValidateRobustBufferSize(context, bufSize, *length))
4558 {
4559 return false;
4560 }
4561
4562 return true;
4563}
4564
Geoff Lang6899b872016-10-14 11:30:13 -04004565bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4566 GLuint program,
4567 GLuint uniformBlockIndex,
4568 GLenum pname,
4569 GLsizei bufSize,
4570 GLsizei *length,
4571 GLint *params)
4572{
4573 if (!ValidateRobustEntryPoint(context, bufSize))
4574 {
4575 return false;
4576 }
4577
4578 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4579 {
4580 return false;
4581 }
4582
4583 if (!ValidateRobustBufferSize(context, bufSize, *length))
4584 {
4585 return false;
4586 }
4587
4588 return true;
4589}
4590
Geoff Lang0a9661f2016-10-20 10:59:20 -07004591bool ValidateGetInternalFormativRobustANGLE(Context *context,
4592 GLenum target,
4593 GLenum internalformat,
4594 GLenum pname,
4595 GLsizei bufSize,
4596 GLsizei *length,
4597 GLint *params)
4598{
4599 if (!ValidateRobustEntryPoint(context, bufSize))
4600 {
4601 return false;
4602 }
4603
4604 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4605 {
4606 return false;
4607 }
4608
4609 if (!ValidateRobustBufferSize(context, bufSize, *length))
4610 {
4611 return false;
4612 }
4613
4614 return true;
4615}
4616
Shao80957d92017-02-20 21:25:59 +08004617bool ValidateVertexFormatBase(ValidationContext *context,
4618 GLuint attribIndex,
4619 GLint size,
4620 GLenum type,
4621 GLboolean pureInteger)
4622{
4623 const Caps &caps = context->getCaps();
4624 if (attribIndex >= caps.maxVertexAttributes)
4625 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004626 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004627 return false;
4628 }
4629
4630 if (size < 1 || size > 4)
4631 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004632 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004633 return false;
Shao80957d92017-02-20 21:25:59 +08004634 }
4635
4636 switch (type)
4637 {
4638 case GL_BYTE:
4639 case GL_UNSIGNED_BYTE:
4640 case GL_SHORT:
4641 case GL_UNSIGNED_SHORT:
4642 break;
4643
4644 case GL_INT:
4645 case GL_UNSIGNED_INT:
4646 if (context->getClientMajorVersion() < 3)
4647 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004648 context->handleError(InvalidEnum()
4649 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004650 return false;
4651 }
4652 break;
4653
4654 case GL_FIXED:
4655 case GL_FLOAT:
4656 if (pureInteger)
4657 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004658 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004659 return false;
4660 }
4661 break;
4662
4663 case GL_HALF_FLOAT:
4664 if (context->getClientMajorVersion() < 3)
4665 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004666 context->handleError(InvalidEnum()
4667 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004668 return false;
4669 }
4670 if (pureInteger)
4671 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004672 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004673 return false;
4674 }
4675 break;
4676
4677 case GL_INT_2_10_10_10_REV:
4678 case GL_UNSIGNED_INT_2_10_10_10_REV:
4679 if (context->getClientMajorVersion() < 3)
4680 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004681 context->handleError(InvalidEnum()
4682 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004683 return false;
4684 }
4685 if (pureInteger)
4686 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004687 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004688 return false;
4689 }
4690 if (size != 4)
4691 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004692 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4693 "UNSIGNED_INT_2_10_10_10_REV and "
4694 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004695 return false;
4696 }
4697 break;
4698
4699 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004700 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004701 return false;
4702 }
4703
4704 return true;
4705}
4706
Geoff Lang76e65652017-03-27 14:58:02 -04004707// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4708// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4709// specified clear value and the type of a buffer that is being cleared generates an
4710// INVALID_OPERATION error instead of producing undefined results
4711bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4712 GLint drawbuffer,
4713 const GLenum *validComponentTypes,
4714 size_t validComponentTypeCount)
4715{
4716 const FramebufferAttachment *attachment =
4717 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4718 if (attachment)
4719 {
4720 GLenum componentType = attachment->getFormat().info->componentType;
4721 const GLenum *end = validComponentTypes + validComponentTypeCount;
4722 if (std::find(validComponentTypes, end, componentType) == end)
4723 {
4724 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004725 InvalidOperation()
4726 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004727 return false;
4728 }
4729 }
4730
4731 return true;
4732}
4733
Corentin Wallezb2931602017-04-11 15:58:57 -04004734bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4735 GLsizei imageSize,
4736 GLsizei dataSize)
4737{
4738 if (!ValidateRobustEntryPoint(context, dataSize))
4739 {
4740 return false;
4741 }
4742
Corentin Wallez336129f2017-10-17 15:55:40 -04004743 gl::Buffer *pixelUnpackBuffer =
4744 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004745 if (pixelUnpackBuffer == nullptr)
4746 {
4747 if (dataSize < imageSize)
4748 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004749 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004750 }
4751 }
4752 return true;
4753}
4754
Jamie Madillbe849e42017-05-02 15:49:00 -04004755bool ValidateGetBufferParameterBase(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004756 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004757 GLenum pname,
4758 bool pointerVersion,
4759 GLsizei *numParams)
4760{
4761 if (numParams)
4762 {
4763 *numParams = 0;
4764 }
4765
Corentin Walleze4477002017-12-01 14:39:58 -05004766 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004767 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004768 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004769 return false;
4770 }
4771
4772 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4773 if (!buffer)
4774 {
4775 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004776 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004777 return false;
4778 }
4779
4780 const Extensions &extensions = context->getExtensions();
4781
4782 switch (pname)
4783 {
4784 case GL_BUFFER_USAGE:
4785 case GL_BUFFER_SIZE:
4786 break;
4787
4788 case GL_BUFFER_ACCESS_OES:
4789 if (!extensions.mapBuffer)
4790 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004791 context->handleError(InvalidEnum()
4792 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004793 return false;
4794 }
4795 break;
4796
4797 case GL_BUFFER_MAPPED:
4798 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4799 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4800 !extensions.mapBufferRange)
4801 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004802 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4803 "GL_OES_mapbuffer or "
4804 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004805 return false;
4806 }
4807 break;
4808
4809 case GL_BUFFER_MAP_POINTER:
4810 if (!pointerVersion)
4811 {
4812 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004813 InvalidEnum()
4814 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004815 return false;
4816 }
4817 break;
4818
4819 case GL_BUFFER_ACCESS_FLAGS:
4820 case GL_BUFFER_MAP_OFFSET:
4821 case GL_BUFFER_MAP_LENGTH:
4822 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4823 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004824 context->handleError(InvalidEnum()
4825 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004826 return false;
4827 }
4828 break;
4829
4830 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004831 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004832 return false;
4833 }
4834
4835 // All buffer parameter queries return one value.
4836 if (numParams)
4837 {
4838 *numParams = 1;
4839 }
4840
4841 return true;
4842}
4843
4844bool ValidateGetRenderbufferParameterivBase(Context *context,
4845 GLenum target,
4846 GLenum pname,
4847 GLsizei *length)
4848{
4849 if (length)
4850 {
4851 *length = 0;
4852 }
4853
4854 if (target != GL_RENDERBUFFER)
4855 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004856 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004857 return false;
4858 }
4859
4860 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4861 if (renderbuffer == nullptr)
4862 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004863 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004864 return false;
4865 }
4866
4867 switch (pname)
4868 {
4869 case GL_RENDERBUFFER_WIDTH:
4870 case GL_RENDERBUFFER_HEIGHT:
4871 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4872 case GL_RENDERBUFFER_RED_SIZE:
4873 case GL_RENDERBUFFER_GREEN_SIZE:
4874 case GL_RENDERBUFFER_BLUE_SIZE:
4875 case GL_RENDERBUFFER_ALPHA_SIZE:
4876 case GL_RENDERBUFFER_DEPTH_SIZE:
4877 case GL_RENDERBUFFER_STENCIL_SIZE:
4878 break;
4879
4880 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4881 if (!context->getExtensions().framebufferMultisample)
4882 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004883 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004884 return false;
4885 }
4886 break;
4887
4888 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004889 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004890 return false;
4891 }
4892
4893 if (length)
4894 {
4895 *length = 1;
4896 }
4897 return true;
4898}
4899
4900bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4901{
4902 if (length)
4903 {
4904 *length = 0;
4905 }
4906
4907 if (GetValidShader(context, shader) == nullptr)
4908 {
4909 return false;
4910 }
4911
4912 switch (pname)
4913 {
4914 case GL_SHADER_TYPE:
4915 case GL_DELETE_STATUS:
4916 case GL_COMPILE_STATUS:
4917 case GL_INFO_LOG_LENGTH:
4918 case GL_SHADER_SOURCE_LENGTH:
4919 break;
4920
4921 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4922 if (!context->getExtensions().translatedShaderSource)
4923 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004924 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004925 return false;
4926 }
4927 break;
4928
4929 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004930 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004931 return false;
4932 }
4933
4934 if (length)
4935 {
4936 *length = 1;
4937 }
4938 return true;
4939}
4940
4941bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4942{
4943 if (length)
4944 {
4945 *length = 0;
4946 }
4947
4948 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4949 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004950 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004951 return false;
4952 }
4953
4954 if (context->getTargetTexture(target) == nullptr)
4955 {
4956 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004957 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004958 return false;
4959 }
4960
4961 switch (pname)
4962 {
4963 case GL_TEXTURE_MAG_FILTER:
4964 case GL_TEXTURE_MIN_FILTER:
4965 case GL_TEXTURE_WRAP_S:
4966 case GL_TEXTURE_WRAP_T:
4967 break;
4968
4969 case GL_TEXTURE_USAGE_ANGLE:
4970 if (!context->getExtensions().textureUsage)
4971 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004972 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004973 return false;
4974 }
4975 break;
4976
4977 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05004978 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04004979 {
Jamie Madillbe849e42017-05-02 15:49:00 -04004980 return false;
4981 }
4982 break;
4983
4984 case GL_TEXTURE_IMMUTABLE_FORMAT:
4985 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4986 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004987 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004988 return false;
4989 }
4990 break;
4991
4992 case GL_TEXTURE_WRAP_R:
4993 case GL_TEXTURE_IMMUTABLE_LEVELS:
4994 case GL_TEXTURE_SWIZZLE_R:
4995 case GL_TEXTURE_SWIZZLE_G:
4996 case GL_TEXTURE_SWIZZLE_B:
4997 case GL_TEXTURE_SWIZZLE_A:
4998 case GL_TEXTURE_BASE_LEVEL:
4999 case GL_TEXTURE_MAX_LEVEL:
5000 case GL_TEXTURE_MIN_LOD:
5001 case GL_TEXTURE_MAX_LOD:
5002 case GL_TEXTURE_COMPARE_MODE:
5003 case GL_TEXTURE_COMPARE_FUNC:
5004 if (context->getClientMajorVersion() < 3)
5005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005006 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005007 return false;
5008 }
5009 break;
5010
5011 case GL_TEXTURE_SRGB_DECODE_EXT:
5012 if (!context->getExtensions().textureSRGBDecode)
5013 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005014 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005015 return false;
5016 }
5017 break;
5018
Yunchao Hebacaa712018-01-30 14:01:39 +08005019 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5020 if (context->getClientVersion() < Version(3, 1))
5021 {
5022 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5023 return false;
5024 }
5025 break;
5026
Jamie Madillbe849e42017-05-02 15:49:00 -04005027 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005028 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005029 return false;
5030 }
5031
5032 if (length)
5033 {
5034 *length = 1;
5035 }
5036 return true;
5037}
5038
5039bool ValidateGetVertexAttribBase(Context *context,
5040 GLuint index,
5041 GLenum pname,
5042 GLsizei *length,
5043 bool pointer,
5044 bool pureIntegerEntryPoint)
5045{
5046 if (length)
5047 {
5048 *length = 0;
5049 }
5050
5051 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5052 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005053 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005054 return false;
5055 }
5056
5057 if (index >= context->getCaps().maxVertexAttributes)
5058 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005059 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005060 return false;
5061 }
5062
5063 if (pointer)
5064 {
5065 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5066 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005067 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005068 return false;
5069 }
5070 }
5071 else
5072 {
5073 switch (pname)
5074 {
5075 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5076 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5077 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5078 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5079 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5080 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5081 case GL_CURRENT_VERTEX_ATTRIB:
5082 break;
5083
5084 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5085 static_assert(
5086 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5087 "ANGLE extension enums not equal to GL enums.");
5088 if (context->getClientMajorVersion() < 3 &&
5089 !context->getExtensions().instancedArrays)
5090 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005091 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5092 "requires OpenGL ES 3.0 or "
5093 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005094 return false;
5095 }
5096 break;
5097
5098 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5099 if (context->getClientMajorVersion() < 3)
5100 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005101 context->handleError(
5102 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005103 return false;
5104 }
5105 break;
5106
5107 case GL_VERTEX_ATTRIB_BINDING:
5108 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5109 if (context->getClientVersion() < ES_3_1)
5110 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005111 context->handleError(InvalidEnum()
5112 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005113 return false;
5114 }
5115 break;
5116
5117 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005118 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005119 return false;
5120 }
5121 }
5122
5123 if (length)
5124 {
5125 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5126 {
5127 *length = 4;
5128 }
5129 else
5130 {
5131 *length = 1;
5132 }
5133 }
5134
5135 return true;
5136}
5137
Jamie Madill4928b7c2017-06-20 12:57:39 -04005138bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005139 GLint x,
5140 GLint y,
5141 GLsizei width,
5142 GLsizei height,
5143 GLenum format,
5144 GLenum type,
5145 GLsizei bufSize,
5146 GLsizei *length,
5147 GLsizei *columns,
5148 GLsizei *rows,
5149 void *pixels)
5150{
5151 if (length != nullptr)
5152 {
5153 *length = 0;
5154 }
5155 if (rows != nullptr)
5156 {
5157 *rows = 0;
5158 }
5159 if (columns != nullptr)
5160 {
5161 *columns = 0;
5162 }
5163
5164 if (width < 0 || height < 0)
5165 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005166 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005167 return false;
5168 }
5169
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005170 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005171
5172 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5173 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005174 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005175 return false;
5176 }
5177
5178 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5179 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005180 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005181 return false;
5182 }
5183
5184 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5185 ASSERT(framebuffer);
5186
5187 if (framebuffer->getReadBufferState() == GL_NONE)
5188 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005189 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005190 return false;
5191 }
5192
5193 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5194 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5195 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5196 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5197 // situation is an application error that would lead to a crash in ANGLE.
5198 if (readBuffer == nullptr)
5199 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005200 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005201 return false;
5202 }
5203
Martin Radev28031682017-07-28 14:47:56 +03005204 // ANGLE_multiview, Revision 1:
5205 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5206 // current read framebuffer is not NONE.
5207 if (readBuffer->getMultiviewLayout() != GL_NONE)
5208 {
5209 context->handleError(InvalidFramebufferOperation()
5210 << "Attempting to read from a multi-view framebuffer.");
5211 return false;
5212 }
5213
Geoff Lang280ba992017-04-18 16:30:58 -04005214 if (context->getExtensions().webglCompatibility)
5215 {
5216 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5217 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5218 // and type before validating the combination of format and type. However, the
5219 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5220 // verifies that GL_INVALID_OPERATION is generated.
5221 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5222 // dEQP/WebGL.
5223 if (!ValidReadPixelsFormatEnum(context, format))
5224 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005225 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005226 return false;
5227 }
5228
5229 if (!ValidReadPixelsTypeEnum(context, type))
5230 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005231 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005232 return false;
5233 }
5234 }
5235
Jamie Madill4928b7c2017-06-20 12:57:39 -04005236 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5237 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005238 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5239
5240 bool validFormatTypeCombination =
5241 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5242
5243 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5244 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005245 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005246 return false;
5247 }
5248
5249 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005250 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005251 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5252 {
5253 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005254 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005255 return false;
5256 }
5257
5258 // .. the data would be packed to the buffer object such that the memory writes required
5259 // would exceed the data store size.
5260 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5261 const gl::Extents size(width, height, 1);
5262 const auto &pack = context->getGLState().getPackState();
5263
5264 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5265 if (endByteOrErr.isError())
5266 {
5267 context->handleError(endByteOrErr.getError());
5268 return false;
5269 }
5270
5271 size_t endByte = endByteOrErr.getResult();
5272 if (bufSize >= 0)
5273 {
5274 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5275 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005276 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005277 return false;
5278 }
5279 }
5280
5281 if (pixelPackBuffer != nullptr)
5282 {
5283 CheckedNumeric<size_t> checkedEndByte(endByte);
5284 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5285 checkedEndByte += checkedOffset;
5286
5287 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5288 {
5289 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005290 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005291 return false;
5292 }
5293 }
5294
5295 if (pixelPackBuffer == nullptr && length != nullptr)
5296 {
5297 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5298 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005299 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005300 return false;
5301 }
5302
5303 *length = static_cast<GLsizei>(endByte);
5304 }
5305
Geoff Langa953b522018-02-21 16:56:23 -05005306 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005307 angle::CheckedNumeric<int> clippedExtent(length);
5308 if (start < 0)
5309 {
5310 // "subtract" the area that is less than 0
5311 clippedExtent += start;
5312 }
5313
Geoff Langa953b522018-02-21 16:56:23 -05005314 angle::CheckedNumeric<int> readExtent = start;
5315 readExtent += length;
5316 if (!readExtent.IsValid())
5317 {
5318 return false;
5319 }
5320
5321 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005322 {
5323 // Subtract the region to the right of the read buffer
5324 clippedExtent -= (readExtent - bufferSize);
5325 }
5326
5327 if (!clippedExtent.IsValid())
5328 {
Geoff Langa953b522018-02-21 16:56:23 -05005329 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005330 }
5331
Geoff Langa953b522018-02-21 16:56:23 -05005332 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5333 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005334 };
5335
Geoff Langa953b522018-02-21 16:56:23 -05005336 GLsizei writtenColumns = 0;
5337 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5338 {
5339 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5340 return false;
5341 }
5342
5343 GLsizei writtenRows = 0;
5344 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5345 {
5346 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5347 return false;
5348 }
5349
Jamie Madillbe849e42017-05-02 15:49:00 -04005350 if (columns != nullptr)
5351 {
Geoff Langa953b522018-02-21 16:56:23 -05005352 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005353 }
5354
5355 if (rows != nullptr)
5356 {
Geoff Langa953b522018-02-21 16:56:23 -05005357 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005358 }
5359
5360 return true;
5361}
5362
5363template <typename ParamType>
5364bool ValidateTexParameterBase(Context *context,
5365 GLenum target,
5366 GLenum pname,
5367 GLsizei bufSize,
5368 const ParamType *params)
5369{
5370 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5371 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005372 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005373 return false;
5374 }
5375
5376 if (context->getTargetTexture(target) == nullptr)
5377 {
5378 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005379 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005380 return false;
5381 }
5382
5383 const GLsizei minBufSize = 1;
5384 if (bufSize >= 0 && bufSize < minBufSize)
5385 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005386 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005387 return false;
5388 }
5389
5390 switch (pname)
5391 {
5392 case GL_TEXTURE_WRAP_R:
5393 case GL_TEXTURE_SWIZZLE_R:
5394 case GL_TEXTURE_SWIZZLE_G:
5395 case GL_TEXTURE_SWIZZLE_B:
5396 case GL_TEXTURE_SWIZZLE_A:
5397 case GL_TEXTURE_BASE_LEVEL:
5398 case GL_TEXTURE_MAX_LEVEL:
5399 case GL_TEXTURE_COMPARE_MODE:
5400 case GL_TEXTURE_COMPARE_FUNC:
5401 case GL_TEXTURE_MIN_LOD:
5402 case GL_TEXTURE_MAX_LOD:
5403 if (context->getClientMajorVersion() < 3)
5404 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005405 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005406 return false;
5407 }
5408 if (target == GL_TEXTURE_EXTERNAL_OES &&
5409 !context->getExtensions().eglImageExternalEssl3)
5410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005411 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5412 "available without "
5413 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005414 return false;
5415 }
5416 break;
5417
5418 default:
5419 break;
5420 }
5421
JiangYizhou4cff8d62017-07-06 14:54:09 +08005422 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5423 {
5424 switch (pname)
5425 {
5426 case GL_TEXTURE_MIN_FILTER:
5427 case GL_TEXTURE_MAG_FILTER:
5428 case GL_TEXTURE_WRAP_S:
5429 case GL_TEXTURE_WRAP_T:
5430 case GL_TEXTURE_WRAP_R:
5431 case GL_TEXTURE_MIN_LOD:
5432 case GL_TEXTURE_MAX_LOD:
5433 case GL_TEXTURE_COMPARE_MODE:
5434 case GL_TEXTURE_COMPARE_FUNC:
5435 context->handleError(InvalidEnum()
5436 << "Invalid parameter for 2D multisampled textures.");
5437 return false;
5438 }
5439 }
5440
Jamie Madillbe849e42017-05-02 15:49:00 -04005441 switch (pname)
5442 {
5443 case GL_TEXTURE_WRAP_S:
5444 case GL_TEXTURE_WRAP_T:
5445 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005446 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005447 bool restrictedWrapModes =
5448 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5449 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5450 {
5451 return false;
5452 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005453 }
5454 break;
5455
5456 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005457 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005458 bool restrictedMinFilter =
5459 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5460 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5461 {
5462 return false;
5463 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005464 }
5465 break;
5466
5467 case GL_TEXTURE_MAG_FILTER:
5468 if (!ValidateTextureMagFilterValue(context, params))
5469 {
5470 return false;
5471 }
5472 break;
5473
5474 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005475 if (!context->getExtensions().textureUsage)
5476 {
5477 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5478 return false;
5479 }
5480
Jamie Madillbe849e42017-05-02 15:49:00 -04005481 switch (ConvertToGLenum(params[0]))
5482 {
5483 case GL_NONE:
5484 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5485 break;
5486
5487 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005488 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005489 return false;
5490 }
5491 break;
5492
5493 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Jamie Madillbe849e42017-05-02 15:49:00 -04005494 {
Luc Ferron1b1a8642018-01-23 15:12:01 -05005495 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5496 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5497 {
5498 return false;
5499 }
5500 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
Jamie Madillbe849e42017-05-02 15:49:00 -04005501 }
5502 break;
5503
5504 case GL_TEXTURE_MIN_LOD:
5505 case GL_TEXTURE_MAX_LOD:
5506 // any value is permissible
5507 break;
5508
5509 case GL_TEXTURE_COMPARE_MODE:
5510 if (!ValidateTextureCompareModeValue(context, params))
5511 {
5512 return false;
5513 }
5514 break;
5515
5516 case GL_TEXTURE_COMPARE_FUNC:
5517 if (!ValidateTextureCompareFuncValue(context, params))
5518 {
5519 return false;
5520 }
5521 break;
5522
5523 case GL_TEXTURE_SWIZZLE_R:
5524 case GL_TEXTURE_SWIZZLE_G:
5525 case GL_TEXTURE_SWIZZLE_B:
5526 case GL_TEXTURE_SWIZZLE_A:
5527 switch (ConvertToGLenum(params[0]))
5528 {
5529 case GL_RED:
5530 case GL_GREEN:
5531 case GL_BLUE:
5532 case GL_ALPHA:
5533 case GL_ZERO:
5534 case GL_ONE:
5535 break;
5536
5537 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005538 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005539 return false;
5540 }
5541 break;
5542
5543 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005544 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005545 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005546 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005547 return false;
5548 }
5549 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5550 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005551 context->handleError(InvalidOperation()
5552 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005553 return false;
5554 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005555 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5556 {
5557 context->handleError(InvalidOperation()
5558 << "Base level must be 0 for multisampled textures.");
5559 return false;
5560 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005561 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5562 {
5563 context->handleError(InvalidOperation()
5564 << "Base level must be 0 for rectangle textures.");
5565 return false;
5566 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005567 break;
5568
5569 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005570 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005571 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005572 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005573 return false;
5574 }
5575 break;
5576
5577 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5578 if (context->getClientVersion() < Version(3, 1))
5579 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005580 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005581 return false;
5582 }
5583 switch (ConvertToGLenum(params[0]))
5584 {
5585 case GL_DEPTH_COMPONENT:
5586 case GL_STENCIL_INDEX:
5587 break;
5588
5589 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005590 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005591 return false;
5592 }
5593 break;
5594
5595 case GL_TEXTURE_SRGB_DECODE_EXT:
5596 if (!ValidateTextureSRGBDecodeValue(context, params))
5597 {
5598 return false;
5599 }
5600 break;
5601
5602 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005603 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005604 return false;
5605 }
5606
5607 return true;
5608}
5609
5610template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5611template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5612
Jamie Madill12e957f2017-08-26 21:42:26 -04005613bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5614{
5615 if (index >= MAX_VERTEX_ATTRIBS)
5616 {
5617 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5618 return false;
5619 }
5620
5621 return true;
5622}
5623
5624bool ValidateGetActiveUniformBlockivBase(Context *context,
5625 GLuint program,
5626 GLuint uniformBlockIndex,
5627 GLenum pname,
5628 GLsizei *length)
5629{
5630 if (length)
5631 {
5632 *length = 0;
5633 }
5634
5635 if (context->getClientMajorVersion() < 3)
5636 {
5637 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5638 return false;
5639 }
5640
5641 Program *programObject = GetValidProgram(context, program);
5642 if (!programObject)
5643 {
5644 return false;
5645 }
5646
5647 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5648 {
5649 context->handleError(InvalidValue()
5650 << "uniformBlockIndex exceeds active uniform block count.");
5651 return false;
5652 }
5653
5654 switch (pname)
5655 {
5656 case GL_UNIFORM_BLOCK_BINDING:
5657 case GL_UNIFORM_BLOCK_DATA_SIZE:
5658 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5659 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5660 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5661 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5662 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5663 break;
5664
5665 default:
5666 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5667 return false;
5668 }
5669
5670 if (length)
5671 {
5672 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5673 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005674 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005675 programObject->getUniformBlockByIndex(uniformBlockIndex);
5676 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5677 }
5678 else
5679 {
5680 *length = 1;
5681 }
5682 }
5683
5684 return true;
5685}
5686
Jamie Madill9696d072017-08-26 23:19:57 -04005687template <typename ParamType>
5688bool ValidateSamplerParameterBase(Context *context,
5689 GLuint sampler,
5690 GLenum pname,
5691 GLsizei bufSize,
5692 ParamType *params)
5693{
5694 if (context->getClientMajorVersion() < 3)
5695 {
5696 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5697 return false;
5698 }
5699
5700 if (!context->isSampler(sampler))
5701 {
5702 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5703 return false;
5704 }
5705
5706 const GLsizei minBufSize = 1;
5707 if (bufSize >= 0 && bufSize < minBufSize)
5708 {
5709 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5710 return false;
5711 }
5712
5713 switch (pname)
5714 {
5715 case GL_TEXTURE_WRAP_S:
5716 case GL_TEXTURE_WRAP_T:
5717 case GL_TEXTURE_WRAP_R:
5718 if (!ValidateTextureWrapModeValue(context, params, false))
5719 {
5720 return false;
5721 }
5722 break;
5723
5724 case GL_TEXTURE_MIN_FILTER:
5725 if (!ValidateTextureMinFilterValue(context, params, false))
5726 {
5727 return false;
5728 }
5729 break;
5730
5731 case GL_TEXTURE_MAG_FILTER:
5732 if (!ValidateTextureMagFilterValue(context, params))
5733 {
5734 return false;
5735 }
5736 break;
5737
5738 case GL_TEXTURE_MIN_LOD:
5739 case GL_TEXTURE_MAX_LOD:
5740 // any value is permissible
5741 break;
5742
5743 case GL_TEXTURE_COMPARE_MODE:
5744 if (!ValidateTextureCompareModeValue(context, params))
5745 {
5746 return false;
5747 }
5748 break;
5749
5750 case GL_TEXTURE_COMPARE_FUNC:
5751 if (!ValidateTextureCompareFuncValue(context, params))
5752 {
5753 return false;
5754 }
5755 break;
5756
5757 case GL_TEXTURE_SRGB_DECODE_EXT:
5758 if (!ValidateTextureSRGBDecodeValue(context, params))
5759 {
5760 return false;
5761 }
5762 break;
5763
Luc Ferron1b1a8642018-01-23 15:12:01 -05005764 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5765 {
5766 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5767 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5768 {
5769 return false;
5770 }
5771 }
5772 break;
5773
Jamie Madill9696d072017-08-26 23:19:57 -04005774 default:
5775 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5776 return false;
5777 }
5778
5779 return true;
5780}
5781
5782template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5783template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5784
5785bool ValidateGetSamplerParameterBase(Context *context,
5786 GLuint sampler,
5787 GLenum pname,
5788 GLsizei *length)
5789{
5790 if (length)
5791 {
5792 *length = 0;
5793 }
5794
5795 if (context->getClientMajorVersion() < 3)
5796 {
5797 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5798 return false;
5799 }
5800
5801 if (!context->isSampler(sampler))
5802 {
5803 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5804 return false;
5805 }
5806
5807 switch (pname)
5808 {
5809 case GL_TEXTURE_WRAP_S:
5810 case GL_TEXTURE_WRAP_T:
5811 case GL_TEXTURE_WRAP_R:
5812 case GL_TEXTURE_MIN_FILTER:
5813 case GL_TEXTURE_MAG_FILTER:
5814 case GL_TEXTURE_MIN_LOD:
5815 case GL_TEXTURE_MAX_LOD:
5816 case GL_TEXTURE_COMPARE_MODE:
5817 case GL_TEXTURE_COMPARE_FUNC:
5818 break;
5819
Luc Ferron1b1a8642018-01-23 15:12:01 -05005820 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5821 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
5822 {
5823 return false;
5824 }
5825 break;
5826
Jamie Madill9696d072017-08-26 23:19:57 -04005827 case GL_TEXTURE_SRGB_DECODE_EXT:
5828 if (!context->getExtensions().textureSRGBDecode)
5829 {
5830 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5831 return false;
5832 }
5833 break;
5834
5835 default:
5836 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5837 return false;
5838 }
5839
5840 if (length)
5841 {
5842 *length = 1;
5843 }
5844 return true;
5845}
5846
5847bool ValidateGetInternalFormativBase(Context *context,
5848 GLenum target,
5849 GLenum internalformat,
5850 GLenum pname,
5851 GLsizei bufSize,
5852 GLsizei *numParams)
5853{
5854 if (numParams)
5855 {
5856 *numParams = 0;
5857 }
5858
5859 if (context->getClientMajorVersion() < 3)
5860 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005861 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005862 return false;
5863 }
5864
5865 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5866 if (!formatCaps.renderable)
5867 {
5868 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5869 return false;
5870 }
5871
5872 switch (target)
5873 {
5874 case GL_RENDERBUFFER:
5875 break;
5876
5877 case GL_TEXTURE_2D_MULTISAMPLE:
5878 if (context->getClientVersion() < ES_3_1)
5879 {
5880 context->handleError(InvalidOperation()
5881 << "Texture target requires at least OpenGL ES 3.1.");
5882 return false;
5883 }
5884 break;
5885
5886 default:
5887 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5888 return false;
5889 }
5890
5891 if (bufSize < 0)
5892 {
5893 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5894 return false;
5895 }
5896
5897 GLsizei maxWriteParams = 0;
5898 switch (pname)
5899 {
5900 case GL_NUM_SAMPLE_COUNTS:
5901 maxWriteParams = 1;
5902 break;
5903
5904 case GL_SAMPLES:
5905 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5906 break;
5907
5908 default:
5909 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5910 return false;
5911 }
5912
5913 if (numParams)
5914 {
5915 // glGetInternalFormativ will not overflow bufSize
5916 *numParams = std::min(bufSize, maxWriteParams);
5917 }
5918
5919 return true;
5920}
5921
Jamie Madillc29968b2016-01-20 11:17:23 -05005922} // namespace gl