blob: e56f731c54f2ecb43b8af22584a8dbb09bbc6858 [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
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800520bool ValidTextureTarget(const ValidationContext *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400521{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800522 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400523 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800524 case TextureType::_2D:
525 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800526 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400527
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800528 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400529 return context->getExtensions().textureRectangle;
530
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800531 case TextureType::_3D:
532 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800533 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500534
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800535 case TextureType::_2DMultisample:
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
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800543bool ValidTexture2DTarget(const ValidationContext *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500544{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800545 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500546 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800547 case TextureType::_2D:
548 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500549 return true;
550
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800551 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400552 return context->getExtensions().textureRectangle;
553
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500554 default:
555 return false;
556 }
557}
558
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800559bool ValidTexture3DTarget(const ValidationContext *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500560{
561 switch (target)
562 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800563 case TextureType::_3D:
564 case TextureType::_2DArray:
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
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800574bool ValidTextureExternalTarget(const ValidationContext *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400575{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800576 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400577 (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
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800585bool ValidTexture2DDestinationTarget(const ValidationContext *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400586{
587 switch (target)
588 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800589 case TextureTarget::_2D:
590 case TextureTarget::CubeMapNegativeX:
591 case TextureTarget::CubeMapNegativeY:
592 case TextureTarget::CubeMapNegativeZ:
593 case TextureTarget::CubeMapPositiveX:
594 case TextureTarget::CubeMapPositiveY:
595 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800596 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800597 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400598 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
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800668bool ValidTexture3DDestinationTarget(const ValidationContext *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500669{
670 switch (target)
671 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800672 case TextureType::_3D:
673 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800674 return true;
675 default:
676 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400677 }
678}
679
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800680bool ValidTexLevelDestinationTarget(const ValidationContext *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800681{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800682 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800683 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800684 case TextureType::_2D:
685 case TextureType::_2DArray:
686 case TextureType::_2DMultisample:
687 case TextureType::CubeMap:
688 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800689 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800690 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400691 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800692 default:
693 return false;
694 }
695}
696
Geoff Lange8afa902017-09-27 15:00:43 -0400697bool ValidFramebufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500698{
He Yunchaoced53ae2016-11-29 15:00:51 +0800699 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
700 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400701 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500702
703 switch (target)
704 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800705 case GL_FRAMEBUFFER:
706 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400707
He Yunchaoced53ae2016-11-29 15:00:51 +0800708 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800709 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400710 return (context->getExtensions().framebufferBlit ||
711 context->getClientMajorVersion() >= 3);
712
He Yunchaoced53ae2016-11-29 15:00:51 +0800713 default:
714 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500715 }
716}
717
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800718bool ValidMipLevel(const ValidationContext *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400719{
Jamie Madillc29968b2016-01-20 11:17:23 -0500720 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400721 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800722 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400723 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800724 case TextureType::_2D:
725 case TextureType::_2DArray:
726 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500727 maxDimension = caps.max2DTextureSize;
728 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800729 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800730 maxDimension = caps.maxCubeMapTextureSize;
731 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800732 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400733 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800734 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800735 maxDimension = caps.max3DTextureSize;
736 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800737 default:
738 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400739 }
740
Brandon Jones6cad5662017-06-14 13:25:13 -0700741 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400742}
743
Brandon Jones6cad5662017-06-14 13:25:13 -0700744bool ValidImageSizeParameters(ValidationContext *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800745 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700746 GLint level,
747 GLsizei width,
748 GLsizei height,
749 GLsizei depth,
750 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400751{
Brandon Jones6cad5662017-06-14 13:25:13 -0700752 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400753 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700754 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400755 return false;
756 }
Austin Kinross08528e12015-10-07 16:24:40 -0700757 // TexSubImage parameters can be NPOT without textureNPOT extension,
758 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500759 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500760 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500761 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400762 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400763 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700764 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400765 return false;
766 }
767
768 if (!ValidMipLevel(context, target, level))
769 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700770 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400771 return false;
772 }
773
774 return true;
775}
776
Geoff Lang966c9402017-04-18 12:38:27 -0400777bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
778{
779 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
780 (size % blockSize == 0);
781}
782
Jamie Madillc29968b2016-01-20 11:17:23 -0500783bool ValidCompressedImageSize(const ValidationContext *context,
784 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400785 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500786 GLsizei width,
787 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400788{
Geoff Langca271392017-04-05 12:30:00 -0400789 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400790 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400791 {
792 return false;
793 }
794
Geoff Lang966c9402017-04-18 12:38:27 -0400795 if (width < 0 || height < 0)
796 {
797 return false;
798 }
799
800 if (CompressedTextureFormatRequiresExactSize(internalFormat))
801 {
802 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
803 // block size for level 0 but WebGL disallows this.
804 bool smallerThanBlockSizeAllowed =
805 level > 0 || !context->getExtensions().webglCompatibility;
806
807 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
808 smallerThanBlockSizeAllowed) ||
809 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
810 smallerThanBlockSizeAllowed))
811 {
812 return false;
813 }
814 }
815
816 return true;
817}
818
819bool ValidCompressedSubImageSize(const ValidationContext *context,
820 GLenum internalFormat,
821 GLint xoffset,
822 GLint yoffset,
823 GLsizei width,
824 GLsizei height,
825 size_t textureWidth,
826 size_t textureHeight)
827{
828 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
829 if (!formatInfo.compressed)
830 {
831 return false;
832 }
833
Geoff Lang44ff5a72017-02-03 15:15:43 -0500834 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400835 {
836 return false;
837 }
838
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500839 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400840 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500841 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400842 yoffset % formatInfo.compressedBlockHeight != 0)
843 {
844 return false;
845 }
846
847 // Allowed to either have data that is a multiple of block size or is smaller than the block
848 // size but fills the entire mip
849 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
850 static_cast<size_t>(width) == textureWidth &&
851 static_cast<size_t>(height) == textureHeight;
852 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
853 (height % formatInfo.compressedBlockHeight) == 0;
854 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400855 {
856 return false;
857 }
858 }
859
Geoff Langd4f180b2013-09-24 13:57:44 -0400860 return true;
861}
862
Geoff Langff5b2d52016-09-07 11:32:23 -0400863bool ValidImageDataSize(ValidationContext *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800864 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400865 GLsizei width,
866 GLsizei height,
867 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400868 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400869 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400870 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400871 GLsizei imageSize)
872{
Corentin Wallez336129f2017-10-17 15:55:40 -0400873 gl::Buffer *pixelUnpackBuffer =
874 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400875 if (pixelUnpackBuffer == nullptr && imageSize < 0)
876 {
877 // Checks are not required
878 return true;
879 }
880
881 // ...the data would be unpacked from the buffer object such that the memory reads required
882 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400883 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
884 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400885 const gl::Extents size(width, height, depth);
886 const auto &unpack = context->getGLState().getUnpackState();
887
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800888 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Geoff Langff5b2d52016-09-07 11:32:23 -0400889 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
890 if (endByteOrErr.isError())
891 {
892 context->handleError(endByteOrErr.getError());
893 return false;
894 }
895
896 GLuint endByte = endByteOrErr.getResult();
897
898 if (pixelUnpackBuffer)
899 {
900 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
901 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
902 checkedEndByte += checkedOffset;
903
904 if (!checkedEndByte.IsValid() ||
905 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
906 {
907 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500908 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -0400909 return false;
910 }
911 }
912 else
913 {
914 ASSERT(imageSize >= 0);
915 if (pixels == nullptr && imageSize != 0)
916 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500917 context->handleError(InvalidOperation()
918 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400919 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400920 }
921
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400922 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400923 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500924 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400925 return false;
926 }
927 }
928
929 return true;
930}
931
Geoff Lang37dde692014-01-31 16:34:54 -0500932bool ValidQueryType(const Context *context, GLenum queryType)
933{
He Yunchaoced53ae2016-11-29 15:00:51 +0800934 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
935 "GL extension enums not equal.");
936 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
937 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -0500938
939 switch (queryType)
940 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800941 case GL_ANY_SAMPLES_PASSED:
942 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400943 return context->getClientMajorVersion() >= 3 ||
944 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +0800945 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
946 return (context->getClientMajorVersion() >= 3);
947 case GL_TIME_ELAPSED_EXT:
948 return context->getExtensions().disjointTimerQuery;
949 case GL_COMMANDS_COMPLETED_CHROMIUM:
950 return context->getExtensions().syncQuery;
951 default:
952 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500953 }
954}
955
Geoff Lang2d62ab72017-03-23 16:54:40 -0400956bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
957 GLenum type,
958 GLboolean normalized,
959 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400960 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400961 bool pureInteger)
962{
963 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400964 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
965 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
966 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
967 // parameter exceeds 255.
968 constexpr GLsizei kMaxWebGLStride = 255;
969 if (stride > kMaxWebGLStride)
970 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500971 context->handleError(InvalidValue()
972 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -0400973 return false;
974 }
975
976 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
977 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
978 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
979 // or an INVALID_OPERATION error is generated.
980 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
981 size_t typeSize = GetVertexFormatTypeSize(internalType);
982
983 ASSERT(isPow2(typeSize) && typeSize > 0);
984 size_t sizeMask = (typeSize - 1);
985 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
986 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700987 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400988 return false;
989 }
990
991 if ((stride & sizeMask) != 0)
992 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700993 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400994 return false;
995 }
996
997 return true;
998}
999
Jamie Madillef300b12016-10-07 15:12:09 -04001000Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001001{
He Yunchaoced53ae2016-11-29 15:00:51 +08001002 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1003 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1004 // or program object and INVALID_OPERATION if the provided name identifies an object
1005 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001006
Dian Xiang769769a2015-09-09 15:20:08 -07001007 Program *validProgram = context->getProgram(id);
1008
1009 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001010 {
Dian Xiang769769a2015-09-09 15:20:08 -07001011 if (context->getShader(id))
1012 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001013 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001014 }
1015 else
1016 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001017 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001018 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001019 }
Dian Xiang769769a2015-09-09 15:20:08 -07001020
1021 return validProgram;
1022}
1023
Jamie Madillef300b12016-10-07 15:12:09 -04001024Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001025{
1026 // See ValidProgram for spec details.
1027
1028 Shader *validShader = context->getShader(id);
1029
1030 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001031 {
Dian Xiang769769a2015-09-09 15:20:08 -07001032 if (context->getProgram(id))
1033 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001034 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001035 }
1036 else
1037 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001038 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001039 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001040 }
Dian Xiang769769a2015-09-09 15:20:08 -07001041
1042 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001043}
1044
Geoff Langb1196682014-07-23 13:47:29 -04001045bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001046{
Geoff Langfa125c92017-10-24 13:01:46 -04001047 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001048 {
Geoff Langfa125c92017-10-24 13:01:46 -04001049 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1050 {
1051 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1052 return false;
1053 }
Jamie Madillb4472272014-07-03 10:38:55 -04001054
Geoff Langfa125c92017-10-24 13:01:46 -04001055 // Color attachment 0 is validated below because it is always valid
1056 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001057 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001058 {
Geoff Langfa125c92017-10-24 13:01:46 -04001059 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001060 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001061 }
1062 }
1063 else
1064 {
1065 switch (attachment)
1066 {
Geoff Langfa125c92017-10-24 13:01:46 -04001067 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001068 case GL_DEPTH_ATTACHMENT:
1069 case GL_STENCIL_ATTACHMENT:
1070 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001071
He Yunchaoced53ae2016-11-29 15:00:51 +08001072 case GL_DEPTH_STENCIL_ATTACHMENT:
1073 if (!context->getExtensions().webglCompatibility &&
1074 context->getClientMajorVersion() < 3)
1075 {
Geoff Langfa125c92017-10-24 13:01:46 -04001076 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001077 return false;
1078 }
1079 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001080
He Yunchaoced53ae2016-11-29 15:00:51 +08001081 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001082 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001083 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001084 }
1085 }
1086
1087 return true;
1088}
1089
Jamie Madille8fb6402017-02-14 17:56:40 -05001090bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001091 GLenum target,
1092 GLsizei samples,
1093 GLenum internalformat,
1094 GLsizei width,
1095 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001096{
1097 switch (target)
1098 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001099 case GL_RENDERBUFFER:
1100 break;
1101 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001102 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001103 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001104 }
1105
1106 if (width < 0 || height < 0 || samples < 0)
1107 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001108 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001109 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001110 }
1111
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001112 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1113 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1114
1115 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001116 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001117 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001118 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001119 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001120 }
1121
1122 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1123 // 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 -08001124 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001125 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1126 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001127 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001128 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001129 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001130 }
1131
Geoff Langaae65a42014-05-26 12:43:44 -04001132 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001133 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001134 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001135 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001136 }
1137
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001138 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001139 if (handle == 0)
1140 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001141 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001142 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001143 }
1144
1145 return true;
1146}
1147
He Yunchaoced53ae2016-11-29 15:00:51 +08001148bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1149 GLenum target,
1150 GLenum attachment,
1151 GLenum renderbuffertarget,
1152 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001153{
Geoff Lange8afa902017-09-27 15:00:43 -04001154 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001155 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001156 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001157 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001158 }
1159
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001160 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001161
Jamie Madill84115c92015-04-23 15:00:07 -04001162 ASSERT(framebuffer);
1163 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001164 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001165 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001166 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001167 }
1168
Jamie Madillb4472272014-07-03 10:38:55 -04001169 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001170 {
Jamie Madillb4472272014-07-03 10:38:55 -04001171 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001172 }
1173
Jamie Madillab9d82c2014-01-21 16:38:14 -05001174 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1175 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1176 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1177 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1178 if (renderbuffer != 0)
1179 {
1180 if (!context->getRenderbuffer(renderbuffer))
1181 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001182 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001183 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001184 }
1185 }
1186
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001187 return true;
1188}
1189
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001190bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001191 GLint srcX0,
1192 GLint srcY0,
1193 GLint srcX1,
1194 GLint srcY1,
1195 GLint dstX0,
1196 GLint dstY0,
1197 GLint dstX1,
1198 GLint dstY1,
1199 GLbitfield mask,
1200 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001201{
1202 switch (filter)
1203 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001204 case GL_NEAREST:
1205 break;
1206 case GL_LINEAR:
1207 break;
1208 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001209 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001210 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001211 }
1212
1213 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1214 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001215 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001216 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001217 }
1218
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001219 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1220 // color buffer, leaving only nearest being unfiltered from above
1221 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1222 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001223 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001224 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001225 }
1226
Jamie Madill51f40ec2016-06-15 14:06:00 -04001227 const auto &glState = context->getGLState();
1228 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1229 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001230
1231 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001232 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001233 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001234 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001235 }
1236
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001237 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001238 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001239 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001240 return false;
1241 }
1242
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001243 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001244 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001245 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001246 return false;
1247 }
1248
Qin Jiajiaaef92162018-02-27 13:51:44 +08001249 if (readFramebuffer->id() == drawFramebuffer->id())
1250 {
1251 context->handleError(InvalidOperation());
1252 return false;
1253 }
1254
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001255 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001256 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001257 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001258 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001259 }
1260
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001261 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1262
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001263 if (mask & GL_COLOR_BUFFER_BIT)
1264 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001265 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001266 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001267
He Yunchao66a41a22016-12-15 16:45:05 +08001268 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001269 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001270 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001271
Geoff Langa15472a2015-08-11 11:48:03 -04001272 for (size_t drawbufferIdx = 0;
1273 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001274 {
Geoff Langa15472a2015-08-11 11:48:03 -04001275 const FramebufferAttachment *attachment =
1276 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1277 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001278 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001279 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001280
Geoff Langb2f3d052013-08-13 12:49:27 -04001281 // The GL ES 3.0.2 spec (pg 193) states that:
1282 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001283 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1284 // as well
1285 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1286 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001287 // Changes with EXT_color_buffer_float:
1288 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001289 GLenum readComponentType = readFormat.info->componentType;
1290 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001291 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001292 readComponentType == GL_SIGNED_NORMALIZED);
1293 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1294 drawComponentType == GL_SIGNED_NORMALIZED);
1295
1296 if (extensions.colorBufferFloat)
1297 {
1298 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1299 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1300
1301 if (readFixedOrFloat != drawFixedOrFloat)
1302 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001303 context->handleError(InvalidOperation()
1304 << "If the read buffer contains fixed-point or "
1305 "floating-point values, the draw buffer must "
1306 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001307 return false;
1308 }
1309 }
1310 else if (readFixedPoint != drawFixedPoint)
1311 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001312 context->handleError(InvalidOperation()
1313 << "If the read buffer contains fixed-point values, "
1314 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001315 return false;
1316 }
1317
1318 if (readComponentType == GL_UNSIGNED_INT &&
1319 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001320 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001321 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001322 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001323 }
1324
Jamie Madill6163c752015-12-07 16:32:59 -05001325 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001326 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001327 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001328 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001329 }
1330
Jamie Madilla3944d42016-07-22 22:13:26 -04001331 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001332 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001333 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001334 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001335 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001336 }
Geoff Lange4915782017-04-12 15:19:07 -04001337
1338 if (context->getExtensions().webglCompatibility &&
1339 *readColorBuffer == *attachment)
1340 {
1341 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001342 InvalidOperation()
1343 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001344 return false;
1345 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001346 }
1347 }
1348
Jamie Madilla3944d42016-07-22 22:13:26 -04001349 if ((readFormat.info->componentType == GL_INT ||
1350 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1351 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001352 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001353 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001354 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001355 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001356 }
He Yunchao66a41a22016-12-15 16:45:05 +08001357 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1358 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1359 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1360 // situation is an application error that would lead to a crash in ANGLE.
1361 else if (drawFramebuffer->hasEnabledDrawBuffer())
1362 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001363 context->handleError(
1364 InvalidOperation()
1365 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001366 return false;
1367 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001368 }
1369
He Yunchaoced53ae2016-11-29 15:00:51 +08001370 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001371 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1372 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001373 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001374 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001375 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001376 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001377 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001378 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001379 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001380
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001381 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001382 {
Kenneth Russell69382852017-07-21 16:38:44 -04001383 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001385 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001386 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001387 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001388
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001389 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001390 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001391 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001392 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001393 }
Geoff Lange4915782017-04-12 15:19:07 -04001394
1395 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001397 context->handleError(
1398 InvalidOperation()
1399 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001400 return false;
1401 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001402 }
He Yunchao66a41a22016-12-15 16:45:05 +08001403 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1404 else if (drawBuffer)
1405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001406 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1407 "depth/stencil attachment of a "
1408 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001409 return false;
1410 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001411 }
1412 }
1413
Martin Radeva3ed4572017-07-27 18:29:37 +03001414 // ANGLE_multiview, Revision 1:
1415 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1416 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1417 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1418 {
1419 context->handleError(InvalidFramebufferOperation()
1420 << "Attempt to read from a multi-view framebuffer.");
1421 return false;
1422 }
1423 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1424 {
1425 context->handleError(InvalidFramebufferOperation()
1426 << "Attempt to write to a multi-view framebuffer.");
1427 return false;
1428 }
1429
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001430 return true;
1431}
1432
Jamie Madill4928b7c2017-06-20 12:57:39 -04001433bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001434 GLint x,
1435 GLint y,
1436 GLsizei width,
1437 GLsizei height,
1438 GLenum format,
1439 GLenum type,
1440 GLsizei bufSize,
1441 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001442 GLsizei *columns,
1443 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001444 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001445{
1446 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001447 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001448 return false;
1449 }
1450
Geoff Lang62fce5b2016-09-30 10:46:35 -04001451 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001452 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001453 {
Geoff Langb1196682014-07-23 13:47:29 -04001454 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001455 }
1456
Geoff Lang62fce5b2016-09-30 10:46:35 -04001457 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001458 {
Geoff Langb1196682014-07-23 13:47:29 -04001459 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001460 }
1461
Jamie Madillc29968b2016-01-20 11:17:23 -05001462 return true;
1463}
1464
1465bool ValidateReadnPixelsEXT(Context *context,
1466 GLint x,
1467 GLint y,
1468 GLsizei width,
1469 GLsizei height,
1470 GLenum format,
1471 GLenum type,
1472 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001473 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001474{
1475 if (bufSize < 0)
1476 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001477 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001478 return false;
1479 }
1480
Geoff Lang62fce5b2016-09-30 10:46:35 -04001481 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001482 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001483}
Jamie Madill26e91952014-03-05 15:01:27 -05001484
Jamie Madill4928b7c2017-06-20 12:57:39 -04001485bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001486 GLint x,
1487 GLint y,
1488 GLsizei width,
1489 GLsizei height,
1490 GLenum format,
1491 GLenum type,
1492 GLsizei bufSize,
1493 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001494 GLsizei *columns,
1495 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001496 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001497{
1498 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001499 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001500 return false;
1501 }
1502
Geoff Lange93daba2017-03-30 13:54:40 -04001503 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1504 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001505 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001506 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001507 }
1508
Geoff Lang62fce5b2016-09-30 10:46:35 -04001509 if (!ValidateRobustBufferSize(context, bufSize, *length))
1510 {
1511 return false;
1512 }
1513
1514 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001515}
1516
Jamie Madillf0e04492017-08-26 15:28:42 -04001517bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001518{
1519 if (!context->getExtensions().occlusionQueryBoolean &&
1520 !context->getExtensions().disjointTimerQuery)
1521 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001522 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001523 return false;
1524 }
1525
Olli Etuaho41997e72016-03-10 13:38:39 +02001526 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001527}
1528
Jamie Madillf0e04492017-08-26 15:28:42 -04001529bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001530{
1531 if (!context->getExtensions().occlusionQueryBoolean &&
1532 !context->getExtensions().disjointTimerQuery)
1533 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001534 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001535 return false;
1536 }
1537
Olli Etuaho41997e72016-03-10 13:38:39 +02001538 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001539}
1540
Jamie Madillf0e04492017-08-26 15:28:42 -04001541bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1542{
1543 if (!context->getExtensions().occlusionQueryBoolean &&
1544 !context->getExtensions().disjointTimerQuery)
1545 {
1546 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1547 return false;
1548 }
1549
1550 return true;
1551}
1552
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001553bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001554{
1555 if (!ValidQueryType(context, target))
1556 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001557 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001558 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001559 }
1560
1561 if (id == 0)
1562 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001563 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001564 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001565 }
1566
1567 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1568 // of zero, if the active query object name for <target> is non-zero (for the
1569 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1570 // the active query for either target is non-zero), if <id> is the name of an
1571 // existing query object whose type does not match <target>, or if <id> is the
1572 // active query object name for any query type, the error INVALID_OPERATION is
1573 // generated.
1574
1575 // Ensure no other queries are active
1576 // NOTE: If other queries than occlusion are supported, we will need to check
1577 // separately that:
1578 // a) The query ID passed is not the current active query for any target/type
1579 // b) There are no active queries for the requested target (and in the case
1580 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1581 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001582
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001583 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001584 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001585 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001586 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001587 }
1588
1589 Query *queryObject = context->getQuery(id, true, target);
1590
1591 // check that name was obtained with glGenQueries
1592 if (!queryObject)
1593 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001594 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001595 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001596 }
1597
1598 // check for type mismatch
1599 if (queryObject->getType() != target)
1600 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001601 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001602 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001603 }
1604
1605 return true;
1606}
1607
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001608bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1609{
1610 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001611 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001612 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001613 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001614 return false;
1615 }
1616
1617 return ValidateBeginQueryBase(context, target, id);
1618}
1619
1620bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001621{
1622 if (!ValidQueryType(context, target))
1623 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001624 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001625 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001626 }
1627
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001628 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001629
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001630 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001631 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001632 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001633 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001634 }
1635
Jamie Madill45c785d2014-05-13 14:09:34 -04001636 return true;
1637}
1638
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001639bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1640{
1641 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001642 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001643 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001644 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001645 return false;
1646 }
1647
1648 return ValidateEndQueryBase(context, target);
1649}
1650
1651bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1652{
1653 if (!context->getExtensions().disjointTimerQuery)
1654 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001655 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001656 return false;
1657 }
1658
1659 if (target != GL_TIMESTAMP_EXT)
1660 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001661 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001662 return false;
1663 }
1664
1665 Query *queryObject = context->getQuery(id, true, target);
1666 if (queryObject == nullptr)
1667 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001668 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001669 return false;
1670 }
1671
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001672 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001673 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001674 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001675 return false;
1676 }
1677
1678 return true;
1679}
1680
Geoff Lang2186c382016-10-14 10:54:54 -04001681bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001682{
Geoff Lang2186c382016-10-14 10:54:54 -04001683 if (numParams)
1684 {
1685 *numParams = 0;
1686 }
1687
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001688 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1689 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001690 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001691 return false;
1692 }
1693
1694 switch (pname)
1695 {
1696 case GL_CURRENT_QUERY_EXT:
1697 if (target == GL_TIMESTAMP_EXT)
1698 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001699 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001700 return false;
1701 }
1702 break;
1703 case GL_QUERY_COUNTER_BITS_EXT:
1704 if (!context->getExtensions().disjointTimerQuery ||
1705 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1706 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001707 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001708 return false;
1709 }
1710 break;
1711 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001712 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001713 return false;
1714 }
1715
Geoff Lang2186c382016-10-14 10:54:54 -04001716 if (numParams)
1717 {
1718 // All queries return only one value
1719 *numParams = 1;
1720 }
1721
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001722 return true;
1723}
1724
1725bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1726{
1727 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001728 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001729 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001730 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001731 return false;
1732 }
1733
Geoff Lang2186c382016-10-14 10:54:54 -04001734 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001735}
1736
Geoff Lang2186c382016-10-14 10:54:54 -04001737bool ValidateGetQueryivRobustANGLE(Context *context,
1738 GLenum target,
1739 GLenum pname,
1740 GLsizei bufSize,
1741 GLsizei *length,
1742 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001743{
Geoff Lang2186c382016-10-14 10:54:54 -04001744 if (!ValidateRobustEntryPoint(context, bufSize))
1745 {
1746 return false;
1747 }
1748
1749 if (!ValidateGetQueryivBase(context, target, pname, length))
1750 {
1751 return false;
1752 }
1753
1754 if (!ValidateRobustBufferSize(context, bufSize, *length))
1755 {
1756 return false;
1757 }
1758
1759 return true;
1760}
1761
1762bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1763{
1764 if (numParams)
1765 {
1766 *numParams = 0;
1767 }
1768
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001769 Query *queryObject = context->getQuery(id, false, GL_NONE);
1770
1771 if (!queryObject)
1772 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001773 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001774 return false;
1775 }
1776
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001777 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001778 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001779 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001780 return false;
1781 }
1782
1783 switch (pname)
1784 {
1785 case GL_QUERY_RESULT_EXT:
1786 case GL_QUERY_RESULT_AVAILABLE_EXT:
1787 break;
1788
1789 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001790 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001791 return false;
1792 }
1793
Geoff Lang2186c382016-10-14 10:54:54 -04001794 if (numParams)
1795 {
1796 *numParams = 1;
1797 }
1798
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001799 return true;
1800}
1801
1802bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1803{
1804 if (!context->getExtensions().disjointTimerQuery)
1805 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001806 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001807 return false;
1808 }
Geoff Lang2186c382016-10-14 10:54:54 -04001809 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1810}
1811
1812bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1813 GLuint id,
1814 GLenum pname,
1815 GLsizei bufSize,
1816 GLsizei *length,
1817 GLint *params)
1818{
1819 if (!context->getExtensions().disjointTimerQuery)
1820 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001821 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001822 return false;
1823 }
1824
1825 if (!ValidateRobustEntryPoint(context, bufSize))
1826 {
1827 return false;
1828 }
1829
1830 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1831 {
1832 return false;
1833 }
1834
1835 if (!ValidateRobustBufferSize(context, bufSize, *length))
1836 {
1837 return false;
1838 }
1839
1840 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001841}
1842
1843bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1844{
1845 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001846 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001847 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001848 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001849 return false;
1850 }
Geoff Lang2186c382016-10-14 10:54:54 -04001851 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1852}
1853
1854bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1855 GLuint id,
1856 GLenum pname,
1857 GLsizei bufSize,
1858 GLsizei *length,
1859 GLuint *params)
1860{
1861 if (!context->getExtensions().disjointTimerQuery &&
1862 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1863 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001864 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001865 return false;
1866 }
1867
1868 if (!ValidateRobustEntryPoint(context, bufSize))
1869 {
1870 return false;
1871 }
1872
1873 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1874 {
1875 return false;
1876 }
1877
1878 if (!ValidateRobustBufferSize(context, bufSize, *length))
1879 {
1880 return false;
1881 }
1882
1883 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001884}
1885
1886bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1887{
1888 if (!context->getExtensions().disjointTimerQuery)
1889 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001890 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001891 return false;
1892 }
Geoff Lang2186c382016-10-14 10:54:54 -04001893 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1894}
1895
1896bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1897 GLuint id,
1898 GLenum pname,
1899 GLsizei bufSize,
1900 GLsizei *length,
1901 GLint64 *params)
1902{
1903 if (!context->getExtensions().disjointTimerQuery)
1904 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001905 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001906 return false;
1907 }
1908
1909 if (!ValidateRobustEntryPoint(context, bufSize))
1910 {
1911 return false;
1912 }
1913
1914 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1915 {
1916 return false;
1917 }
1918
1919 if (!ValidateRobustBufferSize(context, bufSize, *length))
1920 {
1921 return false;
1922 }
1923
1924 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001925}
1926
1927bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1928{
1929 if (!context->getExtensions().disjointTimerQuery)
1930 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001931 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001932 return false;
1933 }
Geoff Lang2186c382016-10-14 10:54:54 -04001934 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1935}
1936
1937bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1938 GLuint id,
1939 GLenum pname,
1940 GLsizei bufSize,
1941 GLsizei *length,
1942 GLuint64 *params)
1943{
1944 if (!context->getExtensions().disjointTimerQuery)
1945 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001946 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001947 return false;
1948 }
1949
1950 if (!ValidateRobustEntryPoint(context, bufSize))
1951 {
1952 return false;
1953 }
1954
1955 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1956 {
1957 return false;
1958 }
1959
1960 if (!ValidateRobustBufferSize(context, bufSize, *length))
1961 {
1962 return false;
1963 }
1964
1965 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001966}
1967
Jiajia Qin5451d532017-11-16 17:16:34 +08001968bool ValidateUniformCommonBase(ValidationContext *context,
1969 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05001970 GLint location,
1971 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08001972 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05001973{
Jiajia Qin5451d532017-11-16 17:16:34 +08001974 // TODO(Jiajia): Add image uniform check in future.
1975 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05001976 {
Jiajia Qin5451d532017-11-16 17:16:34 +08001977 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05001978 return false;
1979 }
1980
Jiajia Qin5451d532017-11-16 17:16:34 +08001981 if (!program)
1982 {
1983 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
1984 return false;
1985 }
1986
1987 if (!program->isLinked())
1988 {
1989 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
1990 return false;
1991 }
1992
1993 if (location == -1)
1994 {
1995 // Silently ignore the uniform command
1996 return false;
1997 }
1998
1999 const auto &uniformLocations = program->getUniformLocations();
2000 size_t castedLocation = static_cast<size_t>(location);
2001 if (castedLocation >= uniformLocations.size())
2002 {
2003 context->handleError(InvalidOperation() << "Invalid uniform location");
2004 return false;
2005 }
2006
2007 const auto &uniformLocation = uniformLocations[castedLocation];
2008 if (uniformLocation.ignored)
2009 {
2010 // Silently ignore the uniform command
2011 return false;
2012 }
2013
2014 if (!uniformLocation.used())
2015 {
2016 context->handleError(InvalidOperation());
2017 return false;
2018 }
2019
2020 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2021
2022 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2023 if (!uniform.isArray() && count > 1)
2024 {
2025 context->handleError(InvalidOperation());
2026 return false;
2027 }
2028
2029 *uniformOut = &uniform;
2030 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002031}
2032
Jiajia Qin5451d532017-11-16 17:16:34 +08002033bool ValidateUniform1ivValue(ValidationContext *context,
2034 GLenum uniformType,
2035 GLsizei count,
2036 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002037{
Jiajia Qin5451d532017-11-16 17:16:34 +08002038 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2039 // It is compatible with INT or BOOL.
2040 // Do these cheap tests first, for a little extra speed.
2041 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002042 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002043 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002044 }
2045
Jiajia Qin5451d532017-11-16 17:16:34 +08002046 if (IsSamplerType(uniformType))
2047 {
2048 // Check that the values are in range.
2049 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2050 for (GLsizei i = 0; i < count; ++i)
2051 {
2052 if (value[i] < 0 || value[i] >= max)
2053 {
2054 context->handleError(InvalidValue() << "sampler uniform value out of range");
2055 return false;
2056 }
2057 }
2058 return true;
2059 }
2060
2061 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2062 return false;
2063}
2064
2065bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2066{
2067 // Check that the value type is compatible with uniform type.
2068 // Do the cheaper test first, for a little extra speed.
2069 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2070 {
2071 return true;
2072 }
2073
2074 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2075 return false;
2076}
2077
2078bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2079{
2080 // Check that the value type is compatible with uniform type.
2081 if (valueType == uniformType)
2082 {
2083 return true;
2084 }
2085
2086 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2087 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002088}
2089
Jamie Madillc1d770e2017-04-13 17:31:24 -04002090bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002091{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002092 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002093 gl::Program *programObject = context->getGLState().getProgram();
2094 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2095 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002096}
2097
Jamie Madillbe849e42017-05-02 15:49:00 -04002098bool ValidateUniform1iv(ValidationContext *context,
2099 GLint location,
2100 GLsizei count,
2101 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002102{
2103 const LinkedUniform *uniform = nullptr;
2104 gl::Program *programObject = context->getGLState().getProgram();
2105 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2106 ValidateUniform1ivValue(context, uniform->type, count, value);
2107}
2108
Jamie Madillc1d770e2017-04-13 17:31:24 -04002109bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002110 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002111 GLint location,
2112 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002113 GLboolean transpose)
2114{
Geoff Lang92019432017-11-20 13:09:34 -05002115 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002116 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002117 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002118 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002119 }
2120
Jamie Madill62d31cb2015-09-11 13:25:51 -04002121 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002122 gl::Program *programObject = context->getGLState().getProgram();
2123 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2124 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002125}
2126
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002127bool ValidateStateQuery(ValidationContext *context,
2128 GLenum pname,
2129 GLenum *nativeType,
2130 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002131{
2132 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2133 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002134 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002135 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002136 }
2137
Jamie Madill0af26e12015-03-05 19:54:33 -05002138 const Caps &caps = context->getCaps();
2139
Jamie Madill893ab082014-05-16 16:56:10 -04002140 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2141 {
2142 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2143
Jamie Madill0af26e12015-03-05 19:54:33 -05002144 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002145 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002146 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002147 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002148 }
2149 }
2150
2151 switch (pname)
2152 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002153 case GL_TEXTURE_BINDING_2D:
2154 case GL_TEXTURE_BINDING_CUBE_MAP:
2155 case GL_TEXTURE_BINDING_3D:
2156 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002157 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002158 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002159 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2160 if (!context->getExtensions().textureRectangle)
2161 {
2162 context->handleError(InvalidEnum()
2163 << "ANGLE_texture_rectangle extension not present");
2164 return false;
2165 }
2166 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002167 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2168 if (!context->getExtensions().eglStreamConsumerExternal &&
2169 !context->getExtensions().eglImageExternal)
2170 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002171 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2172 "nor GL_OES_EGL_image_external "
2173 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002174 return false;
2175 }
2176 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002177
He Yunchaoced53ae2016-11-29 15:00:51 +08002178 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2179 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002180 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002181 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2182 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002183 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002184 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002185 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002186 }
2187
Jamie Madill51f40ec2016-06-15 14:06:00 -04002188 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2189 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002190
2191 if (framebuffer->getReadBufferState() == GL_NONE)
2192 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002193 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002194 return false;
2195 }
2196
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002197 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002198 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002199 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002200 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002201 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002202 }
2203 }
2204 break;
2205
He Yunchaoced53ae2016-11-29 15:00:51 +08002206 default:
2207 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002208 }
2209
2210 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002211 if (*numParams == 0)
2212 {
2213 return false;
2214 }
2215
2216 return true;
2217}
2218
2219bool ValidateRobustStateQuery(ValidationContext *context,
2220 GLenum pname,
2221 GLsizei bufSize,
2222 GLenum *nativeType,
2223 unsigned int *numParams)
2224{
2225 if (!ValidateRobustEntryPoint(context, bufSize))
2226 {
2227 return false;
2228 }
2229
2230 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2231 {
2232 return false;
2233 }
2234
2235 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002236 {
2237 return false;
2238 }
2239
2240 return true;
2241}
2242
Jamie Madillc29968b2016-01-20 11:17:23 -05002243bool ValidateCopyTexImageParametersBase(ValidationContext *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002244 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002245 GLint level,
2246 GLenum internalformat,
2247 bool isSubImage,
2248 GLint xoffset,
2249 GLint yoffset,
2250 GLint zoffset,
2251 GLint x,
2252 GLint y,
2253 GLsizei width,
2254 GLsizei height,
2255 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002256 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002257{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002258 TextureType texType = TextureTargetToType(target);
2259
Brandon Jones6cad5662017-06-14 13:25:13 -07002260 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002261 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002262 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2263 return false;
2264 }
2265
2266 if (width < 0 || height < 0)
2267 {
2268 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002269 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002270 }
2271
He Yunchaoced53ae2016-11-29 15:00:51 +08002272 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2273 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002274 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002275 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002276 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002277 }
2278
2279 if (border != 0)
2280 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002281 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002282 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002283 }
2284
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002285 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002286 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002287 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002288 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002289 }
2290
Jamie Madill51f40ec2016-06-15 14:06:00 -04002291 const auto &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002292 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002293 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002294 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002295 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002296 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002297 }
2298
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002299 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002300 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002301 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002302 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002303 }
2304
Martin Radev138064f2016-07-15 12:03:41 +03002305 if (readFramebuffer->getReadBufferState() == GL_NONE)
2306 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002307 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002308 return false;
2309 }
2310
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002311 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2312 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002313 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002314 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002315 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2316 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002317 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002318 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002319 return false;
2320 }
2321
Martin Radev04e2c3b2017-07-27 16:54:35 +03002322 // ANGLE_multiview spec, Revision 1:
2323 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2324 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2325 // is not NONE.
2326 if (source->getMultiviewLayout() != GL_NONE)
2327 {
2328 context->handleError(InvalidFramebufferOperation()
2329 << "The active read framebuffer object has multiview attachments.");
2330 return false;
2331 }
2332
Geoff Langaae65a42014-05-26 12:43:44 -04002333 const gl::Caps &caps = context->getCaps();
2334
Geoff Langaae65a42014-05-26 12:43:44 -04002335 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002336 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002337 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002338 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002339 maxDimension = caps.max2DTextureSize;
2340 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002341
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002342 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002343 maxDimension = caps.maxCubeMapTextureSize;
2344 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002345
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002346 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002347 maxDimension = caps.maxRectangleTextureSize;
2348 break;
2349
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002350 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002351 maxDimension = caps.max2DTextureSize;
2352 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002353
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002354 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002355 maxDimension = caps.max3DTextureSize;
2356 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002357
He Yunchaoced53ae2016-11-29 15:00:51 +08002358 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002359 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002360 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002361 }
2362
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002363 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002364 if (!texture)
2365 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002366 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002367 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002368 }
2369
Geoff Lang69cce582015-09-17 13:20:36 -04002370 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002371 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002372 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002373 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002374 }
2375
Geoff Langca271392017-04-05 12:30:00 -04002376 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002377 isSubImage ? *texture->getFormat(target, level).info
2378 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002379
Geoff Lang966c9402017-04-18 12:38:27 -04002380 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002381 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002382 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002383 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002384 }
2385
2386 if (isSubImage)
2387 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002388 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2389 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2390 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002391 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002392 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002393 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002394 }
2395 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002396 else
2397 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002398 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002399 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002400 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002401 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002402 }
2403
Geoff Langeb66a6e2016-10-31 13:06:12 -04002404 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002405 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002406 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002407 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002408 }
2409
2410 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002411 if (static_cast<int>(width) > maxLevelDimension ||
2412 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002413 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002414 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002415 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002416 }
2417 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002418
Jamie Madill0c8abca2016-07-22 20:21:26 -04002419 if (textureFormatOut)
2420 {
2421 *textureFormatOut = texture->getFormat(target, level);
2422 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002423
2424 // Detect texture copying feedback loops for WebGL.
2425 if (context->getExtensions().webglCompatibility)
2426 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002427 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002428 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002429 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002430 return false;
2431 }
2432 }
2433
Jamie Madill560a8d82014-05-21 13:06:20 -04002434 return true;
2435}
2436
Jiajia Qind9671222016-11-29 16:30:31 +08002437bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002438{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002439 switch (mode)
2440 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002441 case GL_POINTS:
2442 case GL_LINES:
2443 case GL_LINE_LOOP:
2444 case GL_LINE_STRIP:
2445 case GL_TRIANGLES:
2446 case GL_TRIANGLE_STRIP:
2447 case GL_TRIANGLE_FAN:
2448 break;
2449 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002450 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002451 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002452 }
2453
Jamie Madill250d33f2014-06-06 17:09:03 -04002454 if (count < 0)
2455 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002456 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002457 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002458 }
2459
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002460 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002461
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002462 const Extensions &extensions = context->getExtensions();
2463
2464 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2465 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2466 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2467 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002468 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002469 // Check for mapped buffers
2470 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002471 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002472 {
2473 context->handleError(InvalidOperation());
2474 return false;
2475 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002476 }
2477
Jamie Madillcbcde722017-01-06 14:50:00 -05002478 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2479 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002480 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002481 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002482 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002483 const FramebufferAttachment *dsAttachment =
2484 framebuffer->getStencilOrDepthStencilAttachment();
2485 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002486 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002487 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002488
2489 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2490 bool differentWritemasks =
2491 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2492 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2493 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2494 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2495
2496 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002497 {
Martin Radevffe754b2017-07-31 10:38:07 +03002498 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002499 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002500 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2501 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002502 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002503 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002504 return false;
2505 }
Jamie Madillac528012014-06-20 13:21:23 -04002506 }
2507
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002508 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002509 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002510 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002511 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002512 }
2513
Geoff Lang7dd2e102014-11-10 15:19:26 -05002514 gl::Program *program = state.getProgram();
2515 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002516 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002517 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002518 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002519 }
2520
Yunchao Hecddcb592017-11-13 15:27:35 +08002521 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2522 // vertex shader stage or fragment shader stage is a undefined behaviour.
2523 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2524 // produce undefined result.
Yunchao Heece12532017-11-21 15:50:21 +08002525 if (!program->hasLinkedVertexShader() || !program->hasLinkedFragmentShader())
Yunchao Hecddcb592017-11-13 15:27:35 +08002526 {
2527 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2528 "vertex shader stage or fragment shader stage.");
2529 return false;
2530 }
2531
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002532 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002533 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002534 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002535 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002536 }
2537
Martin Radevffe754b2017-07-31 10:38:07 +03002538 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002539 {
Martin Radevda8e2572017-09-12 17:21:16 +03002540 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002541 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002542 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002543 {
2544 context->handleError(InvalidOperation() << "The number of views in the active program "
2545 "and draw framebuffer does not match.");
2546 return false;
2547 }
Martin Radev7e69f762017-07-27 14:54:13 +03002548
2549 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2550 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2551 framebufferNumViews > 1)
2552 {
2553 context->handleError(InvalidOperation()
2554 << "There is an active transform feedback object "
2555 "when the number of views in the active draw "
2556 "framebuffer is greater than 1.");
2557 return false;
2558 }
Martin Radevffe754b2017-07-31 10:38:07 +03002559
2560 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2561 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2562 {
2563 context->handleError(InvalidOperation() << "There is an active query for target "
2564 "GL_TIME_ELAPSED_EXT when the number of "
2565 "views in the active draw framebuffer is "
2566 "greater than 1.");
2567 return false;
2568 }
Martin Radev7cf61662017-07-26 17:10:53 +03002569 }
2570
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002571 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002572 for (unsigned int uniformBlockIndex = 0;
2573 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002574 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002575 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002576 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002577 const OffsetBindingPointer<Buffer> &uniformBuffer =
2578 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002579
Geoff Lang5d124a62015-09-15 13:03:27 -04002580 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002581 {
2582 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002583 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002584 InvalidOperation()
2585 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002586 return false;
2587 }
2588
Geoff Lang5d124a62015-09-15 13:03:27 -04002589 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002590 if (uniformBufferSize == 0)
2591 {
2592 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002593 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002594 }
2595
Jamie Madill62d31cb2015-09-11 13:25:51 -04002596 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002597 {
2598 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002599 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002600 InvalidOperation()
2601 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002602 return false;
2603 }
2604 }
2605
Geoff Lange0cff192017-05-30 13:04:56 -04002606 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002607 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002608 {
Geoff Lange0cff192017-05-30 13:04:56 -04002609 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002610 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2611 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002612 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002613 return false;
2614 }
Geoff Lange0cff192017-05-30 13:04:56 -04002615
Geoff Lang9ab5b822017-05-30 16:19:23 -04002616 // Detect that the vertex shader input types match the attribute types
2617 if (!ValidateVertexShaderAttributeTypeMatch(context))
2618 {
2619 return false;
2620 }
2621
Geoff Lange0cff192017-05-30 13:04:56 -04002622 // Detect that the color buffer types match the fragment shader output types
2623 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2624 {
2625 return false;
2626 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002627 }
2628
Jamie Madill9fdaa492018-02-16 10:52:11 -05002629 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002630}
2631
Jamie Madillc1d770e2017-04-13 17:31:24 -04002632bool ValidateDrawArraysCommon(ValidationContext *context,
2633 GLenum mode,
2634 GLint first,
2635 GLsizei count,
2636 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002637{
Jamie Madillfd716582014-06-06 17:09:04 -04002638 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002639 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002640 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002641 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002642 }
2643
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002644 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002645 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002646 if (curTransformFeedback && curTransformFeedback->isActive() &&
2647 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002648 {
2649 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002650 // that does not match the current transform feedback object's draw mode (if transform
2651 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002652 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002653 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002654 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002655 }
2656
Jiajia Qind9671222016-11-29 16:30:31 +08002657 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002658 {
2659 return false;
2660 }
2661
Corentin Wallez71168a02016-12-19 15:11:18 -08002662 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002663 // - first < 0 has been checked as an error condition.
2664 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002665 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002666 ASSERT(first >= 0);
2667 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002668 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002669 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2670 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2671 {
2672 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2673 return false;
2674 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002675
Jamie Madill9fdaa492018-02-16 10:52:11 -05002676 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2677 {
2678 return false;
2679 }
Jamie Madillfd716582014-06-06 17:09:04 -04002680 }
2681
2682 return true;
2683}
2684
He Yunchaoced53ae2016-11-29 15:00:51 +08002685bool ValidateDrawArraysInstancedANGLE(Context *context,
2686 GLenum mode,
2687 GLint first,
2688 GLsizei count,
2689 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002690{
Geoff Lang63c5a592017-09-27 14:08:16 -04002691 if (!context->getExtensions().instancedArrays)
2692 {
2693 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2694 return false;
2695 }
2696
Corentin Wallez170efbf2017-05-02 13:45:01 -04002697 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002698 {
2699 return false;
2700 }
2701
Corentin Wallez0dc97812017-06-22 14:38:44 -04002702 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002703}
2704
Jiajia Qind9671222016-11-29 16:30:31 +08002705bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002706{
Jamie Madill250d33f2014-06-06 17:09:03 -04002707 switch (type)
2708 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002709 case GL_UNSIGNED_BYTE:
2710 case GL_UNSIGNED_SHORT:
2711 break;
2712 case GL_UNSIGNED_INT:
2713 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2714 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002715 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002716 return false;
2717 }
2718 break;
2719 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002720 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002721 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002722 }
2723
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002724 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002725
2726 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002727 if (curTransformFeedback && curTransformFeedback->isActive() &&
2728 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002729 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002730 // It is an invalid operation to call DrawElements, DrawRangeElements or
2731 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002732 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002733 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002734 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002735 }
2736
Jiajia Qind9671222016-11-29 16:30:31 +08002737 return true;
2738}
2739
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002740bool ValidateDrawElementsCommon(ValidationContext *context,
2741 GLenum mode,
2742 GLsizei count,
2743 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002744 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002745 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002746{
2747 if (!ValidateDrawElementsBase(context, type))
2748 return false;
2749
2750 const State &state = context->getGLState();
2751
Corentin Wallez170efbf2017-05-02 13:45:01 -04002752 if (!ValidateDrawBase(context, mode, count))
2753 {
2754 return false;
2755 }
2756
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002757 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2758 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2759 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2760 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002761 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002762 // Check for mapped buffers
2763 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002764 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002765 {
2766 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2767 return false;
2768 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002769 }
2770
He Yunchaoced53ae2016-11-29 15:00:51 +08002771 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002772 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002773
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002774 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2775
2776 if (context->getExtensions().webglCompatibility)
2777 {
2778 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2779 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2780 {
2781 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2782 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2783 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002784 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002785 return false;
2786 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002787
2788 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2789 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2790 // error is generated.
2791 if (reinterpret_cast<intptr_t>(indices) < 0)
2792 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002793 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002794 return false;
2795 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002796 }
2797
2798 if (context->getExtensions().webglCompatibility ||
2799 !context->getGLState().areClientArraysEnabled())
2800 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002801 if (!elementArrayBuffer && count > 0)
2802 {
2803 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2804 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2805 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002806 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002807 return false;
2808 }
2809 }
2810
Jamie Madill9fdaa492018-02-16 10:52:11 -05002811 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04002812 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002813 // This is an application error that would normally result in a crash, but we catch it and
2814 // return an error
2815 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
2816 return false;
2817 }
2818
2819 if (count > 0 && elementArrayBuffer)
2820 {
2821 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2822 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2823 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2824 constexpr uint64_t kMaxTypeSize = 8;
2825 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2826 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2827 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
2828
2829 uint64_t typeSize = typeBytes;
2830 uint64_t elementCount = static_cast<uint64_t>(count);
2831 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2832
2833 // Doing the multiplication here is overflow-safe
2834 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2835
2836 // The offset can be any value, check for overflows
2837 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2838 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04002839 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002840 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2841 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002842 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05002843
2844 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2845 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002846 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002847 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
2848 return false;
2849 }
2850
2851 ASSERT(isPow2(typeSize) && typeSize > 0);
2852 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
2853 {
2854 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04002855 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002856 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002857 }
2858
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002859 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002860 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002861 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2862 // access is enabled.
2863 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2864 {
2865 return false;
2866 }
2867 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05002868 else if (count == 0)
2869 {
2870 // ValidateDrawAttribs also does some extra validation that is independent of the vertex
2871 // count.
2872 if (!ValidateDrawAttribs(context, 0, 0, 0))
2873 {
2874 return false;
2875 }
2876 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002877 else
2878 {
2879 // Use the parameter buffer to retrieve and cache the index range.
2880 const auto &params = context->getParams<HasIndexRange>();
2881 const auto &indexRangeOpt = params.getIndexRange();
2882 if (!indexRangeOpt.valid())
2883 {
2884 // Unexpected error.
2885 return false;
2886 }
2887
2888 // If we use an index greater than our maximum supported index range, return an error.
2889 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2890 // return an error if possible here.
2891 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2892 {
2893 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2894 return false;
2895 }
2896
2897 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2898 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2899 {
2900 return false;
2901 }
2902
2903 // No op if there are no real indices in the index data (all are primitive restart).
2904 return (indexRangeOpt.value().vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002905 }
2906
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002907 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002908}
2909
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002910bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2911 GLenum mode,
2912 GLsizei count,
2913 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002914 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002915 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002916{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002917 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002918}
2919
Geoff Lang3edfe032015-09-04 16:38:24 -04002920bool ValidateDrawElementsInstancedANGLE(Context *context,
2921 GLenum mode,
2922 GLsizei count,
2923 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002924 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002925 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002926{
Geoff Lang63c5a592017-09-27 14:08:16 -04002927 if (!context->getExtensions().instancedArrays)
2928 {
2929 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2930 return false;
2931 }
2932
Corentin Wallez170efbf2017-05-02 13:45:01 -04002933 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002934 {
2935 return false;
2936 }
2937
Corentin Wallez0dc97812017-06-22 14:38:44 -04002938 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002939}
2940
He Yunchaoced53ae2016-11-29 15:00:51 +08002941bool ValidateFramebufferTextureBase(Context *context,
2942 GLenum target,
2943 GLenum attachment,
2944 GLuint texture,
2945 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002946{
Geoff Lange8afa902017-09-27 15:00:43 -04002947 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002948 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002949 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002950 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002951 }
2952
2953 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002954 {
2955 return false;
2956 }
2957
Jamie Madill55ec3b12014-07-03 10:38:57 -04002958 if (texture != 0)
2959 {
2960 gl::Texture *tex = context->getTexture(texture);
2961
Luc Ferronadcf0ae2018-01-24 08:27:37 -05002962 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002963 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002964 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002965 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002966 }
2967
2968 if (level < 0)
2969 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002970 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002971 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002972 }
2973 }
2974
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002975 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002976 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002977
Jamie Madill84115c92015-04-23 15:00:07 -04002978 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002979 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002980 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002981 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002982 }
2983
2984 return true;
2985}
2986
Geoff Langb1196682014-07-23 13:47:29 -04002987bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04002988{
2989 if (program == 0)
2990 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002991 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002992 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002993 }
2994
Dian Xiang769769a2015-09-09 15:20:08 -07002995 gl::Program *programObject = GetValidProgram(context, program);
2996 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05002997 {
2998 return false;
2999 }
3000
Jamie Madill0063c512014-08-25 15:47:53 -04003001 if (!programObject || !programObject->isLinked())
3002 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003003 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003004 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003005 }
3006
Geoff Lang7dd2e102014-11-10 15:19:26 -05003007 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003008 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003009 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003010 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003011 }
3012
Jamie Madill0063c512014-08-25 15:47:53 -04003013 return true;
3014}
3015
Geoff Langf41d0ee2016-10-07 13:04:23 -04003016static bool ValidateSizedGetUniform(Context *context,
3017 GLuint program,
3018 GLint location,
3019 GLsizei bufSize,
3020 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003021{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003022 if (length)
3023 {
3024 *length = 0;
3025 }
3026
Jamie Madill78f41802014-08-25 15:47:55 -04003027 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003028 {
Jamie Madill78f41802014-08-25 15:47:55 -04003029 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003030 }
3031
Geoff Langf41d0ee2016-10-07 13:04:23 -04003032 if (bufSize < 0)
3033 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003034 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003035 return false;
3036 }
3037
Jamie Madilla502c742014-08-28 17:19:13 -04003038 gl::Program *programObject = context->getProgram(program);
3039 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003040
Jamie Madill78f41802014-08-25 15:47:55 -04003041 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003042 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003043 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003044 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003045 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003046 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003047 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003048 }
3049
Geoff Langf41d0ee2016-10-07 13:04:23 -04003050 if (length)
3051 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003052 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003053 }
3054
Jamie Madill0063c512014-08-25 15:47:53 -04003055 return true;
3056}
3057
He Yunchaoced53ae2016-11-29 15:00:51 +08003058bool ValidateGetnUniformfvEXT(Context *context,
3059 GLuint program,
3060 GLint location,
3061 GLsizei bufSize,
3062 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003063{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003064 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003065}
3066
He Yunchaoced53ae2016-11-29 15:00:51 +08003067bool ValidateGetnUniformivEXT(Context *context,
3068 GLuint program,
3069 GLint location,
3070 GLsizei bufSize,
3071 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003072{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003073 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3074}
3075
3076bool ValidateGetUniformfvRobustANGLE(Context *context,
3077 GLuint program,
3078 GLint location,
3079 GLsizei bufSize,
3080 GLsizei *length,
3081 GLfloat *params)
3082{
3083 if (!ValidateRobustEntryPoint(context, bufSize))
3084 {
3085 return false;
3086 }
3087
3088 // bufSize is validated in ValidateSizedGetUniform
3089 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3090}
3091
3092bool ValidateGetUniformivRobustANGLE(Context *context,
3093 GLuint program,
3094 GLint location,
3095 GLsizei bufSize,
3096 GLsizei *length,
3097 GLint *params)
3098{
3099 if (!ValidateRobustEntryPoint(context, bufSize))
3100 {
3101 return false;
3102 }
3103
3104 // bufSize is validated in ValidateSizedGetUniform
3105 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3106}
3107
3108bool ValidateGetUniformuivRobustANGLE(Context *context,
3109 GLuint program,
3110 GLint location,
3111 GLsizei bufSize,
3112 GLsizei *length,
3113 GLuint *params)
3114{
3115 if (!ValidateRobustEntryPoint(context, bufSize))
3116 {
3117 return false;
3118 }
3119
3120 if (context->getClientMajorVersion() < 3)
3121 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003122 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003123 return false;
3124 }
3125
3126 // bufSize is validated in ValidateSizedGetUniform
3127 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003128}
3129
He Yunchaoced53ae2016-11-29 15:00:51 +08003130bool ValidateDiscardFramebufferBase(Context *context,
3131 GLenum target,
3132 GLsizei numAttachments,
3133 const GLenum *attachments,
3134 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003135{
3136 if (numAttachments < 0)
3137 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003138 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003139 return false;
3140 }
3141
3142 for (GLsizei i = 0; i < numAttachments; ++i)
3143 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003144 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003145 {
3146 if (defaultFramebuffer)
3147 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003148 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003149 return false;
3150 }
3151
3152 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3153 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003154 context->handleError(InvalidOperation() << "Requested color attachment is "
3155 "greater than the maximum supported "
3156 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003157 return false;
3158 }
3159 }
3160 else
3161 {
3162 switch (attachments[i])
3163 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003164 case GL_DEPTH_ATTACHMENT:
3165 case GL_STENCIL_ATTACHMENT:
3166 case GL_DEPTH_STENCIL_ATTACHMENT:
3167 if (defaultFramebuffer)
3168 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003169 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3170 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003171 return false;
3172 }
3173 break;
3174 case GL_COLOR:
3175 case GL_DEPTH:
3176 case GL_STENCIL:
3177 if (!defaultFramebuffer)
3178 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003179 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3180 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003181 return false;
3182 }
3183 break;
3184 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003185 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003186 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003187 }
3188 }
3189 }
3190
3191 return true;
3192}
3193
Austin Kinross6ee1e782015-05-29 17:05:37 -07003194bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3195{
Jamie Madill007530e2017-12-28 14:27:04 -05003196 if (!context->getExtensions().debugMarker)
3197 {
3198 // The debug marker calls should not set error state
3199 // However, it seems reasonable to set an error state if the extension is not enabled
3200 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3201 return false;
3202 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003203
Jamie Madill007530e2017-12-28 14:27:04 -05003204 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003205 if (length < 0)
3206 {
3207 return false;
3208 }
3209
3210 if (marker == nullptr)
3211 {
3212 return false;
3213 }
3214
3215 return true;
3216}
3217
3218bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3219{
Jamie Madill007530e2017-12-28 14:27:04 -05003220 if (!context->getExtensions().debugMarker)
3221 {
3222 // The debug marker calls should not set error state
3223 // However, it seems reasonable to set an error state if the extension is not enabled
3224 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3225 return false;
3226 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003227
Jamie Madill007530e2017-12-28 14:27:04 -05003228 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003229 if (length < 0)
3230 {
3231 return false;
3232 }
3233
3234 if (length > 0 && marker == nullptr)
3235 {
3236 return false;
3237 }
3238
3239 return true;
3240}
3241
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003242bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003243{
Geoff Langa8406172015-07-21 16:53:39 -04003244 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3245 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003246 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003247 return false;
3248 }
3249
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003250 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003251 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003252 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003253 if (!context->getExtensions().eglImage)
3254 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003255 context->handleError(InvalidEnum()
3256 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003257 }
3258 break;
3259
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003260 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003261 if (!context->getExtensions().eglImageExternal)
3262 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003263 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3264 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003265 }
Geoff Langa8406172015-07-21 16:53:39 -04003266 break;
3267
3268 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003269 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003270 return false;
3271 }
3272
Jamie Madill007530e2017-12-28 14:27:04 -05003273 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3274
Jamie Madill61e16b42017-06-19 11:13:23 -04003275 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003276 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003277 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003278 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003279 return false;
3280 }
3281
Jamie Madill007530e2017-12-28 14:27:04 -05003282 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003283 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003284 context->handleError(InvalidOperation()
3285 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003286 return false;
3287 }
3288
Geoff Langca271392017-04-05 12:30:00 -04003289 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003290 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003291 if (!textureCaps.texturable)
3292 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003293 context->handleError(InvalidOperation()
3294 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003295 return false;
3296 }
3297
Geoff Langdcab33b2015-07-21 13:03:16 -04003298 return true;
3299}
3300
3301bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003302 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003303 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003304{
Geoff Langa8406172015-07-21 16:53:39 -04003305 if (!context->getExtensions().eglImage)
3306 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003307 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003308 return false;
3309 }
3310
3311 switch (target)
3312 {
3313 case GL_RENDERBUFFER:
3314 break;
3315
3316 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003317 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003318 return false;
3319 }
3320
Jamie Madill007530e2017-12-28 14:27:04 -05003321 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3322
Jamie Madill61e16b42017-06-19 11:13:23 -04003323 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003324 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003325 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003326 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003327 return false;
3328 }
3329
Geoff Langca271392017-04-05 12:30:00 -04003330 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003331 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003332 if (!textureCaps.renderable)
3333 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003334 context->handleError(InvalidOperation()
3335 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003336 return false;
3337 }
3338
Geoff Langdcab33b2015-07-21 13:03:16 -04003339 return true;
3340}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003341
3342bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3343{
Geoff Lang36167ab2015-12-07 10:27:14 -05003344 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003345 {
3346 // The default VAO should always exist
3347 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003348 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003349 return false;
3350 }
3351
3352 return true;
3353}
3354
Geoff Langc5629752015-12-07 16:29:04 -05003355bool ValidateProgramBinaryBase(Context *context,
3356 GLuint program,
3357 GLenum binaryFormat,
3358 const void *binary,
3359 GLint length)
3360{
3361 Program *programObject = GetValidProgram(context, program);
3362 if (programObject == nullptr)
3363 {
3364 return false;
3365 }
3366
3367 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3368 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3369 programBinaryFormats.end())
3370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003371 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003372 return false;
3373 }
3374
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003375 if (context->hasActiveTransformFeedback(program))
3376 {
3377 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003378 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3379 "is associated with an active transform "
3380 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003381 return false;
3382 }
3383
Geoff Langc5629752015-12-07 16:29:04 -05003384 return true;
3385}
3386
3387bool ValidateGetProgramBinaryBase(Context *context,
3388 GLuint program,
3389 GLsizei bufSize,
3390 GLsizei *length,
3391 GLenum *binaryFormat,
3392 void *binary)
3393{
3394 Program *programObject = GetValidProgram(context, program);
3395 if (programObject == nullptr)
3396 {
3397 return false;
3398 }
3399
3400 if (!programObject->isLinked())
3401 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003402 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003403 return false;
3404 }
3405
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003406 if (context->getCaps().programBinaryFormats.empty())
3407 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003408 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003409 return false;
3410 }
3411
Geoff Langc5629752015-12-07 16:29:04 -05003412 return true;
3413}
Jamie Madillc29968b2016-01-20 11:17:23 -05003414
Jamie Madillc29968b2016-01-20 11:17:23 -05003415bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3416{
3417 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003418 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003419 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003420 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3421 return false;
3422 }
3423 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3424 {
3425 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003426 return false;
3427 }
3428
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003429 ASSERT(context->getGLState().getDrawFramebuffer());
3430 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003431 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3432
3433 // This should come first before the check for the default frame buffer
3434 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3435 // rather than INVALID_OPERATION
3436 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3437 {
3438 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3439
3440 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003441 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3442 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003443 {
3444 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003445 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3446 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3447 // 3.1 is still a bit ambiguous about the error, but future specs are
3448 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003449 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003450 return false;
3451 }
3452 else if (bufs[colorAttachment] >= maxColorAttachment)
3453 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003454 context->handleError(InvalidOperation()
3455 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003456 return false;
3457 }
3458 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3459 frameBufferId != 0)
3460 {
3461 // INVALID_OPERATION-GL is bound to buffer and ith argument
3462 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003463 context->handleError(InvalidOperation()
3464 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003465 return false;
3466 }
3467 }
3468
3469 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3470 // and n is not 1 or bufs is bound to value other than BACK and NONE
3471 if (frameBufferId == 0)
3472 {
3473 if (n != 1)
3474 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003475 context->handleError(InvalidOperation()
3476 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003477 return false;
3478 }
3479
3480 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3481 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003482 context->handleError(
3483 InvalidOperation()
3484 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003485 return false;
3486 }
3487 }
3488
3489 return true;
3490}
3491
Geoff Lang496c02d2016-10-20 11:38:11 -07003492bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003493 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003494 GLenum pname,
3495 GLsizei *length,
3496 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003497{
Geoff Lang496c02d2016-10-20 11:38:11 -07003498 if (length)
3499 {
3500 *length = 0;
3501 }
3502
3503 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3504 {
3505 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003506 InvalidOperation()
3507 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003508 return false;
3509 }
3510
Corentin Walleze4477002017-12-01 14:39:58 -05003511 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003512 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003513 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003514 return false;
3515 }
3516
Geoff Lang496c02d2016-10-20 11:38:11 -07003517 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003518 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003519 case GL_BUFFER_MAP_POINTER:
3520 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003521
Geoff Lang496c02d2016-10-20 11:38:11 -07003522 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003523 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003524 return false;
3525 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003526
3527 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3528 // target bound to zero generate an INVALID_OPERATION error."
3529 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003530 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003531 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003532 context->handleError(InvalidOperation()
3533 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003534 return false;
3535 }
3536
Geoff Lang496c02d2016-10-20 11:38:11 -07003537 if (length)
3538 {
3539 *length = 1;
3540 }
3541
Olli Etuaho4f667482016-03-30 15:56:35 +03003542 return true;
3543}
3544
Corentin Wallez336129f2017-10-17 15:55:40 -04003545bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003546{
Corentin Walleze4477002017-12-01 14:39:58 -05003547 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003548 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003549 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003550 return false;
3551 }
3552
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003553 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003554
3555 if (buffer == nullptr || !buffer->isMapped())
3556 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003557 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003558 return false;
3559 }
3560
3561 return true;
3562}
3563
3564bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003565 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003566 GLintptr offset,
3567 GLsizeiptr length,
3568 GLbitfield access)
3569{
Corentin Walleze4477002017-12-01 14:39:58 -05003570 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003571 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003572 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003573 return false;
3574 }
3575
Brandon Jones6cad5662017-06-14 13:25:13 -07003576 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003577 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003578 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3579 return false;
3580 }
3581
3582 if (length < 0)
3583 {
3584 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003585 return false;
3586 }
3587
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003588 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003589
3590 if (!buffer)
3591 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003592 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003593 return false;
3594 }
3595
3596 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003597 CheckedNumeric<size_t> checkedOffset(offset);
3598 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003599
Jamie Madille2e406c2016-06-02 13:04:10 -04003600 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003601 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003602 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003603 return false;
3604 }
3605
3606 // Check for invalid bits in the mask
3607 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3608 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3609 GL_MAP_UNSYNCHRONIZED_BIT;
3610
3611 if (access & ~(allAccessBits))
3612 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003613 context->handleError(InvalidValue()
3614 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003615 return false;
3616 }
3617
3618 if (length == 0)
3619 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003620 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003621 return false;
3622 }
3623
3624 if (buffer->isMapped())
3625 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003626 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003627 return false;
3628 }
3629
3630 // Check for invalid bit combinations
3631 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3632 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003633 context->handleError(InvalidOperation()
3634 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003635 return false;
3636 }
3637
3638 GLbitfield writeOnlyBits =
3639 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3640
3641 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3642 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003643 context->handleError(InvalidOperation()
3644 << "Invalid access bits when mapping buffer for reading: 0x"
3645 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003646 return false;
3647 }
3648
3649 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3650 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003651 context->handleError(
3652 InvalidOperation()
3653 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003654 return false;
3655 }
Geoff Lang79f71042017-08-14 16:43:43 -04003656
3657 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003658}
3659
3660bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003661 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003662 GLintptr offset,
3663 GLsizeiptr length)
3664{
Brandon Jones6cad5662017-06-14 13:25:13 -07003665 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003666 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003667 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3668 return false;
3669 }
3670
3671 if (length < 0)
3672 {
3673 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003674 return false;
3675 }
3676
Corentin Walleze4477002017-12-01 14:39:58 -05003677 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003678 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003679 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003680 return false;
3681 }
3682
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003683 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003684
3685 if (buffer == nullptr)
3686 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003687 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003688 return false;
3689 }
3690
3691 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3692 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003693 context->handleError(InvalidOperation()
3694 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003695 return false;
3696 }
3697
3698 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003699 CheckedNumeric<size_t> checkedOffset(offset);
3700 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003701
Jamie Madille2e406c2016-06-02 13:04:10 -04003702 if (!checkedSize.IsValid() ||
3703 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003705 context->handleError(InvalidValue()
3706 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003707 return false;
3708 }
3709
3710 return true;
3711}
3712
Olli Etuaho41997e72016-03-10 13:38:39 +02003713bool ValidateGenOrDelete(Context *context, GLint n)
3714{
3715 if (n < 0)
3716 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003717 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003718 return false;
3719 }
3720 return true;
3721}
3722
Geoff Langff5b2d52016-09-07 11:32:23 -04003723bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3724{
3725 if (!context->getExtensions().robustClientMemory)
3726 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003727 context->handleError(InvalidOperation()
3728 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003729 return false;
3730 }
3731
3732 if (bufSize < 0)
3733 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003734 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003735 return false;
3736 }
3737
3738 return true;
3739}
3740
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003741bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3742{
3743 if (bufSize < numParams)
3744 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003745 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3746 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003747 return false;
3748 }
3749
3750 return true;
3751}
3752
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003753bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04003754 GLenum target,
3755 GLenum attachment,
3756 GLenum pname,
3757 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003758{
Geoff Lange8afa902017-09-27 15:00:43 -04003759 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003760 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003761 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003762 return false;
3763 }
3764
3765 int clientVersion = context->getClientMajorVersion();
3766
3767 switch (pname)
3768 {
3769 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3770 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3771 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3772 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3773 break;
3774
Martin Radeve5285d22017-07-14 16:23:53 +03003775 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3776 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3777 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3778 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3779 if (clientVersion < 3 || !context->getExtensions().multiview)
3780 {
3781 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3782 return false;
3783 }
3784 break;
3785
Geoff Langff5b2d52016-09-07 11:32:23 -04003786 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3787 if (clientVersion < 3 && !context->getExtensions().sRGB)
3788 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003789 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003790 return false;
3791 }
3792 break;
3793
3794 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3795 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3796 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3797 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3798 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3799 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3800 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3801 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3802 if (clientVersion < 3)
3803 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003804 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003805 return false;
3806 }
3807 break;
3808
3809 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003810 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003811 return false;
3812 }
3813
3814 // Determine if the attachment is a valid enum
3815 switch (attachment)
3816 {
3817 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04003818 case GL_DEPTH:
3819 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04003820 if (clientVersion < 3)
3821 {
Geoff Langfa125c92017-10-24 13:01:46 -04003822 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003823 return false;
3824 }
3825 break;
3826
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003827 case GL_DEPTH_STENCIL_ATTACHMENT:
3828 if (clientVersion < 3 && !context->isWebGL1())
3829 {
3830 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3831 return false;
3832 }
3833 break;
3834
Geoff Langfa125c92017-10-24 13:01:46 -04003835 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003836 case GL_DEPTH_ATTACHMENT:
3837 case GL_STENCIL_ATTACHMENT:
3838 break;
3839
3840 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003841 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3842 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003843 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3844 {
Geoff Langfa125c92017-10-24 13:01:46 -04003845 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003846 return false;
3847 }
3848 break;
3849 }
3850
3851 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3852 ASSERT(framebuffer);
3853
3854 if (framebuffer->id() == 0)
3855 {
3856 if (clientVersion < 3)
3857 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003858 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003859 return false;
3860 }
3861
3862 switch (attachment)
3863 {
3864 case GL_BACK:
3865 case GL_DEPTH:
3866 case GL_STENCIL:
3867 break;
3868
3869 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003870 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003871 return false;
3872 }
3873 }
3874 else
3875 {
3876 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3877 {
3878 // Valid attachment query
3879 }
3880 else
3881 {
3882 switch (attachment)
3883 {
3884 case GL_DEPTH_ATTACHMENT:
3885 case GL_STENCIL_ATTACHMENT:
3886 break;
3887
3888 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003889 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04003890 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003891 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003892 return false;
3893 }
3894 break;
3895
3896 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003897 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003898 return false;
3899 }
3900 }
3901 }
3902
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003903 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003904 if (attachmentObject)
3905 {
3906 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3907 attachmentObject->type() == GL_TEXTURE ||
3908 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3909
3910 switch (pname)
3911 {
3912 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3913 if (attachmentObject->type() != GL_RENDERBUFFER &&
3914 attachmentObject->type() != GL_TEXTURE)
3915 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003916 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003917 return false;
3918 }
3919 break;
3920
3921 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3922 if (attachmentObject->type() != GL_TEXTURE)
3923 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003924 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003925 return false;
3926 }
3927 break;
3928
3929 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3930 if (attachmentObject->type() != GL_TEXTURE)
3931 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003932 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003933 return false;
3934 }
3935 break;
3936
3937 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3938 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3939 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003940 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003941 return false;
3942 }
3943 break;
3944
3945 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3946 if (attachmentObject->type() != GL_TEXTURE)
3947 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003948 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003949 return false;
3950 }
3951 break;
3952
3953 default:
3954 break;
3955 }
3956 }
3957 else
3958 {
3959 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3960 // is NONE, then querying any other pname will generate INVALID_ENUM.
3961
3962 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3963 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3964 // INVALID_OPERATION for all other pnames
3965
3966 switch (pname)
3967 {
3968 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3969 break;
3970
3971 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3972 if (clientVersion < 3)
3973 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003974 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003975 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003976 return false;
3977 }
3978 break;
3979
3980 default:
3981 if (clientVersion < 3)
3982 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003983 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003984 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003985 return false;
3986 }
3987 else
3988 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003989 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003990 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003991 return false;
3992 }
3993 }
3994 }
3995
Martin Radeve5285d22017-07-14 16:23:53 +03003996 if (numParams)
3997 {
3998 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
3999 {
4000 // Only when the viewport offsets are queried we can have a varying number of output
4001 // parameters.
4002 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4003 *numParams = numViews * 2;
4004 }
4005 else
4006 {
4007 // For all other queries we can have only one output parameter.
4008 *numParams = 1;
4009 }
4010 }
4011
Geoff Langff5b2d52016-09-07 11:32:23 -04004012 return true;
4013}
4014
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004015bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004016 GLenum target,
4017 GLenum attachment,
4018 GLenum pname,
4019 GLsizei bufSize,
4020 GLsizei *numParams)
4021{
4022 if (!ValidateRobustEntryPoint(context, bufSize))
4023 {
4024 return false;
4025 }
4026
Jamie Madillbe849e42017-05-02 15:49:00 -04004027 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4028 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004029 {
4030 return false;
4031 }
4032
4033 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4034 {
4035 return false;
4036 }
4037
4038 return true;
4039}
4040
Geoff Langff5b2d52016-09-07 11:32:23 -04004041bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004042 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004043 GLenum pname,
4044 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004045 GLsizei *length,
4046 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004047{
4048 if (!ValidateRobustEntryPoint(context, bufSize))
4049 {
4050 return false;
4051 }
4052
Geoff Langebebe1c2016-10-14 12:01:31 -04004053 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004054 {
4055 return false;
4056 }
4057
Geoff Langebebe1c2016-10-14 12:01:31 -04004058 if (!ValidateRobustBufferSize(context, bufSize, *length))
4059 {
4060 return false;
4061 }
4062
4063 return true;
4064}
4065
Geoff Langebebe1c2016-10-14 12:01:31 -04004066bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004067 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004068 GLenum pname,
4069 GLsizei bufSize,
4070 GLsizei *length,
4071 GLint64 *params)
4072{
4073 if (!ValidateRobustEntryPoint(context, bufSize))
4074 {
4075 return false;
4076 }
4077
4078 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4079 {
4080 return false;
4081 }
4082
4083 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004084 {
4085 return false;
4086 }
4087
4088 return true;
4089}
4090
Jamie Madillbe849e42017-05-02 15:49:00 -04004091bool ValidateGetProgramivBase(ValidationContext *context,
4092 GLuint program,
4093 GLenum pname,
4094 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004095{
4096 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004097 if (numParams)
4098 {
4099 *numParams = 1;
4100 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004101
4102 Program *programObject = GetValidProgram(context, program);
4103 if (!programObject)
4104 {
4105 return false;
4106 }
4107
4108 switch (pname)
4109 {
4110 case GL_DELETE_STATUS:
4111 case GL_LINK_STATUS:
4112 case GL_VALIDATE_STATUS:
4113 case GL_INFO_LOG_LENGTH:
4114 case GL_ATTACHED_SHADERS:
4115 case GL_ACTIVE_ATTRIBUTES:
4116 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4117 case GL_ACTIVE_UNIFORMS:
4118 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4119 break;
4120
4121 case GL_PROGRAM_BINARY_LENGTH:
4122 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4123 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004124 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4125 "requires GL_OES_get_program_binary or "
4126 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004127 return false;
4128 }
4129 break;
4130
4131 case GL_ACTIVE_UNIFORM_BLOCKS:
4132 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4133 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4134 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4135 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4136 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4137 if (context->getClientMajorVersion() < 3)
4138 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004139 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004140 return false;
4141 }
4142 break;
4143
Yunchao He61afff12017-03-14 15:34:03 +08004144 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004145 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004146 if (context->getClientVersion() < Version(3, 1))
4147 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004148 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004149 return false;
4150 }
4151 break;
4152
Jiawei Shao6ae51612018-02-23 14:03:25 +08004153 case GL_COMPUTE_WORK_GROUP_SIZE:
4154 if (context->getClientVersion() < Version(3, 1))
4155 {
4156 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4157 return false;
4158 }
4159
4160 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4161 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4162 // program which has not been linked successfully, or which does not contain objects to
4163 // form a compute shader.
4164 if (!programObject->isLinked())
4165 {
4166 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4167 return false;
4168 }
4169 if (!programObject->hasLinkedComputeShader())
4170 {
4171 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4172 return false;
4173 }
4174 break;
4175
Geoff Langff5b2d52016-09-07 11:32:23 -04004176 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004177 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004178 return false;
4179 }
4180
4181 return true;
4182}
4183
4184bool ValidateGetProgramivRobustANGLE(Context *context,
4185 GLuint program,
4186 GLenum pname,
4187 GLsizei bufSize,
4188 GLsizei *numParams)
4189{
4190 if (!ValidateRobustEntryPoint(context, bufSize))
4191 {
4192 return false;
4193 }
4194
Jamie Madillbe849e42017-05-02 15:49:00 -04004195 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004196 {
4197 return false;
4198 }
4199
4200 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4201 {
4202 return false;
4203 }
4204
4205 return true;
4206}
4207
Geoff Lang740d9022016-10-07 11:20:52 -04004208bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4209 GLenum target,
4210 GLenum pname,
4211 GLsizei bufSize,
4212 GLsizei *length,
4213 GLint *params)
4214{
4215 if (!ValidateRobustEntryPoint(context, bufSize))
4216 {
4217 return false;
4218 }
4219
4220 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4221 {
4222 return false;
4223 }
4224
4225 if (!ValidateRobustBufferSize(context, bufSize, *length))
4226 {
4227 return false;
4228 }
4229
4230 return true;
4231}
4232
Geoff Langd7d0ed32016-10-07 11:33:51 -04004233bool ValidateGetShaderivRobustANGLE(Context *context,
4234 GLuint shader,
4235 GLenum pname,
4236 GLsizei bufSize,
4237 GLsizei *length,
4238 GLint *params)
4239{
4240 if (!ValidateRobustEntryPoint(context, bufSize))
4241 {
4242 return false;
4243 }
4244
4245 if (!ValidateGetShaderivBase(context, shader, pname, length))
4246 {
4247 return false;
4248 }
4249
4250 if (!ValidateRobustBufferSize(context, bufSize, *length))
4251 {
4252 return false;
4253 }
4254
4255 return true;
4256}
4257
Geoff Langc1984ed2016-10-07 12:41:00 -04004258bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004259 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004260 GLenum pname,
4261 GLsizei bufSize,
4262 GLsizei *length,
4263 GLfloat *params)
4264{
4265 if (!ValidateRobustEntryPoint(context, bufSize))
4266 {
4267 return false;
4268 }
4269
4270 if (!ValidateGetTexParameterBase(context, target, pname, length))
4271 {
4272 return false;
4273 }
4274
4275 if (!ValidateRobustBufferSize(context, bufSize, *length))
4276 {
4277 return false;
4278 }
4279
4280 return true;
4281}
4282
Geoff Langc1984ed2016-10-07 12:41:00 -04004283bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004284 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004285 GLenum pname,
4286 GLsizei bufSize,
4287 GLsizei *length,
4288 GLint *params)
4289{
4290 if (!ValidateRobustEntryPoint(context, bufSize))
4291 {
4292 return false;
4293 }
4294
4295 if (!ValidateGetTexParameterBase(context, target, pname, length))
4296 {
4297 return false;
4298 }
4299
4300 if (!ValidateRobustBufferSize(context, bufSize, *length))
4301 {
4302 return false;
4303 }
4304
4305 return true;
4306}
4307
Geoff Langc1984ed2016-10-07 12:41:00 -04004308bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004309 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004310 GLenum pname,
4311 GLsizei bufSize,
4312 const GLfloat *params)
4313{
4314 if (!ValidateRobustEntryPoint(context, bufSize))
4315 {
4316 return false;
4317 }
4318
4319 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4320}
4321
Geoff Langc1984ed2016-10-07 12:41:00 -04004322bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004323 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004324 GLenum pname,
4325 GLsizei bufSize,
4326 const GLint *params)
4327{
4328 if (!ValidateRobustEntryPoint(context, bufSize))
4329 {
4330 return false;
4331 }
4332
4333 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4334}
4335
Geoff Langc1984ed2016-10-07 12:41:00 -04004336bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4337 GLuint sampler,
4338 GLenum pname,
4339 GLuint bufSize,
4340 GLsizei *length,
4341 GLfloat *params)
4342{
4343 if (!ValidateRobustEntryPoint(context, bufSize))
4344 {
4345 return false;
4346 }
4347
4348 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4349 {
4350 return false;
4351 }
4352
4353 if (!ValidateRobustBufferSize(context, bufSize, *length))
4354 {
4355 return false;
4356 }
4357
4358 return true;
4359}
4360
Geoff Langc1984ed2016-10-07 12:41:00 -04004361bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4362 GLuint sampler,
4363 GLenum pname,
4364 GLuint bufSize,
4365 GLsizei *length,
4366 GLint *params)
4367{
4368 if (!ValidateRobustEntryPoint(context, bufSize))
4369 {
4370 return false;
4371 }
4372
4373 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4374 {
4375 return false;
4376 }
4377
4378 if (!ValidateRobustBufferSize(context, bufSize, *length))
4379 {
4380 return false;
4381 }
4382
4383 return true;
4384}
4385
Geoff Langc1984ed2016-10-07 12:41:00 -04004386bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4387 GLuint sampler,
4388 GLenum pname,
4389 GLsizei bufSize,
4390 const GLfloat *params)
4391{
4392 if (!ValidateRobustEntryPoint(context, bufSize))
4393 {
4394 return false;
4395 }
4396
4397 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4398}
4399
Geoff Langc1984ed2016-10-07 12:41:00 -04004400bool ValidateSamplerParameterivRobustANGLE(Context *context,
4401 GLuint sampler,
4402 GLenum pname,
4403 GLsizei bufSize,
4404 const GLint *params)
4405{
4406 if (!ValidateRobustEntryPoint(context, bufSize))
4407 {
4408 return false;
4409 }
4410
4411 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4412}
4413
Geoff Lang0b031062016-10-13 14:30:04 -04004414bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4415 GLuint index,
4416 GLenum pname,
4417 GLsizei bufSize,
4418 GLsizei *length,
4419 GLfloat *params)
4420{
4421 if (!ValidateRobustEntryPoint(context, bufSize))
4422 {
4423 return false;
4424 }
4425
4426 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4427 {
4428 return false;
4429 }
4430
4431 if (!ValidateRobustBufferSize(context, bufSize, *length))
4432 {
4433 return false;
4434 }
4435
4436 return true;
4437}
4438
Geoff Lang0b031062016-10-13 14:30:04 -04004439bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4440 GLuint index,
4441 GLenum pname,
4442 GLsizei bufSize,
4443 GLsizei *length,
4444 GLint *params)
4445{
4446 if (!ValidateRobustEntryPoint(context, bufSize))
4447 {
4448 return false;
4449 }
4450
4451 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4452 {
4453 return false;
4454 }
4455
4456 if (!ValidateRobustBufferSize(context, bufSize, *length))
4457 {
4458 return false;
4459 }
4460
4461 return true;
4462}
4463
Geoff Lang0b031062016-10-13 14:30:04 -04004464bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4465 GLuint index,
4466 GLenum pname,
4467 GLsizei bufSize,
4468 GLsizei *length,
4469 void **pointer)
4470{
4471 if (!ValidateRobustEntryPoint(context, bufSize))
4472 {
4473 return false;
4474 }
4475
4476 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4477 {
4478 return false;
4479 }
4480
4481 if (!ValidateRobustBufferSize(context, bufSize, *length))
4482 {
4483 return false;
4484 }
4485
4486 return true;
4487}
4488
Geoff Lang0b031062016-10-13 14:30:04 -04004489bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4490 GLuint index,
4491 GLenum pname,
4492 GLsizei bufSize,
4493 GLsizei *length,
4494 GLint *params)
4495{
4496 if (!ValidateRobustEntryPoint(context, bufSize))
4497 {
4498 return false;
4499 }
4500
4501 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4502 {
4503 return false;
4504 }
4505
4506 if (!ValidateRobustBufferSize(context, bufSize, *length))
4507 {
4508 return false;
4509 }
4510
4511 return true;
4512}
4513
Geoff Lang0b031062016-10-13 14:30:04 -04004514bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4515 GLuint index,
4516 GLenum pname,
4517 GLsizei bufSize,
4518 GLsizei *length,
4519 GLuint *params)
4520{
4521 if (!ValidateRobustEntryPoint(context, bufSize))
4522 {
4523 return false;
4524 }
4525
4526 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4527 {
4528 return false;
4529 }
4530
4531 if (!ValidateRobustBufferSize(context, bufSize, *length))
4532 {
4533 return false;
4534 }
4535
4536 return true;
4537}
4538
Geoff Lang6899b872016-10-14 11:30:13 -04004539bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4540 GLuint program,
4541 GLuint uniformBlockIndex,
4542 GLenum pname,
4543 GLsizei bufSize,
4544 GLsizei *length,
4545 GLint *params)
4546{
4547 if (!ValidateRobustEntryPoint(context, bufSize))
4548 {
4549 return false;
4550 }
4551
4552 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4553 {
4554 return false;
4555 }
4556
4557 if (!ValidateRobustBufferSize(context, bufSize, *length))
4558 {
4559 return false;
4560 }
4561
4562 return true;
4563}
4564
Geoff Lang0a9661f2016-10-20 10:59:20 -07004565bool ValidateGetInternalFormativRobustANGLE(Context *context,
4566 GLenum target,
4567 GLenum internalformat,
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 (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4579 {
4580 return false;
4581 }
4582
4583 if (!ValidateRobustBufferSize(context, bufSize, *length))
4584 {
4585 return false;
4586 }
4587
4588 return true;
4589}
4590
Shao80957d92017-02-20 21:25:59 +08004591bool ValidateVertexFormatBase(ValidationContext *context,
4592 GLuint attribIndex,
4593 GLint size,
4594 GLenum type,
4595 GLboolean pureInteger)
4596{
4597 const Caps &caps = context->getCaps();
4598 if (attribIndex >= caps.maxVertexAttributes)
4599 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004600 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004601 return false;
4602 }
4603
4604 if (size < 1 || size > 4)
4605 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004606 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004607 return false;
Shao80957d92017-02-20 21:25:59 +08004608 }
4609
4610 switch (type)
4611 {
4612 case GL_BYTE:
4613 case GL_UNSIGNED_BYTE:
4614 case GL_SHORT:
4615 case GL_UNSIGNED_SHORT:
4616 break;
4617
4618 case GL_INT:
4619 case GL_UNSIGNED_INT:
4620 if (context->getClientMajorVersion() < 3)
4621 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004622 context->handleError(InvalidEnum()
4623 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004624 return false;
4625 }
4626 break;
4627
4628 case GL_FIXED:
4629 case GL_FLOAT:
4630 if (pureInteger)
4631 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004632 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004633 return false;
4634 }
4635 break;
4636
4637 case GL_HALF_FLOAT:
4638 if (context->getClientMajorVersion() < 3)
4639 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004640 context->handleError(InvalidEnum()
4641 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004642 return false;
4643 }
4644 if (pureInteger)
4645 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004646 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004647 return false;
4648 }
4649 break;
4650
4651 case GL_INT_2_10_10_10_REV:
4652 case GL_UNSIGNED_INT_2_10_10_10_REV:
4653 if (context->getClientMajorVersion() < 3)
4654 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004655 context->handleError(InvalidEnum()
4656 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004657 return false;
4658 }
4659 if (pureInteger)
4660 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004661 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004662 return false;
4663 }
4664 if (size != 4)
4665 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004666 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4667 "UNSIGNED_INT_2_10_10_10_REV and "
4668 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004669 return false;
4670 }
4671 break;
4672
4673 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004674 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004675 return false;
4676 }
4677
4678 return true;
4679}
4680
Geoff Lang76e65652017-03-27 14:58:02 -04004681// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4682// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4683// specified clear value and the type of a buffer that is being cleared generates an
4684// INVALID_OPERATION error instead of producing undefined results
4685bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4686 GLint drawbuffer,
4687 const GLenum *validComponentTypes,
4688 size_t validComponentTypeCount)
4689{
4690 const FramebufferAttachment *attachment =
4691 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4692 if (attachment)
4693 {
4694 GLenum componentType = attachment->getFormat().info->componentType;
4695 const GLenum *end = validComponentTypes + validComponentTypeCount;
4696 if (std::find(validComponentTypes, end, componentType) == end)
4697 {
4698 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004699 InvalidOperation()
4700 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004701 return false;
4702 }
4703 }
4704
4705 return true;
4706}
4707
Corentin Wallezb2931602017-04-11 15:58:57 -04004708bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4709 GLsizei imageSize,
4710 GLsizei dataSize)
4711{
4712 if (!ValidateRobustEntryPoint(context, dataSize))
4713 {
4714 return false;
4715 }
4716
Corentin Wallez336129f2017-10-17 15:55:40 -04004717 gl::Buffer *pixelUnpackBuffer =
4718 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004719 if (pixelUnpackBuffer == nullptr)
4720 {
4721 if (dataSize < imageSize)
4722 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004723 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004724 }
4725 }
4726 return true;
4727}
4728
Jamie Madillbe849e42017-05-02 15:49:00 -04004729bool ValidateGetBufferParameterBase(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004730 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004731 GLenum pname,
4732 bool pointerVersion,
4733 GLsizei *numParams)
4734{
4735 if (numParams)
4736 {
4737 *numParams = 0;
4738 }
4739
Corentin Walleze4477002017-12-01 14:39:58 -05004740 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004741 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004742 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004743 return false;
4744 }
4745
4746 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4747 if (!buffer)
4748 {
4749 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004750 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004751 return false;
4752 }
4753
4754 const Extensions &extensions = context->getExtensions();
4755
4756 switch (pname)
4757 {
4758 case GL_BUFFER_USAGE:
4759 case GL_BUFFER_SIZE:
4760 break;
4761
4762 case GL_BUFFER_ACCESS_OES:
4763 if (!extensions.mapBuffer)
4764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004765 context->handleError(InvalidEnum()
4766 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004767 return false;
4768 }
4769 break;
4770
4771 case GL_BUFFER_MAPPED:
4772 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4773 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4774 !extensions.mapBufferRange)
4775 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004776 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4777 "GL_OES_mapbuffer or "
4778 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004779 return false;
4780 }
4781 break;
4782
4783 case GL_BUFFER_MAP_POINTER:
4784 if (!pointerVersion)
4785 {
4786 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004787 InvalidEnum()
4788 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004789 return false;
4790 }
4791 break;
4792
4793 case GL_BUFFER_ACCESS_FLAGS:
4794 case GL_BUFFER_MAP_OFFSET:
4795 case GL_BUFFER_MAP_LENGTH:
4796 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4797 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004798 context->handleError(InvalidEnum()
4799 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004800 return false;
4801 }
4802 break;
4803
4804 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004805 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004806 return false;
4807 }
4808
4809 // All buffer parameter queries return one value.
4810 if (numParams)
4811 {
4812 *numParams = 1;
4813 }
4814
4815 return true;
4816}
4817
4818bool ValidateGetRenderbufferParameterivBase(Context *context,
4819 GLenum target,
4820 GLenum pname,
4821 GLsizei *length)
4822{
4823 if (length)
4824 {
4825 *length = 0;
4826 }
4827
4828 if (target != GL_RENDERBUFFER)
4829 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004830 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004831 return false;
4832 }
4833
4834 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4835 if (renderbuffer == nullptr)
4836 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004837 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004838 return false;
4839 }
4840
4841 switch (pname)
4842 {
4843 case GL_RENDERBUFFER_WIDTH:
4844 case GL_RENDERBUFFER_HEIGHT:
4845 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4846 case GL_RENDERBUFFER_RED_SIZE:
4847 case GL_RENDERBUFFER_GREEN_SIZE:
4848 case GL_RENDERBUFFER_BLUE_SIZE:
4849 case GL_RENDERBUFFER_ALPHA_SIZE:
4850 case GL_RENDERBUFFER_DEPTH_SIZE:
4851 case GL_RENDERBUFFER_STENCIL_SIZE:
4852 break;
4853
4854 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4855 if (!context->getExtensions().framebufferMultisample)
4856 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004857 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004858 return false;
4859 }
4860 break;
4861
4862 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004863 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004864 return false;
4865 }
4866
4867 if (length)
4868 {
4869 *length = 1;
4870 }
4871 return true;
4872}
4873
4874bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4875{
4876 if (length)
4877 {
4878 *length = 0;
4879 }
4880
4881 if (GetValidShader(context, shader) == nullptr)
4882 {
4883 return false;
4884 }
4885
4886 switch (pname)
4887 {
4888 case GL_SHADER_TYPE:
4889 case GL_DELETE_STATUS:
4890 case GL_COMPILE_STATUS:
4891 case GL_INFO_LOG_LENGTH:
4892 case GL_SHADER_SOURCE_LENGTH:
4893 break;
4894
4895 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4896 if (!context->getExtensions().translatedShaderSource)
4897 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004898 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004899 return false;
4900 }
4901 break;
4902
4903 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004904 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004905 return false;
4906 }
4907
4908 if (length)
4909 {
4910 *length = 1;
4911 }
4912 return true;
4913}
4914
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004915bool ValidateGetTexParameterBase(Context *context,
4916 TextureType target,
4917 GLenum pname,
4918 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04004919{
4920 if (length)
4921 {
4922 *length = 0;
4923 }
4924
4925 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4926 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004927 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004928 return false;
4929 }
4930
4931 if (context->getTargetTexture(target) == nullptr)
4932 {
4933 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004934 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004935 return false;
4936 }
4937
4938 switch (pname)
4939 {
4940 case GL_TEXTURE_MAG_FILTER:
4941 case GL_TEXTURE_MIN_FILTER:
4942 case GL_TEXTURE_WRAP_S:
4943 case GL_TEXTURE_WRAP_T:
4944 break;
4945
4946 case GL_TEXTURE_USAGE_ANGLE:
4947 if (!context->getExtensions().textureUsage)
4948 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004949 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004950 return false;
4951 }
4952 break;
4953
4954 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05004955 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04004956 {
Jamie Madillbe849e42017-05-02 15:49:00 -04004957 return false;
4958 }
4959 break;
4960
4961 case GL_TEXTURE_IMMUTABLE_FORMAT:
4962 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4963 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004964 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004965 return false;
4966 }
4967 break;
4968
4969 case GL_TEXTURE_WRAP_R:
4970 case GL_TEXTURE_IMMUTABLE_LEVELS:
4971 case GL_TEXTURE_SWIZZLE_R:
4972 case GL_TEXTURE_SWIZZLE_G:
4973 case GL_TEXTURE_SWIZZLE_B:
4974 case GL_TEXTURE_SWIZZLE_A:
4975 case GL_TEXTURE_BASE_LEVEL:
4976 case GL_TEXTURE_MAX_LEVEL:
4977 case GL_TEXTURE_MIN_LOD:
4978 case GL_TEXTURE_MAX_LOD:
4979 case GL_TEXTURE_COMPARE_MODE:
4980 case GL_TEXTURE_COMPARE_FUNC:
4981 if (context->getClientMajorVersion() < 3)
4982 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004983 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004984 return false;
4985 }
4986 break;
4987
4988 case GL_TEXTURE_SRGB_DECODE_EXT:
4989 if (!context->getExtensions().textureSRGBDecode)
4990 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004991 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004992 return false;
4993 }
4994 break;
4995
Yunchao Hebacaa712018-01-30 14:01:39 +08004996 case GL_DEPTH_STENCIL_TEXTURE_MODE:
4997 if (context->getClientVersion() < Version(3, 1))
4998 {
4999 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5000 return false;
5001 }
5002 break;
5003
Jamie Madillbe849e42017-05-02 15:49:00 -04005004 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005005 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005006 return false;
5007 }
5008
5009 if (length)
5010 {
5011 *length = 1;
5012 }
5013 return true;
5014}
5015
5016bool ValidateGetVertexAttribBase(Context *context,
5017 GLuint index,
5018 GLenum pname,
5019 GLsizei *length,
5020 bool pointer,
5021 bool pureIntegerEntryPoint)
5022{
5023 if (length)
5024 {
5025 *length = 0;
5026 }
5027
5028 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5029 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005030 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005031 return false;
5032 }
5033
5034 if (index >= context->getCaps().maxVertexAttributes)
5035 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005036 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005037 return false;
5038 }
5039
5040 if (pointer)
5041 {
5042 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5043 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005044 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005045 return false;
5046 }
5047 }
5048 else
5049 {
5050 switch (pname)
5051 {
5052 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5053 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5054 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5055 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5056 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5057 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5058 case GL_CURRENT_VERTEX_ATTRIB:
5059 break;
5060
5061 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5062 static_assert(
5063 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5064 "ANGLE extension enums not equal to GL enums.");
5065 if (context->getClientMajorVersion() < 3 &&
5066 !context->getExtensions().instancedArrays)
5067 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005068 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5069 "requires OpenGL ES 3.0 or "
5070 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005071 return false;
5072 }
5073 break;
5074
5075 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5076 if (context->getClientMajorVersion() < 3)
5077 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005078 context->handleError(
5079 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005080 return false;
5081 }
5082 break;
5083
5084 case GL_VERTEX_ATTRIB_BINDING:
5085 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5086 if (context->getClientVersion() < ES_3_1)
5087 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005088 context->handleError(InvalidEnum()
5089 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005090 return false;
5091 }
5092 break;
5093
5094 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005095 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005096 return false;
5097 }
5098 }
5099
5100 if (length)
5101 {
5102 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5103 {
5104 *length = 4;
5105 }
5106 else
5107 {
5108 *length = 1;
5109 }
5110 }
5111
5112 return true;
5113}
5114
Jamie Madill4928b7c2017-06-20 12:57:39 -04005115bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005116 GLint x,
5117 GLint y,
5118 GLsizei width,
5119 GLsizei height,
5120 GLenum format,
5121 GLenum type,
5122 GLsizei bufSize,
5123 GLsizei *length,
5124 GLsizei *columns,
5125 GLsizei *rows,
5126 void *pixels)
5127{
5128 if (length != nullptr)
5129 {
5130 *length = 0;
5131 }
5132 if (rows != nullptr)
5133 {
5134 *rows = 0;
5135 }
5136 if (columns != nullptr)
5137 {
5138 *columns = 0;
5139 }
5140
5141 if (width < 0 || height < 0)
5142 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005143 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005144 return false;
5145 }
5146
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005147 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005148
5149 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5150 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005151 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005152 return false;
5153 }
5154
5155 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5156 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005157 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005158 return false;
5159 }
5160
5161 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5162 ASSERT(framebuffer);
5163
5164 if (framebuffer->getReadBufferState() == GL_NONE)
5165 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005166 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005167 return false;
5168 }
5169
5170 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5171 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5172 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5173 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5174 // situation is an application error that would lead to a crash in ANGLE.
5175 if (readBuffer == nullptr)
5176 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005177 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005178 return false;
5179 }
5180
Martin Radev28031682017-07-28 14:47:56 +03005181 // ANGLE_multiview, Revision 1:
5182 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5183 // current read framebuffer is not NONE.
5184 if (readBuffer->getMultiviewLayout() != GL_NONE)
5185 {
5186 context->handleError(InvalidFramebufferOperation()
5187 << "Attempting to read from a multi-view framebuffer.");
5188 return false;
5189 }
5190
Geoff Lang280ba992017-04-18 16:30:58 -04005191 if (context->getExtensions().webglCompatibility)
5192 {
5193 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5194 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5195 // and type before validating the combination of format and type. However, the
5196 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5197 // verifies that GL_INVALID_OPERATION is generated.
5198 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5199 // dEQP/WebGL.
5200 if (!ValidReadPixelsFormatEnum(context, format))
5201 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005202 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005203 return false;
5204 }
5205
5206 if (!ValidReadPixelsTypeEnum(context, type))
5207 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005208 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005209 return false;
5210 }
5211 }
5212
Jamie Madill4928b7c2017-06-20 12:57:39 -04005213 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5214 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005215 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5216
5217 bool validFormatTypeCombination =
5218 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5219
5220 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5221 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005222 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005223 return false;
5224 }
5225
5226 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005227 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005228 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5229 {
5230 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005231 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005232 return false;
5233 }
5234
5235 // .. the data would be packed to the buffer object such that the memory writes required
5236 // would exceed the data store size.
5237 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5238 const gl::Extents size(width, height, 1);
5239 const auto &pack = context->getGLState().getPackState();
5240
5241 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5242 if (endByteOrErr.isError())
5243 {
5244 context->handleError(endByteOrErr.getError());
5245 return false;
5246 }
5247
5248 size_t endByte = endByteOrErr.getResult();
5249 if (bufSize >= 0)
5250 {
5251 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5252 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005253 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005254 return false;
5255 }
5256 }
5257
5258 if (pixelPackBuffer != nullptr)
5259 {
5260 CheckedNumeric<size_t> checkedEndByte(endByte);
5261 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5262 checkedEndByte += checkedOffset;
5263
5264 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5265 {
5266 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005267 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005268 return false;
5269 }
5270 }
5271
5272 if (pixelPackBuffer == nullptr && length != nullptr)
5273 {
5274 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5275 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005276 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005277 return false;
5278 }
5279
5280 *length = static_cast<GLsizei>(endByte);
5281 }
5282
Geoff Langa953b522018-02-21 16:56:23 -05005283 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005284 angle::CheckedNumeric<int> clippedExtent(length);
5285 if (start < 0)
5286 {
5287 // "subtract" the area that is less than 0
5288 clippedExtent += start;
5289 }
5290
Geoff Langa953b522018-02-21 16:56:23 -05005291 angle::CheckedNumeric<int> readExtent = start;
5292 readExtent += length;
5293 if (!readExtent.IsValid())
5294 {
5295 return false;
5296 }
5297
5298 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005299 {
5300 // Subtract the region to the right of the read buffer
5301 clippedExtent -= (readExtent - bufferSize);
5302 }
5303
5304 if (!clippedExtent.IsValid())
5305 {
Geoff Langa953b522018-02-21 16:56:23 -05005306 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005307 }
5308
Geoff Langa953b522018-02-21 16:56:23 -05005309 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5310 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005311 };
5312
Geoff Langa953b522018-02-21 16:56:23 -05005313 GLsizei writtenColumns = 0;
5314 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5315 {
5316 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5317 return false;
5318 }
5319
5320 GLsizei writtenRows = 0;
5321 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5322 {
5323 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5324 return false;
5325 }
5326
Jamie Madillbe849e42017-05-02 15:49:00 -04005327 if (columns != nullptr)
5328 {
Geoff Langa953b522018-02-21 16:56:23 -05005329 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005330 }
5331
5332 if (rows != nullptr)
5333 {
Geoff Langa953b522018-02-21 16:56:23 -05005334 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005335 }
5336
5337 return true;
5338}
5339
5340template <typename ParamType>
5341bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005342 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005343 GLenum pname,
5344 GLsizei bufSize,
5345 const ParamType *params)
5346{
5347 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5348 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005349 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005350 return false;
5351 }
5352
5353 if (context->getTargetTexture(target) == nullptr)
5354 {
5355 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005356 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005357 return false;
5358 }
5359
5360 const GLsizei minBufSize = 1;
5361 if (bufSize >= 0 && bufSize < minBufSize)
5362 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005363 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005364 return false;
5365 }
5366
5367 switch (pname)
5368 {
5369 case GL_TEXTURE_WRAP_R:
5370 case GL_TEXTURE_SWIZZLE_R:
5371 case GL_TEXTURE_SWIZZLE_G:
5372 case GL_TEXTURE_SWIZZLE_B:
5373 case GL_TEXTURE_SWIZZLE_A:
5374 case GL_TEXTURE_BASE_LEVEL:
5375 case GL_TEXTURE_MAX_LEVEL:
5376 case GL_TEXTURE_COMPARE_MODE:
5377 case GL_TEXTURE_COMPARE_FUNC:
5378 case GL_TEXTURE_MIN_LOD:
5379 case GL_TEXTURE_MAX_LOD:
5380 if (context->getClientMajorVersion() < 3)
5381 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005382 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005383 return false;
5384 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005385 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005386 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005387 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5388 "available without "
5389 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005390 return false;
5391 }
5392 break;
5393
5394 default:
5395 break;
5396 }
5397
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005398 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005399 {
5400 switch (pname)
5401 {
5402 case GL_TEXTURE_MIN_FILTER:
5403 case GL_TEXTURE_MAG_FILTER:
5404 case GL_TEXTURE_WRAP_S:
5405 case GL_TEXTURE_WRAP_T:
5406 case GL_TEXTURE_WRAP_R:
5407 case GL_TEXTURE_MIN_LOD:
5408 case GL_TEXTURE_MAX_LOD:
5409 case GL_TEXTURE_COMPARE_MODE:
5410 case GL_TEXTURE_COMPARE_FUNC:
5411 context->handleError(InvalidEnum()
5412 << "Invalid parameter for 2D multisampled textures.");
5413 return false;
5414 }
5415 }
5416
Jamie Madillbe849e42017-05-02 15:49:00 -04005417 switch (pname)
5418 {
5419 case GL_TEXTURE_WRAP_S:
5420 case GL_TEXTURE_WRAP_T:
5421 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005422 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005423 bool restrictedWrapModes =
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005424 target == TextureType::External || target == TextureType::Rectangle;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005425 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5426 {
5427 return false;
5428 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005429 }
5430 break;
5431
5432 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005433 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005434 bool restrictedMinFilter =
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005435 target == TextureType::External || target == TextureType::Rectangle;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005436 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5437 {
5438 return false;
5439 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005440 }
5441 break;
5442
5443 case GL_TEXTURE_MAG_FILTER:
5444 if (!ValidateTextureMagFilterValue(context, params))
5445 {
5446 return false;
5447 }
5448 break;
5449
5450 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005451 if (!context->getExtensions().textureUsage)
5452 {
5453 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5454 return false;
5455 }
5456
Jamie Madillbe849e42017-05-02 15:49:00 -04005457 switch (ConvertToGLenum(params[0]))
5458 {
5459 case GL_NONE:
5460 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5461 break;
5462
5463 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005464 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005465 return false;
5466 }
5467 break;
5468
5469 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Jamie Madillbe849e42017-05-02 15:49:00 -04005470 {
Luc Ferron1b1a8642018-01-23 15:12:01 -05005471 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5472 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5473 {
5474 return false;
5475 }
5476 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
Jamie Madillbe849e42017-05-02 15:49:00 -04005477 }
5478 break;
5479
5480 case GL_TEXTURE_MIN_LOD:
5481 case GL_TEXTURE_MAX_LOD:
5482 // any value is permissible
5483 break;
5484
5485 case GL_TEXTURE_COMPARE_MODE:
5486 if (!ValidateTextureCompareModeValue(context, params))
5487 {
5488 return false;
5489 }
5490 break;
5491
5492 case GL_TEXTURE_COMPARE_FUNC:
5493 if (!ValidateTextureCompareFuncValue(context, params))
5494 {
5495 return false;
5496 }
5497 break;
5498
5499 case GL_TEXTURE_SWIZZLE_R:
5500 case GL_TEXTURE_SWIZZLE_G:
5501 case GL_TEXTURE_SWIZZLE_B:
5502 case GL_TEXTURE_SWIZZLE_A:
5503 switch (ConvertToGLenum(params[0]))
5504 {
5505 case GL_RED:
5506 case GL_GREEN:
5507 case GL_BLUE:
5508 case GL_ALPHA:
5509 case GL_ZERO:
5510 case GL_ONE:
5511 break;
5512
5513 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005514 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005515 return false;
5516 }
5517 break;
5518
5519 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005520 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005521 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005522 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005523 return false;
5524 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005525 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005527 context->handleError(InvalidOperation()
5528 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005529 return false;
5530 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005531 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005532 {
5533 context->handleError(InvalidOperation()
5534 << "Base level must be 0 for multisampled textures.");
5535 return false;
5536 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005537 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005538 {
5539 context->handleError(InvalidOperation()
5540 << "Base level must be 0 for rectangle textures.");
5541 return false;
5542 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005543 break;
5544
5545 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005546 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005547 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005548 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005549 return false;
5550 }
5551 break;
5552
5553 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5554 if (context->getClientVersion() < Version(3, 1))
5555 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005556 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005557 return false;
5558 }
5559 switch (ConvertToGLenum(params[0]))
5560 {
5561 case GL_DEPTH_COMPONENT:
5562 case GL_STENCIL_INDEX:
5563 break;
5564
5565 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005566 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005567 return false;
5568 }
5569 break;
5570
5571 case GL_TEXTURE_SRGB_DECODE_EXT:
5572 if (!ValidateTextureSRGBDecodeValue(context, params))
5573 {
5574 return false;
5575 }
5576 break;
5577
5578 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005579 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005580 return false;
5581 }
5582
5583 return true;
5584}
5585
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005586template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
5587template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04005588
Jamie Madill12e957f2017-08-26 21:42:26 -04005589bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5590{
5591 if (index >= MAX_VERTEX_ATTRIBS)
5592 {
5593 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5594 return false;
5595 }
5596
5597 return true;
5598}
5599
5600bool ValidateGetActiveUniformBlockivBase(Context *context,
5601 GLuint program,
5602 GLuint uniformBlockIndex,
5603 GLenum pname,
5604 GLsizei *length)
5605{
5606 if (length)
5607 {
5608 *length = 0;
5609 }
5610
5611 if (context->getClientMajorVersion() < 3)
5612 {
5613 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5614 return false;
5615 }
5616
5617 Program *programObject = GetValidProgram(context, program);
5618 if (!programObject)
5619 {
5620 return false;
5621 }
5622
5623 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5624 {
5625 context->handleError(InvalidValue()
5626 << "uniformBlockIndex exceeds active uniform block count.");
5627 return false;
5628 }
5629
5630 switch (pname)
5631 {
5632 case GL_UNIFORM_BLOCK_BINDING:
5633 case GL_UNIFORM_BLOCK_DATA_SIZE:
5634 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5635 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5636 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5637 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5638 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5639 break;
5640
5641 default:
5642 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5643 return false;
5644 }
5645
5646 if (length)
5647 {
5648 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5649 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005650 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005651 programObject->getUniformBlockByIndex(uniformBlockIndex);
5652 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5653 }
5654 else
5655 {
5656 *length = 1;
5657 }
5658 }
5659
5660 return true;
5661}
5662
Jamie Madill9696d072017-08-26 23:19:57 -04005663template <typename ParamType>
5664bool ValidateSamplerParameterBase(Context *context,
5665 GLuint sampler,
5666 GLenum pname,
5667 GLsizei bufSize,
5668 ParamType *params)
5669{
5670 if (context->getClientMajorVersion() < 3)
5671 {
5672 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5673 return false;
5674 }
5675
5676 if (!context->isSampler(sampler))
5677 {
5678 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5679 return false;
5680 }
5681
5682 const GLsizei minBufSize = 1;
5683 if (bufSize >= 0 && bufSize < minBufSize)
5684 {
5685 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5686 return false;
5687 }
5688
5689 switch (pname)
5690 {
5691 case GL_TEXTURE_WRAP_S:
5692 case GL_TEXTURE_WRAP_T:
5693 case GL_TEXTURE_WRAP_R:
5694 if (!ValidateTextureWrapModeValue(context, params, false))
5695 {
5696 return false;
5697 }
5698 break;
5699
5700 case GL_TEXTURE_MIN_FILTER:
5701 if (!ValidateTextureMinFilterValue(context, params, false))
5702 {
5703 return false;
5704 }
5705 break;
5706
5707 case GL_TEXTURE_MAG_FILTER:
5708 if (!ValidateTextureMagFilterValue(context, params))
5709 {
5710 return false;
5711 }
5712 break;
5713
5714 case GL_TEXTURE_MIN_LOD:
5715 case GL_TEXTURE_MAX_LOD:
5716 // any value is permissible
5717 break;
5718
5719 case GL_TEXTURE_COMPARE_MODE:
5720 if (!ValidateTextureCompareModeValue(context, params))
5721 {
5722 return false;
5723 }
5724 break;
5725
5726 case GL_TEXTURE_COMPARE_FUNC:
5727 if (!ValidateTextureCompareFuncValue(context, params))
5728 {
5729 return false;
5730 }
5731 break;
5732
5733 case GL_TEXTURE_SRGB_DECODE_EXT:
5734 if (!ValidateTextureSRGBDecodeValue(context, params))
5735 {
5736 return false;
5737 }
5738 break;
5739
Luc Ferron1b1a8642018-01-23 15:12:01 -05005740 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5741 {
5742 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5743 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5744 {
5745 return false;
5746 }
5747 }
5748 break;
5749
Jamie Madill9696d072017-08-26 23:19:57 -04005750 default:
5751 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5752 return false;
5753 }
5754
5755 return true;
5756}
5757
5758template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5759template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5760
5761bool ValidateGetSamplerParameterBase(Context *context,
5762 GLuint sampler,
5763 GLenum pname,
5764 GLsizei *length)
5765{
5766 if (length)
5767 {
5768 *length = 0;
5769 }
5770
5771 if (context->getClientMajorVersion() < 3)
5772 {
5773 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5774 return false;
5775 }
5776
5777 if (!context->isSampler(sampler))
5778 {
5779 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5780 return false;
5781 }
5782
5783 switch (pname)
5784 {
5785 case GL_TEXTURE_WRAP_S:
5786 case GL_TEXTURE_WRAP_T:
5787 case GL_TEXTURE_WRAP_R:
5788 case GL_TEXTURE_MIN_FILTER:
5789 case GL_TEXTURE_MAG_FILTER:
5790 case GL_TEXTURE_MIN_LOD:
5791 case GL_TEXTURE_MAX_LOD:
5792 case GL_TEXTURE_COMPARE_MODE:
5793 case GL_TEXTURE_COMPARE_FUNC:
5794 break;
5795
Luc Ferron1b1a8642018-01-23 15:12:01 -05005796 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5797 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
5798 {
5799 return false;
5800 }
5801 break;
5802
Jamie Madill9696d072017-08-26 23:19:57 -04005803 case GL_TEXTURE_SRGB_DECODE_EXT:
5804 if (!context->getExtensions().textureSRGBDecode)
5805 {
5806 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5807 return false;
5808 }
5809 break;
5810
5811 default:
5812 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5813 return false;
5814 }
5815
5816 if (length)
5817 {
5818 *length = 1;
5819 }
5820 return true;
5821}
5822
5823bool ValidateGetInternalFormativBase(Context *context,
5824 GLenum target,
5825 GLenum internalformat,
5826 GLenum pname,
5827 GLsizei bufSize,
5828 GLsizei *numParams)
5829{
5830 if (numParams)
5831 {
5832 *numParams = 0;
5833 }
5834
5835 if (context->getClientMajorVersion() < 3)
5836 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005837 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005838 return false;
5839 }
5840
5841 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5842 if (!formatCaps.renderable)
5843 {
5844 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5845 return false;
5846 }
5847
5848 switch (target)
5849 {
5850 case GL_RENDERBUFFER:
5851 break;
5852
5853 case GL_TEXTURE_2D_MULTISAMPLE:
5854 if (context->getClientVersion() < ES_3_1)
5855 {
5856 context->handleError(InvalidOperation()
5857 << "Texture target requires at least OpenGL ES 3.1.");
5858 return false;
5859 }
5860 break;
5861
5862 default:
5863 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5864 return false;
5865 }
5866
5867 if (bufSize < 0)
5868 {
5869 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5870 return false;
5871 }
5872
5873 GLsizei maxWriteParams = 0;
5874 switch (pname)
5875 {
5876 case GL_NUM_SAMPLE_COUNTS:
5877 maxWriteParams = 1;
5878 break;
5879
5880 case GL_SAMPLES:
5881 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5882 break;
5883
5884 default:
5885 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5886 return false;
5887 }
5888
5889 if (numParams)
5890 {
5891 // glGetInternalFormativ will not overflow bufSize
5892 *numParams = std::min(bufSize, maxWriteParams);
5893 }
5894
5895 return true;
5896}
5897
Jamie Madillc29968b2016-01-20 11:17:23 -05005898} // namespace gl