blob: 0657124110575586e86c0d2233b8f201c0faeff2 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040012#include "libANGLE/Display.h"
Brandon Jones6cad5662017-06-14 13:25:13 -070013#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Framebuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
Geoff Langa8406172015-07-21 16:53:39 -040016#include "libANGLE/Image.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050017#include "libANGLE/Program.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Query.h"
19#include "libANGLE/Texture.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/TransformFeedback.h"
21#include "libANGLE/VertexArray.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040022#include "libANGLE/formatutils.h"
jchen10a99ed552017-09-22 08:10:32 +080023#include "libANGLE/queryconversions.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040024#include "libANGLE/validationES2.h"
25#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040026
27#include "common/mathutil.h"
28#include "common/utilities.h"
29
Jamie Madille2e406c2016-06-02 13:04:10 -040030using namespace angle;
31
Geoff Lange8ebe7f2013-08-05 15:03:13 -040032namespace gl
33{
Jamie Madill1ca74672015-07-21 15:14:11 -040034namespace
35{
Luc Ferron9dbaeba2018-02-01 07:26:59 -050036bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
37{
38 // List of compressed format that require that the texture size is smaller than or a multiple of
39 // the compressed block size.
40 switch (internalFormat)
41 {
42 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
43 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
44 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
45 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
46 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
47 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
48 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
49 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
50 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
51 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
52 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
53 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
54 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
55 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
56 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
57 return true;
jchen10a99ed552017-09-22 08:10:32 +080058
Luc Ferron9dbaeba2018-02-01 07:26:59 -050059 default:
60 return false;
61 }
62}
63bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
64{
65 // Compressed sub textures have additional formats that requires exact size.
66 // ES 3.1, Section 8.7, Page 171
67 return CompressedTextureFormatRequiresExactSize(internalFormat) ||
68 IsETC2EACFormat(internalFormat);
69}
Corentin Wallez92db6942016-12-09 13:10:36 -050070bool ValidateDrawAttribs(ValidationContext *context,
71 GLint primcount,
72 GLint maxVertex,
73 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040074{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070075 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040076 const gl::Program *program = state.getProgram();
77
Corentin Wallez327411e2016-12-09 11:09:17 -050078 bool webglCompatibility = context->getExtensions().webglCompatibility;
79
Jamie Madill231c7f52017-04-26 13:45:37 -040080 const VertexArray *vao = state.getVertexArray();
81 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080082 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madilld078c682018-01-02 11:50:24 -050083 for (size_t attributeIndex : vao->getEnabledAttributesMask())
Jamie Madill1ca74672015-07-21 15:14:11 -040084 {
85 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallez672f7f32017-06-15 17:42:17 -040086
87 // No need to range check for disabled attribs.
88 if (!attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040089 {
Corentin Wallezfd456442016-12-21 17:57:00 -050090 continue;
91 }
Jamie Madill1ca74672015-07-21 15:14:11 -040092
Jamie Madill231c7f52017-04-26 13:45:37 -040093 // If we have no buffer, then we either get an error, or there are no more checks to be
94 // done.
Corentin Wallez672f7f32017-06-15 17:42:17 -040095 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
96 gl::Buffer *buffer = binding.getBuffer().get();
Corentin Wallezfd456442016-12-21 17:57:00 -050097 if (!buffer)
98 {
Geoff Langfeb8c682017-02-13 16:07:35 -050099 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -0500100 {
101 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -0500102 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
103 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
104 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
105 // error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700106 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
Corentin Wallezfd456442016-12-21 17:57:00 -0500107 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -0500108 }
Corentin Wallezfd456442016-12-21 17:57:00 -0500109 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -0400110 {
111 // This is an application error that would normally result in a crash,
112 // but we catch it and return an error
Brandon Jonesafa75152017-07-21 13:11:29 -0700113 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
Jamie Madill1ca74672015-07-21 15:14:11 -0400114 return false;
115 }
Corentin Wallezfd456442016-12-21 17:57:00 -0500116 continue;
117 }
118
Corentin Wallez672f7f32017-06-15 17:42:17 -0400119 // This needs to come after the check for client arrays as even unused attributes cannot use
120 // client-side arrays
121 if (!program->isAttribLocationActive(attributeIndex))
122 {
123 continue;
124 }
125
Corentin Wallezfd456442016-12-21 17:57:00 -0500126 // If we're drawing zero vertices, we have enough data.
127 if (vertexCount <= 0 || primcount <= 0)
128 {
129 continue;
130 }
131
132 GLint maxVertexElement = 0;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300133 GLuint divisor = binding.getDivisor();
134 if (divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500135 {
136 maxVertexElement = maxVertex;
137 }
138 else
139 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300140 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500141 }
142
143 // We do manual overflow checks here instead of using safe_math.h because it was
144 // a bottleneck. Thanks to some properties of GL we know inequalities that can
145 // help us make the overflow checks faster.
146
147 // The max possible attribSize is 16 for a vector of 4 32 bit values.
148 constexpr uint64_t kMaxAttribSize = 16;
149 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
150 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
151
152 // We know attribStride is given as a GLsizei which is typedefed to int.
153 // We also know an upper bound for attribSize.
154 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800155 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500156 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
157 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
158
159 // Computing the max offset using uint64_t without attrib.offset is overflow
160 // safe. Note: Last vertex element does not take the full stride!
161 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
162 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
163
164 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800165 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
166 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500167 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700168 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500169 return false;
170 }
171 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
172
173 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
174 // We can return INVALID_OPERATION if our vertex attribute does not have
175 // enough backing data.
176 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
177 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700178 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500179 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400180 }
181 }
182
183 return true;
184}
185
Geoff Lang280ba992017-04-18 16:30:58 -0400186bool ValidReadPixelsTypeEnum(ValidationContext *context, GLenum type)
187{
188 switch (type)
189 {
190 // Types referenced in Table 3.4 of the ES 2.0.25 spec
191 case GL_UNSIGNED_BYTE:
192 case GL_UNSIGNED_SHORT_4_4_4_4:
193 case GL_UNSIGNED_SHORT_5_5_5_1:
194 case GL_UNSIGNED_SHORT_5_6_5:
195 return context->getClientVersion() >= ES_2_0;
196
197 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
198 case GL_BYTE:
199 case GL_INT:
200 case GL_SHORT:
201 case GL_UNSIGNED_INT:
202 case GL_UNSIGNED_INT_10F_11F_11F_REV:
203 case GL_UNSIGNED_INT_24_8:
204 case GL_UNSIGNED_INT_2_10_10_10_REV:
205 case GL_UNSIGNED_INT_5_9_9_9_REV:
206 case GL_UNSIGNED_SHORT:
207 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
208 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
209 return context->getClientVersion() >= ES_3_0;
210
211 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400212 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
213 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400214
215 case GL_HALF_FLOAT:
216 return context->getClientVersion() >= ES_3_0 ||
217 context->getExtensions().textureHalfFloat;
218
219 case GL_HALF_FLOAT_OES:
220 return context->getExtensions().colorBufferHalfFloat;
221
222 default:
223 return false;
224 }
225}
226
227bool ValidReadPixelsFormatEnum(ValidationContext *context, GLenum format)
228{
229 switch (format)
230 {
231 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
232 case GL_RGBA:
233 case GL_RGB:
234 case GL_ALPHA:
235 return context->getClientVersion() >= ES_2_0;
236
237 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
238 case GL_RG:
239 case GL_RED:
240 case GL_RGBA_INTEGER:
241 case GL_RGB_INTEGER:
242 case GL_RG_INTEGER:
243 case GL_RED_INTEGER:
244 return context->getClientVersion() >= ES_3_0;
245
246 case GL_SRGB_ALPHA_EXT:
247 case GL_SRGB_EXT:
248 return context->getExtensions().sRGB;
249
250 case GL_BGRA_EXT:
251 return context->getExtensions().readFormatBGRA;
252
253 default:
254 return false;
255 }
256}
257
Geoff Langf607c602016-09-21 11:46:48 -0400258bool ValidReadPixelsFormatType(ValidationContext *context,
259 GLenum framebufferComponentType,
260 GLenum format,
261 GLenum type)
262{
263 switch (framebufferComponentType)
264 {
265 case GL_UNSIGNED_NORMALIZED:
266 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
267 // ReadPixels with BGRA even if the extension is not present
268 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
269 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
270 type == GL_UNSIGNED_BYTE);
271
272 case GL_SIGNED_NORMALIZED:
273 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
274
275 case GL_INT:
276 return (format == GL_RGBA_INTEGER && type == GL_INT);
277
278 case GL_UNSIGNED_INT:
279 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
280
281 case GL_FLOAT:
282 return (format == GL_RGBA && type == GL_FLOAT);
283
284 default:
285 UNREACHABLE();
286 return false;
287 }
288}
289
Geoff Langc1984ed2016-10-07 12:41:00 -0400290template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400291bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400292{
293 switch (ConvertToGLenum(params[0]))
294 {
295 case GL_CLAMP_TO_EDGE:
296 break;
297
298 case GL_REPEAT:
299 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400300 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400301 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400302 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700303 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400304 return false;
305 }
306 break;
307
308 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700309 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400310 return false;
311 }
312
313 return true;
314}
315
316template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400317bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400318{
319 switch (ConvertToGLenum(params[0]))
320 {
321 case GL_NEAREST:
322 case GL_LINEAR:
323 break;
324
325 case GL_NEAREST_MIPMAP_NEAREST:
326 case GL_LINEAR_MIPMAP_NEAREST:
327 case GL_NEAREST_MIPMAP_LINEAR:
328 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400329 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400330 {
331 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700332 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400333 return false;
334 }
335 break;
336
337 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700338 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400339 return false;
340 }
341
342 return true;
343}
344
345template <typename ParamType>
346bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
347{
348 switch (ConvertToGLenum(params[0]))
349 {
350 case GL_NEAREST:
351 case GL_LINEAR:
352 break;
353
354 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700355 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400356 return false;
357 }
358
359 return true;
360}
361
362template <typename ParamType>
363bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
364{
365 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
366 switch (ConvertToGLenum(params[0]))
367 {
368 case GL_NONE:
369 case GL_COMPARE_REF_TO_TEXTURE:
370 break;
371
372 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700373 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400374 return false;
375 }
376
377 return true;
378}
379
380template <typename ParamType>
381bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
382{
383 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
384 switch (ConvertToGLenum(params[0]))
385 {
386 case GL_LEQUAL:
387 case GL_GEQUAL:
388 case GL_LESS:
389 case GL_GREATER:
390 case GL_EQUAL:
391 case GL_NOTEQUAL:
392 case GL_ALWAYS:
393 case GL_NEVER:
394 break;
395
396 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700397 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400398 return false;
399 }
400
401 return true;
402}
403
404template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700405bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
406{
407 if (!context->getExtensions().textureSRGBDecode)
408 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700409 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700410 return false;
411 }
412
413 switch (ConvertToGLenum(params[0]))
414 {
415 case GL_DECODE_EXT:
416 case GL_SKIP_DECODE_EXT:
417 break;
418
419 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700420 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700421 return false;
422 }
423
424 return true;
425}
426
Luc Ferron1b1a8642018-01-23 15:12:01 -0500427bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
428{
429 if (!context->getExtensions().textureFilterAnisotropic)
430 {
431 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
432 return false;
433 }
434
435 return true;
436}
437
438bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
439{
440 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
441 {
442 return false;
443 }
444
445 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
446
447 if (paramValue < 1 || paramValue > largest)
448 {
449 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
450 return false;
451 }
452
453 return true;
454}
455
Geoff Lange0cff192017-05-30 13:04:56 -0400456bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
457{
458 const Program *program = context->getGLState().getProgram();
459 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
460
Brandon Jonesc405ae72017-12-06 14:15:03 -0800461 if (!ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
462 framebuffer->getDrawBufferTypeMask().to_ulong(),
463 program->getActiveOutputVariables().to_ulong(),
464 framebuffer->getDrawBufferMask().to_ulong()))
Geoff Lange0cff192017-05-30 13:04:56 -0400465 {
Brandon Jones76746f92017-11-22 11:44:41 -0800466 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
467 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400468 }
469
470 return true;
471}
472
Geoff Lang9ab5b822017-05-30 16:19:23 -0400473bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
474{
Jamie Madillcac94a92017-11-10 10:09:32 -0500475 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400476 const Program *program = context->getGLState().getProgram();
477 const VertexArray *vao = context->getGLState().getVertexArray();
478
Brandon Jonesc405ae72017-12-06 14:15:03 -0800479 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
480 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
481 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
482
483 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
484 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
485 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
486
487 if (!ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
488 program->getAttributesMask().to_ulong(), 0xFFFF))
Geoff Lang9ab5b822017-05-30 16:19:23 -0400489 {
Brandon Jonesc405ae72017-12-06 14:15:03 -0800490 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexShaderTypeMismatch);
491 return false;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400492 }
Geoff Lang9ab5b822017-05-30 16:19:23 -0400493 return true;
494}
495
Geoff Langf41a7152016-09-19 15:11:17 -0400496} // anonymous namespace
497
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500498bool IsETC2EACFormat(const GLenum format)
499{
500 // ES 3.1, Table 8.19
501 switch (format)
502 {
503 case GL_COMPRESSED_R11_EAC:
504 case GL_COMPRESSED_SIGNED_R11_EAC:
505 case GL_COMPRESSED_RG11_EAC:
506 case GL_COMPRESSED_SIGNED_RG11_EAC:
507 case GL_COMPRESSED_RGB8_ETC2:
508 case GL_COMPRESSED_SRGB8_ETC2:
509 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
510 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
511 case GL_COMPRESSED_RGBA8_ETC2_EAC:
512 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
513 return true;
514
515 default:
516 return false;
517 }
518}
519
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500520bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400521{
Jamie Madilld7460c72014-01-21 16:38:14 -0500522 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400523 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800524 case GL_TEXTURE_2D:
525 case GL_TEXTURE_CUBE_MAP:
526 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400527
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400528 case GL_TEXTURE_RECTANGLE_ANGLE:
529 return context->getExtensions().textureRectangle;
530
He Yunchaoced53ae2016-11-29 15:00:51 +0800531 case GL_TEXTURE_3D:
532 case GL_TEXTURE_2D_ARRAY:
533 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500534
He Yunchaoced53ae2016-11-29 15:00:51 +0800535 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800536 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400537
He Yunchaoced53ae2016-11-29 15:00:51 +0800538 default:
539 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500540 }
Jamie Madill35d15012013-10-07 10:46:37 -0400541}
542
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500543bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
544{
545 switch (target)
546 {
547 case GL_TEXTURE_2D:
548 case GL_TEXTURE_CUBE_MAP:
549 return true;
550
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400551 case GL_TEXTURE_RECTANGLE_ANGLE:
552 return context->getExtensions().textureRectangle;
553
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500554 default:
555 return false;
556 }
557}
558
559bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
560{
561 switch (target)
562 {
563 case GL_TEXTURE_3D:
564 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300565 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500566
567 default:
568 return false;
569 }
570}
571
Ian Ewellbda75592016-04-18 17:25:54 -0400572// Most texture GL calls are not compatible with external textures, so we have a separate validation
573// function for use in the GL calls that do
574bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
575{
576 return (target == GL_TEXTURE_EXTERNAL_OES) &&
577 (context->getExtensions().eglImageExternal ||
578 context->getExtensions().eglStreamConsumerExternal);
579}
580
Shannon Woods4dfed832014-03-17 20:03:39 -0400581// This function differs from ValidTextureTarget in that the target must be
582// usable as the destination of a 2D operation-- so a cube face is valid, but
583// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400584// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500585bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400586{
587 switch (target)
588 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800589 case GL_TEXTURE_2D:
590 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
591 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
592 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
593 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
594 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
595 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
596 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400597 case GL_TEXTURE_RECTANGLE_ANGLE:
598 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800599 default:
600 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500601 }
602}
603
Jamie Madillbe849e42017-05-02 15:49:00 -0400604bool ValidateDrawElementsInstancedBase(ValidationContext *context,
605 GLenum mode,
606 GLsizei count,
607 GLenum type,
608 const GLvoid *indices,
609 GLsizei primcount)
610{
611 if (primcount < 0)
612 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700613 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400614 return false;
615 }
616
617 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
618 {
619 return false;
620 }
621
Jamie Madill9fdaa492018-02-16 10:52:11 -0500622 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400623}
624
625bool ValidateDrawArraysInstancedBase(Context *context,
626 GLenum mode,
627 GLint first,
628 GLsizei count,
629 GLsizei primcount)
630{
631 if (primcount < 0)
632 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700633 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400634 return false;
635 }
636
637 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
638 {
639 return false;
640 }
641
Jamie Madill9fdaa492018-02-16 10:52:11 -0500642 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400643}
644
Corentin Wallez0dc97812017-06-22 14:38:44 -0400645bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400646{
647 // Verify there is at least one active attribute with a divisor of zero
648 const State &state = context->getGLState();
649
650 Program *program = state.getProgram();
651
652 const auto &attribs = state.getVertexArray()->getVertexAttributes();
653 const auto &bindings = state.getVertexArray()->getVertexBindings();
654 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
655 {
656 const VertexAttribute &attrib = attribs[attributeIndex];
657 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300658 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400659 {
660 return true;
661 }
662 }
663
Brandon Jonesafa75152017-07-21 13:11:29 -0700664 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400665 return false;
666}
667
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500668bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
669{
670 switch (target)
671 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800672 case GL_TEXTURE_3D:
673 case GL_TEXTURE_2D_ARRAY:
674 return true;
675 default:
676 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400677 }
678}
679
He Yunchao11b038b2016-11-22 21:24:04 +0800680bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
681{
682 switch (target)
683 {
684 case GL_TEXTURE_2D:
685 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
686 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
687 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
688 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
689 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
690 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
691 case GL_TEXTURE_3D:
692 case GL_TEXTURE_2D_ARRAY:
693 case GL_TEXTURE_2D_MULTISAMPLE:
694 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400695 case GL_TEXTURE_RECTANGLE_ANGLE:
696 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800697 default:
698 return false;
699 }
700}
701
Geoff Lange8afa902017-09-27 15:00:43 -0400702bool ValidFramebufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500703{
He Yunchaoced53ae2016-11-29 15:00:51 +0800704 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
705 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400706 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500707
708 switch (target)
709 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800710 case GL_FRAMEBUFFER:
711 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400712
He Yunchaoced53ae2016-11-29 15:00:51 +0800713 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800714 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400715 return (context->getExtensions().framebufferBlit ||
716 context->getClientMajorVersion() >= 3);
717
He Yunchaoced53ae2016-11-29 15:00:51 +0800718 default:
719 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500720 }
721}
722
Jamie Madillc29968b2016-01-20 11:17:23 -0500723bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400724{
Jamie Madillc29968b2016-01-20 11:17:23 -0500725 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400726 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -0400727 switch (target)
728 {
Jamie Madillc29968b2016-01-20 11:17:23 -0500729 case GL_TEXTURE_2D:
730 maxDimension = caps.max2DTextureSize;
731 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800732 case GL_TEXTURE_CUBE_MAP:
733 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
734 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
735 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
736 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
737 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
738 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
739 maxDimension = caps.maxCubeMapTextureSize;
740 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400741 case GL_TEXTURE_RECTANGLE_ANGLE:
742 return level == 0;
He Yunchaoced53ae2016-11-29 15:00:51 +0800743 case GL_TEXTURE_3D:
744 maxDimension = caps.max3DTextureSize;
745 break;
746 case GL_TEXTURE_2D_ARRAY:
747 maxDimension = caps.max2DTextureSize;
748 break;
He Yunchao11b038b2016-11-22 21:24:04 +0800749 case GL_TEXTURE_2D_MULTISAMPLE:
750 maxDimension = caps.max2DTextureSize;
751 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800752 default:
753 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400754 }
755
Brandon Jones6cad5662017-06-14 13:25:13 -0700756 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400757}
758
Brandon Jones6cad5662017-06-14 13:25:13 -0700759bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -0700760 GLenum target,
761 GLint level,
762 GLsizei width,
763 GLsizei height,
764 GLsizei depth,
765 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400766{
Brandon Jones6cad5662017-06-14 13:25:13 -0700767 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400768 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700769 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400770 return false;
771 }
Austin Kinross08528e12015-10-07 16:24:40 -0700772 // TexSubImage parameters can be NPOT without textureNPOT extension,
773 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500774 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500775 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500776 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400777 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400778 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700779 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400780 return false;
781 }
782
783 if (!ValidMipLevel(context, target, level))
784 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700785 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400786 return false;
787 }
788
789 return true;
790}
791
Geoff Lang966c9402017-04-18 12:38:27 -0400792bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
793{
794 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
795 (size % blockSize == 0);
796}
797
Jamie Madillc29968b2016-01-20 11:17:23 -0500798bool ValidCompressedImageSize(const ValidationContext *context,
799 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400800 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500801 GLsizei width,
802 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400803{
Geoff Langca271392017-04-05 12:30:00 -0400804 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400805 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400806 {
807 return false;
808 }
809
Geoff Lang966c9402017-04-18 12:38:27 -0400810 if (width < 0 || height < 0)
811 {
812 return false;
813 }
814
815 if (CompressedTextureFormatRequiresExactSize(internalFormat))
816 {
817 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
818 // block size for level 0 but WebGL disallows this.
819 bool smallerThanBlockSizeAllowed =
820 level > 0 || !context->getExtensions().webglCompatibility;
821
822 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
823 smallerThanBlockSizeAllowed) ||
824 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
825 smallerThanBlockSizeAllowed))
826 {
827 return false;
828 }
829 }
830
831 return true;
832}
833
834bool ValidCompressedSubImageSize(const ValidationContext *context,
835 GLenum internalFormat,
836 GLint xoffset,
837 GLint yoffset,
838 GLsizei width,
839 GLsizei height,
840 size_t textureWidth,
841 size_t textureHeight)
842{
843 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
844 if (!formatInfo.compressed)
845 {
846 return false;
847 }
848
Geoff Lang44ff5a72017-02-03 15:15:43 -0500849 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400850 {
851 return false;
852 }
853
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500854 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400855 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500856 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400857 yoffset % formatInfo.compressedBlockHeight != 0)
858 {
859 return false;
860 }
861
862 // Allowed to either have data that is a multiple of block size or is smaller than the block
863 // size but fills the entire mip
864 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
865 static_cast<size_t>(width) == textureWidth &&
866 static_cast<size_t>(height) == textureHeight;
867 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
868 (height % formatInfo.compressedBlockHeight) == 0;
869 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400870 {
871 return false;
872 }
873 }
874
Geoff Langd4f180b2013-09-24 13:57:44 -0400875 return true;
876}
877
Geoff Langff5b2d52016-09-07 11:32:23 -0400878bool ValidImageDataSize(ValidationContext *context,
879 GLenum textureTarget,
880 GLsizei width,
881 GLsizei height,
882 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400883 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400884 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400885 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400886 GLsizei imageSize)
887{
Corentin Wallez336129f2017-10-17 15:55:40 -0400888 gl::Buffer *pixelUnpackBuffer =
889 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400890 if (pixelUnpackBuffer == nullptr && imageSize < 0)
891 {
892 // Checks are not required
893 return true;
894 }
895
896 // ...the data would be unpacked from the buffer object such that the memory reads required
897 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400898 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
899 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400900 const gl::Extents size(width, height, depth);
901 const auto &unpack = context->getGLState().getUnpackState();
902
903 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
904 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
905 if (endByteOrErr.isError())
906 {
907 context->handleError(endByteOrErr.getError());
908 return false;
909 }
910
911 GLuint endByte = endByteOrErr.getResult();
912
913 if (pixelUnpackBuffer)
914 {
915 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
916 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
917 checkedEndByte += checkedOffset;
918
919 if (!checkedEndByte.IsValid() ||
920 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
921 {
922 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500923 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -0400924 return false;
925 }
926 }
927 else
928 {
929 ASSERT(imageSize >= 0);
930 if (pixels == nullptr && imageSize != 0)
931 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500932 context->handleError(InvalidOperation()
933 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400934 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400935 }
936
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400937 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400938 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500939 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400940 return false;
941 }
942 }
943
944 return true;
945}
946
Geoff Lang37dde692014-01-31 16:34:54 -0500947bool ValidQueryType(const Context *context, GLenum queryType)
948{
He Yunchaoced53ae2016-11-29 15:00:51 +0800949 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
950 "GL extension enums not equal.");
951 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
952 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -0500953
954 switch (queryType)
955 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800956 case GL_ANY_SAMPLES_PASSED:
957 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400958 return context->getClientMajorVersion() >= 3 ||
959 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +0800960 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
961 return (context->getClientMajorVersion() >= 3);
962 case GL_TIME_ELAPSED_EXT:
963 return context->getExtensions().disjointTimerQuery;
964 case GL_COMMANDS_COMPLETED_CHROMIUM:
965 return context->getExtensions().syncQuery;
966 default:
967 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500968 }
969}
970
Geoff Lang2d62ab72017-03-23 16:54:40 -0400971bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
972 GLenum type,
973 GLboolean normalized,
974 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400975 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400976 bool pureInteger)
977{
978 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400979 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
980 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
981 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
982 // parameter exceeds 255.
983 constexpr GLsizei kMaxWebGLStride = 255;
984 if (stride > kMaxWebGLStride)
985 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500986 context->handleError(InvalidValue()
987 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -0400988 return false;
989 }
990
991 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
992 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
993 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
994 // or an INVALID_OPERATION error is generated.
995 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
996 size_t typeSize = GetVertexFormatTypeSize(internalType);
997
998 ASSERT(isPow2(typeSize) && typeSize > 0);
999 size_t sizeMask = (typeSize - 1);
1000 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1001 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001002 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001003 return false;
1004 }
1005
1006 if ((stride & sizeMask) != 0)
1007 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001008 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001009 return false;
1010 }
1011
1012 return true;
1013}
1014
Jamie Madillef300b12016-10-07 15:12:09 -04001015Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001016{
He Yunchaoced53ae2016-11-29 15:00:51 +08001017 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1018 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1019 // or program object and INVALID_OPERATION if the provided name identifies an object
1020 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001021
Dian Xiang769769a2015-09-09 15:20:08 -07001022 Program *validProgram = context->getProgram(id);
1023
1024 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001025 {
Dian Xiang769769a2015-09-09 15:20:08 -07001026 if (context->getShader(id))
1027 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001028 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001029 }
1030 else
1031 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001032 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001033 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001034 }
Dian Xiang769769a2015-09-09 15:20:08 -07001035
1036 return validProgram;
1037}
1038
Jamie Madillef300b12016-10-07 15:12:09 -04001039Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001040{
1041 // See ValidProgram for spec details.
1042
1043 Shader *validShader = context->getShader(id);
1044
1045 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001046 {
Dian Xiang769769a2015-09-09 15:20:08 -07001047 if (context->getProgram(id))
1048 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001049 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001050 }
1051 else
1052 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001053 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001054 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001055 }
Dian Xiang769769a2015-09-09 15:20:08 -07001056
1057 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001058}
1059
Geoff Langb1196682014-07-23 13:47:29 -04001060bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001061{
Geoff Langfa125c92017-10-24 13:01:46 -04001062 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001063 {
Geoff Langfa125c92017-10-24 13:01:46 -04001064 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1065 {
1066 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1067 return false;
1068 }
Jamie Madillb4472272014-07-03 10:38:55 -04001069
Geoff Langfa125c92017-10-24 13:01:46 -04001070 // Color attachment 0 is validated below because it is always valid
1071 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001072 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001073 {
Geoff Langfa125c92017-10-24 13:01:46 -04001074 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001075 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001076 }
1077 }
1078 else
1079 {
1080 switch (attachment)
1081 {
Geoff Langfa125c92017-10-24 13:01:46 -04001082 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001083 case GL_DEPTH_ATTACHMENT:
1084 case GL_STENCIL_ATTACHMENT:
1085 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001086
He Yunchaoced53ae2016-11-29 15:00:51 +08001087 case GL_DEPTH_STENCIL_ATTACHMENT:
1088 if (!context->getExtensions().webglCompatibility &&
1089 context->getClientMajorVersion() < 3)
1090 {
Geoff Langfa125c92017-10-24 13:01:46 -04001091 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001092 return false;
1093 }
1094 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001095
He Yunchaoced53ae2016-11-29 15:00:51 +08001096 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001097 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001098 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001099 }
1100 }
1101
1102 return true;
1103}
1104
Jamie Madille8fb6402017-02-14 17:56:40 -05001105bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001106 GLenum target,
1107 GLsizei samples,
1108 GLenum internalformat,
1109 GLsizei width,
1110 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001111{
1112 switch (target)
1113 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001114 case GL_RENDERBUFFER:
1115 break;
1116 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001117 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001118 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001119 }
1120
1121 if (width < 0 || height < 0 || samples < 0)
1122 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001123 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001124 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001125 }
1126
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001127 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1128 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1129
1130 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001131 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001132 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001133 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001134 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001135 }
1136
1137 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1138 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
Corentin Walleze0902642014-11-04 12:32:15 -08001139 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001140 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1141 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001142 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001143 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001144 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001145 }
1146
Geoff Langaae65a42014-05-26 12:43:44 -04001147 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001148 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001149 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001150 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001151 }
1152
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001153 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001154 if (handle == 0)
1155 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001156 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001157 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001158 }
1159
1160 return true;
1161}
1162
He Yunchaoced53ae2016-11-29 15:00:51 +08001163bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1164 GLenum target,
1165 GLenum attachment,
1166 GLenum renderbuffertarget,
1167 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001168{
Geoff Lange8afa902017-09-27 15:00:43 -04001169 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001170 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001171 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001172 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001173 }
1174
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001175 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001176
Jamie Madill84115c92015-04-23 15:00:07 -04001177 ASSERT(framebuffer);
1178 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001179 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001180 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001181 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001182 }
1183
Jamie Madillb4472272014-07-03 10:38:55 -04001184 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001185 {
Jamie Madillb4472272014-07-03 10:38:55 -04001186 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001187 }
1188
Jamie Madillab9d82c2014-01-21 16:38:14 -05001189 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1190 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1191 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1192 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1193 if (renderbuffer != 0)
1194 {
1195 if (!context->getRenderbuffer(renderbuffer))
1196 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001197 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001198 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001199 }
1200 }
1201
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001202 return true;
1203}
1204
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001205bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001206 GLint srcX0,
1207 GLint srcY0,
1208 GLint srcX1,
1209 GLint srcY1,
1210 GLint dstX0,
1211 GLint dstY0,
1212 GLint dstX1,
1213 GLint dstY1,
1214 GLbitfield mask,
1215 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001216{
1217 switch (filter)
1218 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001219 case GL_NEAREST:
1220 break;
1221 case GL_LINEAR:
1222 break;
1223 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001224 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001225 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001226 }
1227
1228 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1229 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001230 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001231 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001232 }
1233
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001234 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1235 // color buffer, leaving only nearest being unfiltered from above
1236 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1237 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001238 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001239 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001240 }
1241
Jamie Madill51f40ec2016-06-15 14:06:00 -04001242 const auto &glState = context->getGLState();
1243 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1244 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001245
1246 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001247 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001248 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001249 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001250 }
1251
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001252 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001253 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001254 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001255 return false;
1256 }
1257
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001258 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001259 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001260 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001261 return false;
1262 }
1263
Qin Jiajiaaef92162018-02-27 13:51:44 +08001264 if (readFramebuffer->id() == drawFramebuffer->id())
1265 {
1266 context->handleError(InvalidOperation());
1267 return false;
1268 }
1269
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001270 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001271 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001272 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001273 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001274 }
1275
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001276 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1277
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001278 if (mask & GL_COLOR_BUFFER_BIT)
1279 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001280 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001281 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001282
He Yunchao66a41a22016-12-15 16:45:05 +08001283 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001284 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001285 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001286
Geoff Langa15472a2015-08-11 11:48:03 -04001287 for (size_t drawbufferIdx = 0;
1288 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001289 {
Geoff Langa15472a2015-08-11 11:48:03 -04001290 const FramebufferAttachment *attachment =
1291 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1292 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001293 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001294 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001295
Geoff Langb2f3d052013-08-13 12:49:27 -04001296 // The GL ES 3.0.2 spec (pg 193) states that:
1297 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001298 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1299 // as well
1300 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1301 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001302 // Changes with EXT_color_buffer_float:
1303 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001304 GLenum readComponentType = readFormat.info->componentType;
1305 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001306 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001307 readComponentType == GL_SIGNED_NORMALIZED);
1308 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1309 drawComponentType == GL_SIGNED_NORMALIZED);
1310
1311 if (extensions.colorBufferFloat)
1312 {
1313 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1314 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1315
1316 if (readFixedOrFloat != drawFixedOrFloat)
1317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001318 context->handleError(InvalidOperation()
1319 << "If the read buffer contains fixed-point or "
1320 "floating-point values, the draw buffer must "
1321 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001322 return false;
1323 }
1324 }
1325 else if (readFixedPoint != drawFixedPoint)
1326 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001327 context->handleError(InvalidOperation()
1328 << "If the read buffer contains fixed-point values, "
1329 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001330 return false;
1331 }
1332
1333 if (readComponentType == GL_UNSIGNED_INT &&
1334 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001335 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001336 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001337 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001338 }
1339
Jamie Madill6163c752015-12-07 16:32:59 -05001340 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001341 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001342 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001343 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001344 }
1345
Jamie Madilla3944d42016-07-22 22:13:26 -04001346 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001347 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001348 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001349 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001350 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001351 }
Geoff Lange4915782017-04-12 15:19:07 -04001352
1353 if (context->getExtensions().webglCompatibility &&
1354 *readColorBuffer == *attachment)
1355 {
1356 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001357 InvalidOperation()
1358 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001359 return false;
1360 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001361 }
1362 }
1363
Jamie Madilla3944d42016-07-22 22:13:26 -04001364 if ((readFormat.info->componentType == GL_INT ||
1365 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1366 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001367 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001368 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001369 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001370 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001371 }
He Yunchao66a41a22016-12-15 16:45:05 +08001372 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1373 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1374 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1375 // situation is an application error that would lead to a crash in ANGLE.
1376 else if (drawFramebuffer->hasEnabledDrawBuffer())
1377 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001378 context->handleError(
1379 InvalidOperation()
1380 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001381 return false;
1382 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001383 }
1384
He Yunchaoced53ae2016-11-29 15:00:51 +08001385 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001386 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1387 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001388 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001389 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001390 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001391 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001392 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001393 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001394 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001395
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001396 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001397 {
Kenneth Russell69382852017-07-21 16:38:44 -04001398 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001399 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001400 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001401 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001402 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001403
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001404 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001406 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001407 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001408 }
Geoff Lange4915782017-04-12 15:19:07 -04001409
1410 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1411 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001412 context->handleError(
1413 InvalidOperation()
1414 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001415 return false;
1416 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001417 }
He Yunchao66a41a22016-12-15 16:45:05 +08001418 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1419 else if (drawBuffer)
1420 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001421 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1422 "depth/stencil attachment of a "
1423 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001424 return false;
1425 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001426 }
1427 }
1428
Martin Radeva3ed4572017-07-27 18:29:37 +03001429 // ANGLE_multiview, Revision 1:
1430 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1431 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1432 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1433 {
1434 context->handleError(InvalidFramebufferOperation()
1435 << "Attempt to read from a multi-view framebuffer.");
1436 return false;
1437 }
1438 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1439 {
1440 context->handleError(InvalidFramebufferOperation()
1441 << "Attempt to write to a multi-view framebuffer.");
1442 return false;
1443 }
1444
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001445 return true;
1446}
1447
Jamie Madill4928b7c2017-06-20 12:57:39 -04001448bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001449 GLint x,
1450 GLint y,
1451 GLsizei width,
1452 GLsizei height,
1453 GLenum format,
1454 GLenum type,
1455 GLsizei bufSize,
1456 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001457 GLsizei *columns,
1458 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001459 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001460{
1461 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001462 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001463 return false;
1464 }
1465
Geoff Lang62fce5b2016-09-30 10:46:35 -04001466 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001467 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001468 {
Geoff Langb1196682014-07-23 13:47:29 -04001469 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001470 }
1471
Geoff Lang62fce5b2016-09-30 10:46:35 -04001472 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001473 {
Geoff Langb1196682014-07-23 13:47:29 -04001474 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001475 }
1476
Jamie Madillc29968b2016-01-20 11:17:23 -05001477 return true;
1478}
1479
1480bool ValidateReadnPixelsEXT(Context *context,
1481 GLint x,
1482 GLint y,
1483 GLsizei width,
1484 GLsizei height,
1485 GLenum format,
1486 GLenum type,
1487 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001488 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001489{
1490 if (bufSize < 0)
1491 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001492 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001493 return false;
1494 }
1495
Geoff Lang62fce5b2016-09-30 10:46:35 -04001496 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001497 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001498}
Jamie Madill26e91952014-03-05 15:01:27 -05001499
Jamie Madill4928b7c2017-06-20 12:57:39 -04001500bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001501 GLint x,
1502 GLint y,
1503 GLsizei width,
1504 GLsizei height,
1505 GLenum format,
1506 GLenum type,
1507 GLsizei bufSize,
1508 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001509 GLsizei *columns,
1510 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001511 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001512{
1513 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001514 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001515 return false;
1516 }
1517
Geoff Lange93daba2017-03-30 13:54:40 -04001518 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1519 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001520 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001521 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001522 }
1523
Geoff Lang62fce5b2016-09-30 10:46:35 -04001524 if (!ValidateRobustBufferSize(context, bufSize, *length))
1525 {
1526 return false;
1527 }
1528
1529 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001530}
1531
Jamie Madillf0e04492017-08-26 15:28:42 -04001532bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001533{
1534 if (!context->getExtensions().occlusionQueryBoolean &&
1535 !context->getExtensions().disjointTimerQuery)
1536 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001537 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001538 return false;
1539 }
1540
Olli Etuaho41997e72016-03-10 13:38:39 +02001541 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001542}
1543
Jamie Madillf0e04492017-08-26 15:28:42 -04001544bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001545{
1546 if (!context->getExtensions().occlusionQueryBoolean &&
1547 !context->getExtensions().disjointTimerQuery)
1548 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001549 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001550 return false;
1551 }
1552
Olli Etuaho41997e72016-03-10 13:38:39 +02001553 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001554}
1555
Jamie Madillf0e04492017-08-26 15:28:42 -04001556bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1557{
1558 if (!context->getExtensions().occlusionQueryBoolean &&
1559 !context->getExtensions().disjointTimerQuery)
1560 {
1561 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1562 return false;
1563 }
1564
1565 return true;
1566}
1567
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001568bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001569{
1570 if (!ValidQueryType(context, target))
1571 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001572 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001573 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001574 }
1575
1576 if (id == 0)
1577 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001578 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001579 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001580 }
1581
1582 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1583 // of zero, if the active query object name for <target> is non-zero (for the
1584 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1585 // the active query for either target is non-zero), if <id> is the name of an
1586 // existing query object whose type does not match <target>, or if <id> is the
1587 // active query object name for any query type, the error INVALID_OPERATION is
1588 // generated.
1589
1590 // Ensure no other queries are active
1591 // NOTE: If other queries than occlusion are supported, we will need to check
1592 // separately that:
1593 // a) The query ID passed is not the current active query for any target/type
1594 // b) There are no active queries for the requested target (and in the case
1595 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1596 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001597
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001598 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001599 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001600 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001601 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001602 }
1603
1604 Query *queryObject = context->getQuery(id, true, target);
1605
1606 // check that name was obtained with glGenQueries
1607 if (!queryObject)
1608 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001609 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001610 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001611 }
1612
1613 // check for type mismatch
1614 if (queryObject->getType() != target)
1615 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001616 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001617 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001618 }
1619
1620 return true;
1621}
1622
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001623bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1624{
1625 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001626 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001627 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001628 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001629 return false;
1630 }
1631
1632 return ValidateBeginQueryBase(context, target, id);
1633}
1634
1635bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001636{
1637 if (!ValidQueryType(context, target))
1638 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001639 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001640 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001641 }
1642
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001643 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001644
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001645 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001647 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001648 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001649 }
1650
Jamie Madill45c785d2014-05-13 14:09:34 -04001651 return true;
1652}
1653
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001654bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1655{
1656 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001657 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001658 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001659 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001660 return false;
1661 }
1662
1663 return ValidateEndQueryBase(context, target);
1664}
1665
1666bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1667{
1668 if (!context->getExtensions().disjointTimerQuery)
1669 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001670 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001671 return false;
1672 }
1673
1674 if (target != GL_TIMESTAMP_EXT)
1675 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001676 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001677 return false;
1678 }
1679
1680 Query *queryObject = context->getQuery(id, true, target);
1681 if (queryObject == nullptr)
1682 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001683 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001684 return false;
1685 }
1686
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001687 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001688 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001689 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001690 return false;
1691 }
1692
1693 return true;
1694}
1695
Geoff Lang2186c382016-10-14 10:54:54 -04001696bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001697{
Geoff Lang2186c382016-10-14 10:54:54 -04001698 if (numParams)
1699 {
1700 *numParams = 0;
1701 }
1702
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001703 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1704 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001705 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001706 return false;
1707 }
1708
1709 switch (pname)
1710 {
1711 case GL_CURRENT_QUERY_EXT:
1712 if (target == GL_TIMESTAMP_EXT)
1713 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001714 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001715 return false;
1716 }
1717 break;
1718 case GL_QUERY_COUNTER_BITS_EXT:
1719 if (!context->getExtensions().disjointTimerQuery ||
1720 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1721 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001722 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001723 return false;
1724 }
1725 break;
1726 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001727 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001728 return false;
1729 }
1730
Geoff Lang2186c382016-10-14 10:54:54 -04001731 if (numParams)
1732 {
1733 // All queries return only one value
1734 *numParams = 1;
1735 }
1736
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001737 return true;
1738}
1739
1740bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1741{
1742 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001743 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001744 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001745 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001746 return false;
1747 }
1748
Geoff Lang2186c382016-10-14 10:54:54 -04001749 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001750}
1751
Geoff Lang2186c382016-10-14 10:54:54 -04001752bool ValidateGetQueryivRobustANGLE(Context *context,
1753 GLenum target,
1754 GLenum pname,
1755 GLsizei bufSize,
1756 GLsizei *length,
1757 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001758{
Geoff Lang2186c382016-10-14 10:54:54 -04001759 if (!ValidateRobustEntryPoint(context, bufSize))
1760 {
1761 return false;
1762 }
1763
1764 if (!ValidateGetQueryivBase(context, target, pname, length))
1765 {
1766 return false;
1767 }
1768
1769 if (!ValidateRobustBufferSize(context, bufSize, *length))
1770 {
1771 return false;
1772 }
1773
1774 return true;
1775}
1776
1777bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1778{
1779 if (numParams)
1780 {
1781 *numParams = 0;
1782 }
1783
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001784 Query *queryObject = context->getQuery(id, false, GL_NONE);
1785
1786 if (!queryObject)
1787 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001788 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001789 return false;
1790 }
1791
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001792 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001793 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001794 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001795 return false;
1796 }
1797
1798 switch (pname)
1799 {
1800 case GL_QUERY_RESULT_EXT:
1801 case GL_QUERY_RESULT_AVAILABLE_EXT:
1802 break;
1803
1804 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001805 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001806 return false;
1807 }
1808
Geoff Lang2186c382016-10-14 10:54:54 -04001809 if (numParams)
1810 {
1811 *numParams = 1;
1812 }
1813
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001814 return true;
1815}
1816
1817bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, 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");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001822 return false;
1823 }
Geoff Lang2186c382016-10-14 10:54:54 -04001824 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1825}
1826
1827bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1828 GLuint id,
1829 GLenum pname,
1830 GLsizei bufSize,
1831 GLsizei *length,
1832 GLint *params)
1833{
1834 if (!context->getExtensions().disjointTimerQuery)
1835 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001836 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001837 return false;
1838 }
1839
1840 if (!ValidateRobustEntryPoint(context, bufSize))
1841 {
1842 return false;
1843 }
1844
1845 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1846 {
1847 return false;
1848 }
1849
1850 if (!ValidateRobustBufferSize(context, bufSize, *length))
1851 {
1852 return false;
1853 }
1854
1855 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001856}
1857
1858bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1859{
1860 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001861 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001862 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001863 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001864 return false;
1865 }
Geoff Lang2186c382016-10-14 10:54:54 -04001866 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1867}
1868
1869bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1870 GLuint id,
1871 GLenum pname,
1872 GLsizei bufSize,
1873 GLsizei *length,
1874 GLuint *params)
1875{
1876 if (!context->getExtensions().disjointTimerQuery &&
1877 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1878 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001879 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001880 return false;
1881 }
1882
1883 if (!ValidateRobustEntryPoint(context, bufSize))
1884 {
1885 return false;
1886 }
1887
1888 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1889 {
1890 return false;
1891 }
1892
1893 if (!ValidateRobustBufferSize(context, bufSize, *length))
1894 {
1895 return false;
1896 }
1897
1898 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001899}
1900
1901bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1902{
1903 if (!context->getExtensions().disjointTimerQuery)
1904 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001905 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001906 return false;
1907 }
Geoff Lang2186c382016-10-14 10:54:54 -04001908 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1909}
1910
1911bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1912 GLuint id,
1913 GLenum pname,
1914 GLsizei bufSize,
1915 GLsizei *length,
1916 GLint64 *params)
1917{
1918 if (!context->getExtensions().disjointTimerQuery)
1919 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001920 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001921 return false;
1922 }
1923
1924 if (!ValidateRobustEntryPoint(context, bufSize))
1925 {
1926 return false;
1927 }
1928
1929 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1930 {
1931 return false;
1932 }
1933
1934 if (!ValidateRobustBufferSize(context, bufSize, *length))
1935 {
1936 return false;
1937 }
1938
1939 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001940}
1941
1942bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1943{
1944 if (!context->getExtensions().disjointTimerQuery)
1945 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001946 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001947 return false;
1948 }
Geoff Lang2186c382016-10-14 10:54:54 -04001949 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1950}
1951
1952bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1953 GLuint id,
1954 GLenum pname,
1955 GLsizei bufSize,
1956 GLsizei *length,
1957 GLuint64 *params)
1958{
1959 if (!context->getExtensions().disjointTimerQuery)
1960 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001961 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001962 return false;
1963 }
1964
1965 if (!ValidateRobustEntryPoint(context, bufSize))
1966 {
1967 return false;
1968 }
1969
1970 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1971 {
1972 return false;
1973 }
1974
1975 if (!ValidateRobustBufferSize(context, bufSize, *length))
1976 {
1977 return false;
1978 }
1979
1980 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001981}
1982
Jiajia Qin5451d532017-11-16 17:16:34 +08001983bool ValidateUniformCommonBase(ValidationContext *context,
1984 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05001985 GLint location,
1986 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08001987 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05001988{
Jiajia Qin5451d532017-11-16 17:16:34 +08001989 // TODO(Jiajia): Add image uniform check in future.
1990 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05001991 {
Jiajia Qin5451d532017-11-16 17:16:34 +08001992 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05001993 return false;
1994 }
1995
Jiajia Qin5451d532017-11-16 17:16:34 +08001996 if (!program)
1997 {
1998 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
1999 return false;
2000 }
2001
2002 if (!program->isLinked())
2003 {
2004 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2005 return false;
2006 }
2007
2008 if (location == -1)
2009 {
2010 // Silently ignore the uniform command
2011 return false;
2012 }
2013
2014 const auto &uniformLocations = program->getUniformLocations();
2015 size_t castedLocation = static_cast<size_t>(location);
2016 if (castedLocation >= uniformLocations.size())
2017 {
2018 context->handleError(InvalidOperation() << "Invalid uniform location");
2019 return false;
2020 }
2021
2022 const auto &uniformLocation = uniformLocations[castedLocation];
2023 if (uniformLocation.ignored)
2024 {
2025 // Silently ignore the uniform command
2026 return false;
2027 }
2028
2029 if (!uniformLocation.used())
2030 {
2031 context->handleError(InvalidOperation());
2032 return false;
2033 }
2034
2035 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2036
2037 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2038 if (!uniform.isArray() && count > 1)
2039 {
2040 context->handleError(InvalidOperation());
2041 return false;
2042 }
2043
2044 *uniformOut = &uniform;
2045 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002046}
2047
Jiajia Qin5451d532017-11-16 17:16:34 +08002048bool ValidateUniform1ivValue(ValidationContext *context,
2049 GLenum uniformType,
2050 GLsizei count,
2051 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002052{
Jiajia Qin5451d532017-11-16 17:16:34 +08002053 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2054 // It is compatible with INT or BOOL.
2055 // Do these cheap tests first, for a little extra speed.
2056 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002057 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002058 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002059 }
2060
Jiajia Qin5451d532017-11-16 17:16:34 +08002061 if (IsSamplerType(uniformType))
2062 {
2063 // Check that the values are in range.
2064 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2065 for (GLsizei i = 0; i < count; ++i)
2066 {
2067 if (value[i] < 0 || value[i] >= max)
2068 {
2069 context->handleError(InvalidValue() << "sampler uniform value out of range");
2070 return false;
2071 }
2072 }
2073 return true;
2074 }
2075
2076 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2077 return false;
2078}
2079
2080bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2081{
2082 // Check that the value type is compatible with uniform type.
2083 // Do the cheaper test first, for a little extra speed.
2084 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2085 {
2086 return true;
2087 }
2088
2089 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2090 return false;
2091}
2092
2093bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2094{
2095 // Check that the value type is compatible with uniform type.
2096 if (valueType == uniformType)
2097 {
2098 return true;
2099 }
2100
2101 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2102 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002103}
2104
Jamie Madillc1d770e2017-04-13 17:31:24 -04002105bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002106{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002107 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002108 gl::Program *programObject = context->getGLState().getProgram();
2109 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2110 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002111}
2112
Jamie Madillbe849e42017-05-02 15:49:00 -04002113bool ValidateUniform1iv(ValidationContext *context,
2114 GLint location,
2115 GLsizei count,
2116 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002117{
2118 const LinkedUniform *uniform = nullptr;
2119 gl::Program *programObject = context->getGLState().getProgram();
2120 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2121 ValidateUniform1ivValue(context, uniform->type, count, value);
2122}
2123
Jamie Madillc1d770e2017-04-13 17:31:24 -04002124bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002125 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002126 GLint location,
2127 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002128 GLboolean transpose)
2129{
Geoff Lang92019432017-11-20 13:09:34 -05002130 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002131 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002132 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002133 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002134 }
2135
Jamie Madill62d31cb2015-09-11 13:25:51 -04002136 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002137 gl::Program *programObject = context->getGLState().getProgram();
2138 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2139 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002140}
2141
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002142bool ValidateStateQuery(ValidationContext *context,
2143 GLenum pname,
2144 GLenum *nativeType,
2145 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002146{
2147 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2148 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002149 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002150 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002151 }
2152
Jamie Madill0af26e12015-03-05 19:54:33 -05002153 const Caps &caps = context->getCaps();
2154
Jamie Madill893ab082014-05-16 16:56:10 -04002155 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2156 {
2157 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2158
Jamie Madill0af26e12015-03-05 19:54:33 -05002159 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002160 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002161 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002162 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002163 }
2164 }
2165
2166 switch (pname)
2167 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002168 case GL_TEXTURE_BINDING_2D:
2169 case GL_TEXTURE_BINDING_CUBE_MAP:
2170 case GL_TEXTURE_BINDING_3D:
2171 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002172 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002173 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002174 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2175 if (!context->getExtensions().textureRectangle)
2176 {
2177 context->handleError(InvalidEnum()
2178 << "ANGLE_texture_rectangle extension not present");
2179 return false;
2180 }
2181 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002182 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2183 if (!context->getExtensions().eglStreamConsumerExternal &&
2184 !context->getExtensions().eglImageExternal)
2185 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002186 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2187 "nor GL_OES_EGL_image_external "
2188 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002189 return false;
2190 }
2191 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002192
He Yunchaoced53ae2016-11-29 15:00:51 +08002193 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2194 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002195 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002196 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2197 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002198 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002199 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002200 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002201 }
2202
Jamie Madill51f40ec2016-06-15 14:06:00 -04002203 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2204 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002205
2206 if (framebuffer->getReadBufferState() == GL_NONE)
2207 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002208 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002209 return false;
2210 }
2211
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002212 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002213 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002214 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002215 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002216 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002217 }
2218 }
2219 break;
2220
He Yunchaoced53ae2016-11-29 15:00:51 +08002221 default:
2222 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002223 }
2224
2225 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002226 if (*numParams == 0)
2227 {
2228 return false;
2229 }
2230
2231 return true;
2232}
2233
2234bool ValidateRobustStateQuery(ValidationContext *context,
2235 GLenum pname,
2236 GLsizei bufSize,
2237 GLenum *nativeType,
2238 unsigned int *numParams)
2239{
2240 if (!ValidateRobustEntryPoint(context, bufSize))
2241 {
2242 return false;
2243 }
2244
2245 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2246 {
2247 return false;
2248 }
2249
2250 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002251 {
2252 return false;
2253 }
2254
2255 return true;
2256}
2257
Jamie Madillc29968b2016-01-20 11:17:23 -05002258bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2259 GLenum target,
2260 GLint level,
2261 GLenum internalformat,
2262 bool isSubImage,
2263 GLint xoffset,
2264 GLint yoffset,
2265 GLint zoffset,
2266 GLint x,
2267 GLint y,
2268 GLsizei width,
2269 GLsizei height,
2270 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002271 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002272{
Brandon Jones6cad5662017-06-14 13:25:13 -07002273 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002274 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002275 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2276 return false;
2277 }
2278
2279 if (width < 0 || height < 0)
2280 {
2281 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002282 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002283 }
2284
He Yunchaoced53ae2016-11-29 15:00:51 +08002285 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2286 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002287 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002288 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002289 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002290 }
2291
2292 if (border != 0)
2293 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002294 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002295 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002296 }
2297
2298 if (!ValidMipLevel(context, target, level))
2299 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002300 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002301 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002302 }
2303
Jamie Madill51f40ec2016-06-15 14:06:00 -04002304 const auto &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002305 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002306 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002307 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002308 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002309 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002310 }
2311
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002312 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002313 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002314 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002315 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002316 }
2317
Martin Radev138064f2016-07-15 12:03:41 +03002318 if (readFramebuffer->getReadBufferState() == GL_NONE)
2319 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002320 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002321 return false;
2322 }
2323
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002324 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2325 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002326 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002327 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002328 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2329 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002330 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002331 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002332 return false;
2333 }
2334
Martin Radev04e2c3b2017-07-27 16:54:35 +03002335 // ANGLE_multiview spec, Revision 1:
2336 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2337 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2338 // is not NONE.
2339 if (source->getMultiviewLayout() != GL_NONE)
2340 {
2341 context->handleError(InvalidFramebufferOperation()
2342 << "The active read framebuffer object has multiview attachments.");
2343 return false;
2344 }
2345
Geoff Langaae65a42014-05-26 12:43:44 -04002346 const gl::Caps &caps = context->getCaps();
2347
Geoff Langaae65a42014-05-26 12:43:44 -04002348 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002349 switch (target)
2350 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002351 case GL_TEXTURE_2D:
2352 maxDimension = caps.max2DTextureSize;
2353 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002354
He Yunchaoced53ae2016-11-29 15:00:51 +08002355 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2356 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2357 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2358 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2359 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2360 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2361 maxDimension = caps.maxCubeMapTextureSize;
2362 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002363
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002364 case GL_TEXTURE_RECTANGLE_ANGLE:
2365 maxDimension = caps.maxRectangleTextureSize;
2366 break;
2367
He Yunchaoced53ae2016-11-29 15:00:51 +08002368 case GL_TEXTURE_2D_ARRAY:
2369 maxDimension = caps.max2DTextureSize;
2370 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002371
He Yunchaoced53ae2016-11-29 15:00:51 +08002372 case GL_TEXTURE_3D:
2373 maxDimension = caps.max3DTextureSize;
2374 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002375
He Yunchaoced53ae2016-11-29 15:00:51 +08002376 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002377 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002378 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002379 }
2380
Jamie Madillc29968b2016-01-20 11:17:23 -05002381 gl::Texture *texture =
2382 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002383 if (!texture)
2384 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002385 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002386 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002387 }
2388
Geoff Lang69cce582015-09-17 13:20:36 -04002389 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002390 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002391 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002392 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002393 }
2394
Geoff Langca271392017-04-05 12:30:00 -04002395 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002396 isSubImage ? *texture->getFormat(target, level).info
2397 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002398
Geoff Lang966c9402017-04-18 12:38:27 -04002399 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002400 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002401 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002402 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002403 }
2404
2405 if (isSubImage)
2406 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002407 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2408 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2409 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002411 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002412 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002413 }
2414 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002415 else
2416 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002417 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002418 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002419 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002420 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002421 }
2422
Geoff Langeb66a6e2016-10-31 13:06:12 -04002423 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002424 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002425 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002426 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002427 }
2428
2429 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002430 if (static_cast<int>(width) > maxLevelDimension ||
2431 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002432 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002433 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002434 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002435 }
2436 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002437
Jamie Madill0c8abca2016-07-22 20:21:26 -04002438 if (textureFormatOut)
2439 {
2440 *textureFormatOut = texture->getFormat(target, level);
2441 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002442
2443 // Detect texture copying feedback loops for WebGL.
2444 if (context->getExtensions().webglCompatibility)
2445 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002446 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002447 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002448 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002449 return false;
2450 }
2451 }
2452
Jamie Madill560a8d82014-05-21 13:06:20 -04002453 return true;
2454}
2455
Jiajia Qind9671222016-11-29 16:30:31 +08002456bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002457{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002458 switch (mode)
2459 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002460 case GL_POINTS:
2461 case GL_LINES:
2462 case GL_LINE_LOOP:
2463 case GL_LINE_STRIP:
2464 case GL_TRIANGLES:
2465 case GL_TRIANGLE_STRIP:
2466 case GL_TRIANGLE_FAN:
2467 break;
2468 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002469 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002470 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002471 }
2472
Jamie Madill250d33f2014-06-06 17:09:03 -04002473 if (count < 0)
2474 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002475 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002476 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002477 }
2478
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002479 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002480
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002481 const Extensions &extensions = context->getExtensions();
2482
2483 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2484 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2485 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2486 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002487 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002488 // Check for mapped buffers
2489 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002490 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002491 {
2492 context->handleError(InvalidOperation());
2493 return false;
2494 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002495 }
2496
Jamie Madillcbcde722017-01-06 14:50:00 -05002497 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2498 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002499 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002500 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002501 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002502 const FramebufferAttachment *dsAttachment =
2503 framebuffer->getStencilOrDepthStencilAttachment();
2504 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002505 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002506 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002507
2508 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2509 bool differentWritemasks =
2510 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2511 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2512 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2513 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2514
2515 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002516 {
Martin Radevffe754b2017-07-31 10:38:07 +03002517 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002518 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002519 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2520 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002521 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002522 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002523 return false;
2524 }
Jamie Madillac528012014-06-20 13:21:23 -04002525 }
2526
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002527 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002528 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002529 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002530 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002531 }
2532
Geoff Lang7dd2e102014-11-10 15:19:26 -05002533 gl::Program *program = state.getProgram();
2534 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002535 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002536 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002537 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002538 }
2539
Yunchao Hecddcb592017-11-13 15:27:35 +08002540 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2541 // vertex shader stage or fragment shader stage is a undefined behaviour.
2542 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2543 // produce undefined result.
Yunchao Heece12532017-11-21 15:50:21 +08002544 if (!program->hasLinkedVertexShader() || !program->hasLinkedFragmentShader())
Yunchao Hecddcb592017-11-13 15:27:35 +08002545 {
2546 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2547 "vertex shader stage or fragment shader stage.");
2548 return false;
2549 }
2550
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002551 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002552 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002553 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002554 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002555 }
2556
Martin Radevffe754b2017-07-31 10:38:07 +03002557 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002558 {
Martin Radevda8e2572017-09-12 17:21:16 +03002559 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002560 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002561 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002562 {
2563 context->handleError(InvalidOperation() << "The number of views in the active program "
2564 "and draw framebuffer does not match.");
2565 return false;
2566 }
Martin Radev7e69f762017-07-27 14:54:13 +03002567
2568 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2569 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2570 framebufferNumViews > 1)
2571 {
2572 context->handleError(InvalidOperation()
2573 << "There is an active transform feedback object "
2574 "when the number of views in the active draw "
2575 "framebuffer is greater than 1.");
2576 return false;
2577 }
Martin Radevffe754b2017-07-31 10:38:07 +03002578
2579 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2580 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2581 {
2582 context->handleError(InvalidOperation() << "There is an active query for target "
2583 "GL_TIME_ELAPSED_EXT when the number of "
2584 "views in the active draw framebuffer is "
2585 "greater than 1.");
2586 return false;
2587 }
Martin Radev7cf61662017-07-26 17:10:53 +03002588 }
2589
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002590 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002591 for (unsigned int uniformBlockIndex = 0;
2592 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002593 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002594 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002595 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002596 const OffsetBindingPointer<Buffer> &uniformBuffer =
2597 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002598
Geoff Lang5d124a62015-09-15 13:03:27 -04002599 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002600 {
2601 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002602 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002603 InvalidOperation()
2604 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002605 return false;
2606 }
2607
Geoff Lang5d124a62015-09-15 13:03:27 -04002608 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002609 if (uniformBufferSize == 0)
2610 {
2611 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002612 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002613 }
2614
Jamie Madill62d31cb2015-09-11 13:25:51 -04002615 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002616 {
2617 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002618 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002619 InvalidOperation()
2620 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002621 return false;
2622 }
2623 }
2624
Geoff Lange0cff192017-05-30 13:04:56 -04002625 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002626 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002627 {
Geoff Lange0cff192017-05-30 13:04:56 -04002628 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002629 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2630 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002631 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002632 return false;
2633 }
Geoff Lange0cff192017-05-30 13:04:56 -04002634
Geoff Lang9ab5b822017-05-30 16:19:23 -04002635 // Detect that the vertex shader input types match the attribute types
2636 if (!ValidateVertexShaderAttributeTypeMatch(context))
2637 {
2638 return false;
2639 }
2640
Geoff Lange0cff192017-05-30 13:04:56 -04002641 // Detect that the color buffer types match the fragment shader output types
2642 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2643 {
2644 return false;
2645 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002646 }
2647
Jamie Madill9fdaa492018-02-16 10:52:11 -05002648 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002649}
2650
Jamie Madillc1d770e2017-04-13 17:31:24 -04002651bool ValidateDrawArraysCommon(ValidationContext *context,
2652 GLenum mode,
2653 GLint first,
2654 GLsizei count,
2655 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002656{
Jamie Madillfd716582014-06-06 17:09:04 -04002657 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002658 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002659 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002660 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002661 }
2662
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002663 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002664 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002665 if (curTransformFeedback && curTransformFeedback->isActive() &&
2666 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002667 {
2668 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002669 // that does not match the current transform feedback object's draw mode (if transform
2670 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002671 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002672 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002673 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002674 }
2675
Jiajia Qind9671222016-11-29 16:30:31 +08002676 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002677 {
2678 return false;
2679 }
2680
Corentin Wallez71168a02016-12-19 15:11:18 -08002681 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002682 // - first < 0 has been checked as an error condition.
2683 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002684 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002685 ASSERT(first >= 0);
2686 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002687 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002688 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2689 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2690 {
2691 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2692 return false;
2693 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002694
Jamie Madill9fdaa492018-02-16 10:52:11 -05002695 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2696 {
2697 return false;
2698 }
Jamie Madillfd716582014-06-06 17:09:04 -04002699 }
2700
2701 return true;
2702}
2703
He Yunchaoced53ae2016-11-29 15:00:51 +08002704bool ValidateDrawArraysInstancedANGLE(Context *context,
2705 GLenum mode,
2706 GLint first,
2707 GLsizei count,
2708 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002709{
Geoff Lang63c5a592017-09-27 14:08:16 -04002710 if (!context->getExtensions().instancedArrays)
2711 {
2712 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2713 return false;
2714 }
2715
Corentin Wallez170efbf2017-05-02 13:45:01 -04002716 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002717 {
2718 return false;
2719 }
2720
Corentin Wallez0dc97812017-06-22 14:38:44 -04002721 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002722}
2723
Jiajia Qind9671222016-11-29 16:30:31 +08002724bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002725{
Jamie Madill250d33f2014-06-06 17:09:03 -04002726 switch (type)
2727 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002728 case GL_UNSIGNED_BYTE:
2729 case GL_UNSIGNED_SHORT:
2730 break;
2731 case GL_UNSIGNED_INT:
2732 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2733 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002734 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002735 return false;
2736 }
2737 break;
2738 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002739 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002740 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002741 }
2742
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002743 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002744
2745 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002746 if (curTransformFeedback && curTransformFeedback->isActive() &&
2747 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002748 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002749 // It is an invalid operation to call DrawElements, DrawRangeElements or
2750 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002751 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002752 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002753 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002754 }
2755
Jiajia Qind9671222016-11-29 16:30:31 +08002756 return true;
2757}
2758
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002759bool ValidateDrawElementsCommon(ValidationContext *context,
2760 GLenum mode,
2761 GLsizei count,
2762 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002763 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002764 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002765{
2766 if (!ValidateDrawElementsBase(context, type))
2767 return false;
2768
2769 const State &state = context->getGLState();
2770
Corentin Wallez170efbf2017-05-02 13:45:01 -04002771 if (!ValidateDrawBase(context, mode, count))
2772 {
2773 return false;
2774 }
2775
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002776 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2777 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2778 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2779 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002780 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002781 // Check for mapped buffers
2782 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002783 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002784 {
2785 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2786 return false;
2787 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002788 }
2789
He Yunchaoced53ae2016-11-29 15:00:51 +08002790 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002791 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002792
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002793 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2794
2795 if (context->getExtensions().webglCompatibility)
2796 {
2797 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2798 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2799 {
2800 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2801 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2802 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002803 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002804 return false;
2805 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002806
2807 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2808 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2809 // error is generated.
2810 if (reinterpret_cast<intptr_t>(indices) < 0)
2811 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002812 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002813 return false;
2814 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002815 }
2816
2817 if (context->getExtensions().webglCompatibility ||
2818 !context->getGLState().areClientArraysEnabled())
2819 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002820 if (!elementArrayBuffer && count > 0)
2821 {
2822 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2823 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2824 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002825 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002826 return false;
2827 }
2828 }
2829
Jamie Madill9fdaa492018-02-16 10:52:11 -05002830 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04002831 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002832 // This is an application error that would normally result in a crash, but we catch it and
2833 // return an error
2834 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
2835 return false;
2836 }
2837
2838 if (count > 0 && elementArrayBuffer)
2839 {
2840 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2841 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2842 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2843 constexpr uint64_t kMaxTypeSize = 8;
2844 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2845 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2846 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
2847
2848 uint64_t typeSize = typeBytes;
2849 uint64_t elementCount = static_cast<uint64_t>(count);
2850 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2851
2852 // Doing the multiplication here is overflow-safe
2853 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2854
2855 // The offset can be any value, check for overflows
2856 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2857 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04002858 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002859 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2860 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002861 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05002862
2863 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2864 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002865 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002866 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
2867 return false;
2868 }
2869
2870 ASSERT(isPow2(typeSize) && typeSize > 0);
2871 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
2872 {
2873 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04002874 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002875 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002876 }
2877
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002878 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002879 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002880 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2881 // access is enabled.
2882 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2883 {
2884 return false;
2885 }
2886 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05002887 else if (count == 0)
2888 {
2889 // ValidateDrawAttribs also does some extra validation that is independent of the vertex
2890 // count.
2891 if (!ValidateDrawAttribs(context, 0, 0, 0))
2892 {
2893 return false;
2894 }
2895 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002896 else
2897 {
2898 // Use the parameter buffer to retrieve and cache the index range.
2899 const auto &params = context->getParams<HasIndexRange>();
2900 const auto &indexRangeOpt = params.getIndexRange();
2901 if (!indexRangeOpt.valid())
2902 {
2903 // Unexpected error.
2904 return false;
2905 }
2906
2907 // If we use an index greater than our maximum supported index range, return an error.
2908 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2909 // return an error if possible here.
2910 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2911 {
2912 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2913 return false;
2914 }
2915
2916 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2917 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2918 {
2919 return false;
2920 }
2921
2922 // No op if there are no real indices in the index data (all are primitive restart).
2923 return (indexRangeOpt.value().vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002924 }
2925
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002926 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002927}
2928
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002929bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2930 GLenum mode,
2931 GLsizei count,
2932 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002933 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002934 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002935{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002936 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002937}
2938
Geoff Lang3edfe032015-09-04 16:38:24 -04002939bool ValidateDrawElementsInstancedANGLE(Context *context,
2940 GLenum mode,
2941 GLsizei count,
2942 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002943 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002944 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002945{
Geoff Lang63c5a592017-09-27 14:08:16 -04002946 if (!context->getExtensions().instancedArrays)
2947 {
2948 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2949 return false;
2950 }
2951
Corentin Wallez170efbf2017-05-02 13:45:01 -04002952 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002953 {
2954 return false;
2955 }
2956
Corentin Wallez0dc97812017-06-22 14:38:44 -04002957 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002958}
2959
He Yunchaoced53ae2016-11-29 15:00:51 +08002960bool ValidateFramebufferTextureBase(Context *context,
2961 GLenum target,
2962 GLenum attachment,
2963 GLuint texture,
2964 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002965{
Geoff Lange8afa902017-09-27 15:00:43 -04002966 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002967 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002968 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002969 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002970 }
2971
2972 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002973 {
2974 return false;
2975 }
2976
Jamie Madill55ec3b12014-07-03 10:38:57 -04002977 if (texture != 0)
2978 {
2979 gl::Texture *tex = context->getTexture(texture);
2980
Luc Ferronadcf0ae2018-01-24 08:27:37 -05002981 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002982 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002983 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002984 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002985 }
2986
2987 if (level < 0)
2988 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002989 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002990 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002991 }
2992 }
2993
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002994 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002995 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002996
Jamie Madill84115c92015-04-23 15:00:07 -04002997 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002998 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002999 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003000 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003001 }
3002
3003 return true;
3004}
3005
Geoff Langb1196682014-07-23 13:47:29 -04003006bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003007{
3008 if (program == 0)
3009 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003010 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003011 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003012 }
3013
Dian Xiang769769a2015-09-09 15:20:08 -07003014 gl::Program *programObject = GetValidProgram(context, program);
3015 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003016 {
3017 return false;
3018 }
3019
Jamie Madill0063c512014-08-25 15:47:53 -04003020 if (!programObject || !programObject->isLinked())
3021 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003022 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003023 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003024 }
3025
Geoff Lang7dd2e102014-11-10 15:19:26 -05003026 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003027 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003028 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003029 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003030 }
3031
Jamie Madill0063c512014-08-25 15:47:53 -04003032 return true;
3033}
3034
Geoff Langf41d0ee2016-10-07 13:04:23 -04003035static bool ValidateSizedGetUniform(Context *context,
3036 GLuint program,
3037 GLint location,
3038 GLsizei bufSize,
3039 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003040{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003041 if (length)
3042 {
3043 *length = 0;
3044 }
3045
Jamie Madill78f41802014-08-25 15:47:55 -04003046 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003047 {
Jamie Madill78f41802014-08-25 15:47:55 -04003048 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003049 }
3050
Geoff Langf41d0ee2016-10-07 13:04:23 -04003051 if (bufSize < 0)
3052 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003053 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003054 return false;
3055 }
3056
Jamie Madilla502c742014-08-28 17:19:13 -04003057 gl::Program *programObject = context->getProgram(program);
3058 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003059
Jamie Madill78f41802014-08-25 15:47:55 -04003060 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003061 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003062 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003063 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003064 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003065 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003066 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003067 }
3068
Geoff Langf41d0ee2016-10-07 13:04:23 -04003069 if (length)
3070 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003071 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003072 }
3073
Jamie Madill0063c512014-08-25 15:47:53 -04003074 return true;
3075}
3076
He Yunchaoced53ae2016-11-29 15:00:51 +08003077bool ValidateGetnUniformfvEXT(Context *context,
3078 GLuint program,
3079 GLint location,
3080 GLsizei bufSize,
3081 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003082{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003083 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003084}
3085
He Yunchaoced53ae2016-11-29 15:00:51 +08003086bool ValidateGetnUniformivEXT(Context *context,
3087 GLuint program,
3088 GLint location,
3089 GLsizei bufSize,
3090 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003091{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003092 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3093}
3094
3095bool ValidateGetUniformfvRobustANGLE(Context *context,
3096 GLuint program,
3097 GLint location,
3098 GLsizei bufSize,
3099 GLsizei *length,
3100 GLfloat *params)
3101{
3102 if (!ValidateRobustEntryPoint(context, bufSize))
3103 {
3104 return false;
3105 }
3106
3107 // bufSize is validated in ValidateSizedGetUniform
3108 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3109}
3110
3111bool ValidateGetUniformivRobustANGLE(Context *context,
3112 GLuint program,
3113 GLint location,
3114 GLsizei bufSize,
3115 GLsizei *length,
3116 GLint *params)
3117{
3118 if (!ValidateRobustEntryPoint(context, bufSize))
3119 {
3120 return false;
3121 }
3122
3123 // bufSize is validated in ValidateSizedGetUniform
3124 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3125}
3126
3127bool ValidateGetUniformuivRobustANGLE(Context *context,
3128 GLuint program,
3129 GLint location,
3130 GLsizei bufSize,
3131 GLsizei *length,
3132 GLuint *params)
3133{
3134 if (!ValidateRobustEntryPoint(context, bufSize))
3135 {
3136 return false;
3137 }
3138
3139 if (context->getClientMajorVersion() < 3)
3140 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003141 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003142 return false;
3143 }
3144
3145 // bufSize is validated in ValidateSizedGetUniform
3146 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003147}
3148
He Yunchaoced53ae2016-11-29 15:00:51 +08003149bool ValidateDiscardFramebufferBase(Context *context,
3150 GLenum target,
3151 GLsizei numAttachments,
3152 const GLenum *attachments,
3153 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003154{
3155 if (numAttachments < 0)
3156 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003157 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003158 return false;
3159 }
3160
3161 for (GLsizei i = 0; i < numAttachments; ++i)
3162 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003163 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003164 {
3165 if (defaultFramebuffer)
3166 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003167 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003168 return false;
3169 }
3170
3171 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3172 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003173 context->handleError(InvalidOperation() << "Requested color attachment is "
3174 "greater than the maximum supported "
3175 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003176 return false;
3177 }
3178 }
3179 else
3180 {
3181 switch (attachments[i])
3182 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003183 case GL_DEPTH_ATTACHMENT:
3184 case GL_STENCIL_ATTACHMENT:
3185 case GL_DEPTH_STENCIL_ATTACHMENT:
3186 if (defaultFramebuffer)
3187 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003188 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3189 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003190 return false;
3191 }
3192 break;
3193 case GL_COLOR:
3194 case GL_DEPTH:
3195 case GL_STENCIL:
3196 if (!defaultFramebuffer)
3197 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003198 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3199 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003200 return false;
3201 }
3202 break;
3203 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003204 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003205 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003206 }
3207 }
3208 }
3209
3210 return true;
3211}
3212
Austin Kinross6ee1e782015-05-29 17:05:37 -07003213bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3214{
Jamie Madill007530e2017-12-28 14:27:04 -05003215 if (!context->getExtensions().debugMarker)
3216 {
3217 // The debug marker calls should not set error state
3218 // However, it seems reasonable to set an error state if the extension is not enabled
3219 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3220 return false;
3221 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003222
Jamie Madill007530e2017-12-28 14:27:04 -05003223 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003224 if (length < 0)
3225 {
3226 return false;
3227 }
3228
3229 if (marker == nullptr)
3230 {
3231 return false;
3232 }
3233
3234 return true;
3235}
3236
3237bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3238{
Jamie Madill007530e2017-12-28 14:27:04 -05003239 if (!context->getExtensions().debugMarker)
3240 {
3241 // The debug marker calls should not set error state
3242 // However, it seems reasonable to set an error state if the extension is not enabled
3243 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3244 return false;
3245 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003246
Jamie Madill007530e2017-12-28 14:27:04 -05003247 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003248 if (length < 0)
3249 {
3250 return false;
3251 }
3252
3253 if (length > 0 && marker == nullptr)
3254 {
3255 return false;
3256 }
3257
3258 return true;
3259}
3260
Jamie Madill007530e2017-12-28 14:27:04 -05003261bool ValidateEGLImageTargetTexture2DOES(Context *context, GLenum target, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003262{
Geoff Langa8406172015-07-21 16:53:39 -04003263 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3264 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003265 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003266 return false;
3267 }
3268
3269 switch (target)
3270 {
3271 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003272 if (!context->getExtensions().eglImage)
3273 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003274 context->handleError(InvalidEnum()
3275 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003276 }
3277 break;
3278
3279 case GL_TEXTURE_EXTERNAL_OES:
3280 if (!context->getExtensions().eglImageExternal)
3281 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003282 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3283 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003284 }
Geoff Langa8406172015-07-21 16:53:39 -04003285 break;
3286
3287 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003288 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003289 return false;
3290 }
3291
Jamie Madill007530e2017-12-28 14:27:04 -05003292 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3293
Jamie Madill61e16b42017-06-19 11:13:23 -04003294 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003295 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003296 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003297 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003298 return false;
3299 }
3300
Jamie Madill007530e2017-12-28 14:27:04 -05003301 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003302 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003303 context->handleError(InvalidOperation()
3304 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003305 return false;
3306 }
3307
Geoff Langca271392017-04-05 12:30:00 -04003308 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003309 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003310 if (!textureCaps.texturable)
3311 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003312 context->handleError(InvalidOperation()
3313 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003314 return false;
3315 }
3316
Geoff Langdcab33b2015-07-21 13:03:16 -04003317 return true;
3318}
3319
3320bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003321 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003322 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003323{
Geoff Langa8406172015-07-21 16:53:39 -04003324 if (!context->getExtensions().eglImage)
3325 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003326 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003327 return false;
3328 }
3329
3330 switch (target)
3331 {
3332 case GL_RENDERBUFFER:
3333 break;
3334
3335 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003336 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003337 return false;
3338 }
3339
Jamie Madill007530e2017-12-28 14:27:04 -05003340 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3341
Jamie Madill61e16b42017-06-19 11:13:23 -04003342 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003343 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003344 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003345 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003346 return false;
3347 }
3348
Geoff Langca271392017-04-05 12:30:00 -04003349 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003350 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003351 if (!textureCaps.renderable)
3352 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003353 context->handleError(InvalidOperation()
3354 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003355 return false;
3356 }
3357
Geoff Langdcab33b2015-07-21 13:03:16 -04003358 return true;
3359}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003360
3361bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3362{
Geoff Lang36167ab2015-12-07 10:27:14 -05003363 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003364 {
3365 // The default VAO should always exist
3366 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003367 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003368 return false;
3369 }
3370
3371 return true;
3372}
3373
Geoff Langc5629752015-12-07 16:29:04 -05003374bool ValidateProgramBinaryBase(Context *context,
3375 GLuint program,
3376 GLenum binaryFormat,
3377 const void *binary,
3378 GLint length)
3379{
3380 Program *programObject = GetValidProgram(context, program);
3381 if (programObject == nullptr)
3382 {
3383 return false;
3384 }
3385
3386 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3387 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3388 programBinaryFormats.end())
3389 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003390 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003391 return false;
3392 }
3393
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003394 if (context->hasActiveTransformFeedback(program))
3395 {
3396 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003397 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3398 "is associated with an active transform "
3399 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003400 return false;
3401 }
3402
Geoff Langc5629752015-12-07 16:29:04 -05003403 return true;
3404}
3405
3406bool ValidateGetProgramBinaryBase(Context *context,
3407 GLuint program,
3408 GLsizei bufSize,
3409 GLsizei *length,
3410 GLenum *binaryFormat,
3411 void *binary)
3412{
3413 Program *programObject = GetValidProgram(context, program);
3414 if (programObject == nullptr)
3415 {
3416 return false;
3417 }
3418
3419 if (!programObject->isLinked())
3420 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003421 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003422 return false;
3423 }
3424
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003425 if (context->getCaps().programBinaryFormats.empty())
3426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003427 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003428 return false;
3429 }
3430
Geoff Langc5629752015-12-07 16:29:04 -05003431 return true;
3432}
Jamie Madillc29968b2016-01-20 11:17:23 -05003433
Jamie Madillc29968b2016-01-20 11:17:23 -05003434bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3435{
3436 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003437 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003438 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003439 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3440 return false;
3441 }
3442 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3443 {
3444 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003445 return false;
3446 }
3447
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003448 ASSERT(context->getGLState().getDrawFramebuffer());
3449 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003450 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3451
3452 // This should come first before the check for the default frame buffer
3453 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3454 // rather than INVALID_OPERATION
3455 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3456 {
3457 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3458
3459 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003460 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3461 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003462 {
3463 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003464 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3465 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3466 // 3.1 is still a bit ambiguous about the error, but future specs are
3467 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003468 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003469 return false;
3470 }
3471 else if (bufs[colorAttachment] >= maxColorAttachment)
3472 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003473 context->handleError(InvalidOperation()
3474 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003475 return false;
3476 }
3477 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3478 frameBufferId != 0)
3479 {
3480 // INVALID_OPERATION-GL is bound to buffer and ith argument
3481 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003482 context->handleError(InvalidOperation()
3483 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003484 return false;
3485 }
3486 }
3487
3488 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3489 // and n is not 1 or bufs is bound to value other than BACK and NONE
3490 if (frameBufferId == 0)
3491 {
3492 if (n != 1)
3493 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003494 context->handleError(InvalidOperation()
3495 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003496 return false;
3497 }
3498
3499 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3500 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003501 context->handleError(
3502 InvalidOperation()
3503 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003504 return false;
3505 }
3506 }
3507
3508 return true;
3509}
3510
Geoff Lang496c02d2016-10-20 11:38:11 -07003511bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003512 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003513 GLenum pname,
3514 GLsizei *length,
3515 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003516{
Geoff Lang496c02d2016-10-20 11:38:11 -07003517 if (length)
3518 {
3519 *length = 0;
3520 }
3521
3522 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3523 {
3524 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003525 InvalidOperation()
3526 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003527 return false;
3528 }
3529
Corentin Walleze4477002017-12-01 14:39:58 -05003530 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003531 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003532 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003533 return false;
3534 }
3535
Geoff Lang496c02d2016-10-20 11:38:11 -07003536 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003537 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003538 case GL_BUFFER_MAP_POINTER:
3539 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003540
Geoff Lang496c02d2016-10-20 11:38:11 -07003541 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003542 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003543 return false;
3544 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003545
3546 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3547 // target bound to zero generate an INVALID_OPERATION error."
3548 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003549 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003550 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003551 context->handleError(InvalidOperation()
3552 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003553 return false;
3554 }
3555
Geoff Lang496c02d2016-10-20 11:38:11 -07003556 if (length)
3557 {
3558 *length = 1;
3559 }
3560
Olli Etuaho4f667482016-03-30 15:56:35 +03003561 return true;
3562}
3563
Corentin Wallez336129f2017-10-17 15:55:40 -04003564bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003565{
Corentin Walleze4477002017-12-01 14:39:58 -05003566 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003567 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003568 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003569 return false;
3570 }
3571
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003572 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003573
3574 if (buffer == nullptr || !buffer->isMapped())
3575 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003576 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003577 return false;
3578 }
3579
3580 return true;
3581}
3582
3583bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003584 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003585 GLintptr offset,
3586 GLsizeiptr length,
3587 GLbitfield access)
3588{
Corentin Walleze4477002017-12-01 14:39:58 -05003589 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003590 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003591 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003592 return false;
3593 }
3594
Brandon Jones6cad5662017-06-14 13:25:13 -07003595 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003596 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003597 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3598 return false;
3599 }
3600
3601 if (length < 0)
3602 {
3603 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003604 return false;
3605 }
3606
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003607 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003608
3609 if (!buffer)
3610 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003611 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003612 return false;
3613 }
3614
3615 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003616 CheckedNumeric<size_t> checkedOffset(offset);
3617 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003618
Jamie Madille2e406c2016-06-02 13:04:10 -04003619 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003620 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003621 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003622 return false;
3623 }
3624
3625 // Check for invalid bits in the mask
3626 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3627 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3628 GL_MAP_UNSYNCHRONIZED_BIT;
3629
3630 if (access & ~(allAccessBits))
3631 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003632 context->handleError(InvalidValue()
3633 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003634 return false;
3635 }
3636
3637 if (length == 0)
3638 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003639 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003640 return false;
3641 }
3642
3643 if (buffer->isMapped())
3644 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003645 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003646 return false;
3647 }
3648
3649 // Check for invalid bit combinations
3650 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3651 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003652 context->handleError(InvalidOperation()
3653 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003654 return false;
3655 }
3656
3657 GLbitfield writeOnlyBits =
3658 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3659
3660 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3661 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003662 context->handleError(InvalidOperation()
3663 << "Invalid access bits when mapping buffer for reading: 0x"
3664 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003665 return false;
3666 }
3667
3668 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3669 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003670 context->handleError(
3671 InvalidOperation()
3672 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003673 return false;
3674 }
Geoff Lang79f71042017-08-14 16:43:43 -04003675
3676 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003677}
3678
3679bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003680 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003681 GLintptr offset,
3682 GLsizeiptr length)
3683{
Brandon Jones6cad5662017-06-14 13:25:13 -07003684 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003685 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003686 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3687 return false;
3688 }
3689
3690 if (length < 0)
3691 {
3692 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003693 return false;
3694 }
3695
Corentin Walleze4477002017-12-01 14:39:58 -05003696 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003697 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003698 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003699 return false;
3700 }
3701
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003702 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003703
3704 if (buffer == nullptr)
3705 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003706 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003707 return false;
3708 }
3709
3710 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3711 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003712 context->handleError(InvalidOperation()
3713 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003714 return false;
3715 }
3716
3717 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003718 CheckedNumeric<size_t> checkedOffset(offset);
3719 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003720
Jamie Madille2e406c2016-06-02 13:04:10 -04003721 if (!checkedSize.IsValid() ||
3722 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003724 context->handleError(InvalidValue()
3725 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003726 return false;
3727 }
3728
3729 return true;
3730}
3731
Olli Etuaho41997e72016-03-10 13:38:39 +02003732bool ValidateGenOrDelete(Context *context, GLint n)
3733{
3734 if (n < 0)
3735 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003736 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003737 return false;
3738 }
3739 return true;
3740}
3741
Geoff Langff5b2d52016-09-07 11:32:23 -04003742bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3743{
3744 if (!context->getExtensions().robustClientMemory)
3745 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003746 context->handleError(InvalidOperation()
3747 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003748 return false;
3749 }
3750
3751 if (bufSize < 0)
3752 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003753 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003754 return false;
3755 }
3756
3757 return true;
3758}
3759
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003760bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3761{
3762 if (bufSize < numParams)
3763 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003764 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3765 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003766 return false;
3767 }
3768
3769 return true;
3770}
3771
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003772bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04003773 GLenum target,
3774 GLenum attachment,
3775 GLenum pname,
3776 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003777{
Geoff Lange8afa902017-09-27 15:00:43 -04003778 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003779 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003780 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003781 return false;
3782 }
3783
3784 int clientVersion = context->getClientMajorVersion();
3785
3786 switch (pname)
3787 {
3788 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3789 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3790 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3791 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3792 break;
3793
Martin Radeve5285d22017-07-14 16:23:53 +03003794 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3795 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3796 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3797 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3798 if (clientVersion < 3 || !context->getExtensions().multiview)
3799 {
3800 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3801 return false;
3802 }
3803 break;
3804
Geoff Langff5b2d52016-09-07 11:32:23 -04003805 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3806 if (clientVersion < 3 && !context->getExtensions().sRGB)
3807 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003808 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003809 return false;
3810 }
3811 break;
3812
3813 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3814 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3815 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3816 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3817 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3818 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3819 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3820 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3821 if (clientVersion < 3)
3822 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003823 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003824 return false;
3825 }
3826 break;
3827
3828 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003829 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003830 return false;
3831 }
3832
3833 // Determine if the attachment is a valid enum
3834 switch (attachment)
3835 {
3836 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04003837 case GL_DEPTH:
3838 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04003839 if (clientVersion < 3)
3840 {
Geoff Langfa125c92017-10-24 13:01:46 -04003841 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003842 return false;
3843 }
3844 break;
3845
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003846 case GL_DEPTH_STENCIL_ATTACHMENT:
3847 if (clientVersion < 3 && !context->isWebGL1())
3848 {
3849 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3850 return false;
3851 }
3852 break;
3853
Geoff Langfa125c92017-10-24 13:01:46 -04003854 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003855 case GL_DEPTH_ATTACHMENT:
3856 case GL_STENCIL_ATTACHMENT:
3857 break;
3858
3859 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003860 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3861 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003862 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3863 {
Geoff Langfa125c92017-10-24 13:01:46 -04003864 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003865 return false;
3866 }
3867 break;
3868 }
3869
3870 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3871 ASSERT(framebuffer);
3872
3873 if (framebuffer->id() == 0)
3874 {
3875 if (clientVersion < 3)
3876 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003877 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003878 return false;
3879 }
3880
3881 switch (attachment)
3882 {
3883 case GL_BACK:
3884 case GL_DEPTH:
3885 case GL_STENCIL:
3886 break;
3887
3888 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003889 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003890 return false;
3891 }
3892 }
3893 else
3894 {
3895 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3896 {
3897 // Valid attachment query
3898 }
3899 else
3900 {
3901 switch (attachment)
3902 {
3903 case GL_DEPTH_ATTACHMENT:
3904 case GL_STENCIL_ATTACHMENT:
3905 break;
3906
3907 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003908 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04003909 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003910 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003911 return false;
3912 }
3913 break;
3914
3915 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003916 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003917 return false;
3918 }
3919 }
3920 }
3921
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003922 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003923 if (attachmentObject)
3924 {
3925 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3926 attachmentObject->type() == GL_TEXTURE ||
3927 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3928
3929 switch (pname)
3930 {
3931 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3932 if (attachmentObject->type() != GL_RENDERBUFFER &&
3933 attachmentObject->type() != GL_TEXTURE)
3934 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003935 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003936 return false;
3937 }
3938 break;
3939
3940 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3941 if (attachmentObject->type() != GL_TEXTURE)
3942 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003943 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003944 return false;
3945 }
3946 break;
3947
3948 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3949 if (attachmentObject->type() != GL_TEXTURE)
3950 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003951 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003952 return false;
3953 }
3954 break;
3955
3956 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3957 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3958 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003959 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003960 return false;
3961 }
3962 break;
3963
3964 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3965 if (attachmentObject->type() != GL_TEXTURE)
3966 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003967 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003968 return false;
3969 }
3970 break;
3971
3972 default:
3973 break;
3974 }
3975 }
3976 else
3977 {
3978 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3979 // is NONE, then querying any other pname will generate INVALID_ENUM.
3980
3981 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3982 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3983 // INVALID_OPERATION for all other pnames
3984
3985 switch (pname)
3986 {
3987 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3988 break;
3989
3990 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3991 if (clientVersion < 3)
3992 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003993 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003994 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003995 return false;
3996 }
3997 break;
3998
3999 default:
4000 if (clientVersion < 3)
4001 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004002 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004003 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004004 return false;
4005 }
4006 else
4007 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004008 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004009 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004010 return false;
4011 }
4012 }
4013 }
4014
Martin Radeve5285d22017-07-14 16:23:53 +03004015 if (numParams)
4016 {
4017 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4018 {
4019 // Only when the viewport offsets are queried we can have a varying number of output
4020 // parameters.
4021 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4022 *numParams = numViews * 2;
4023 }
4024 else
4025 {
4026 // For all other queries we can have only one output parameter.
4027 *numParams = 1;
4028 }
4029 }
4030
Geoff Langff5b2d52016-09-07 11:32:23 -04004031 return true;
4032}
4033
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004034bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004035 GLenum target,
4036 GLenum attachment,
4037 GLenum pname,
4038 GLsizei bufSize,
4039 GLsizei *numParams)
4040{
4041 if (!ValidateRobustEntryPoint(context, bufSize))
4042 {
4043 return false;
4044 }
4045
Jamie Madillbe849e42017-05-02 15:49:00 -04004046 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4047 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004048 {
4049 return false;
4050 }
4051
4052 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4053 {
4054 return false;
4055 }
4056
4057 return true;
4058}
4059
Geoff Langff5b2d52016-09-07 11:32:23 -04004060bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004061 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004062 GLenum pname,
4063 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004064 GLsizei *length,
4065 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004066{
4067 if (!ValidateRobustEntryPoint(context, bufSize))
4068 {
4069 return false;
4070 }
4071
Geoff Langebebe1c2016-10-14 12:01:31 -04004072 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004073 {
4074 return false;
4075 }
4076
Geoff Langebebe1c2016-10-14 12:01:31 -04004077 if (!ValidateRobustBufferSize(context, bufSize, *length))
4078 {
4079 return false;
4080 }
4081
4082 return true;
4083}
4084
Geoff Langebebe1c2016-10-14 12:01:31 -04004085bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004086 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004087 GLenum pname,
4088 GLsizei bufSize,
4089 GLsizei *length,
4090 GLint64 *params)
4091{
4092 if (!ValidateRobustEntryPoint(context, bufSize))
4093 {
4094 return false;
4095 }
4096
4097 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4098 {
4099 return false;
4100 }
4101
4102 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004103 {
4104 return false;
4105 }
4106
4107 return true;
4108}
4109
Jamie Madillbe849e42017-05-02 15:49:00 -04004110bool ValidateGetProgramivBase(ValidationContext *context,
4111 GLuint program,
4112 GLenum pname,
4113 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004114{
4115 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004116 if (numParams)
4117 {
4118 *numParams = 1;
4119 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004120
4121 Program *programObject = GetValidProgram(context, program);
4122 if (!programObject)
4123 {
4124 return false;
4125 }
4126
4127 switch (pname)
4128 {
4129 case GL_DELETE_STATUS:
4130 case GL_LINK_STATUS:
4131 case GL_VALIDATE_STATUS:
4132 case GL_INFO_LOG_LENGTH:
4133 case GL_ATTACHED_SHADERS:
4134 case GL_ACTIVE_ATTRIBUTES:
4135 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4136 case GL_ACTIVE_UNIFORMS:
4137 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4138 break;
4139
4140 case GL_PROGRAM_BINARY_LENGTH:
4141 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4142 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004143 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4144 "requires GL_OES_get_program_binary or "
4145 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004146 return false;
4147 }
4148 break;
4149
4150 case GL_ACTIVE_UNIFORM_BLOCKS:
4151 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4152 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4153 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4154 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4155 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4156 if (context->getClientMajorVersion() < 3)
4157 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004158 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004159 return false;
4160 }
4161 break;
4162
Yunchao He61afff12017-03-14 15:34:03 +08004163 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004164 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004165 if (context->getClientVersion() < Version(3, 1))
4166 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004167 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004168 return false;
4169 }
4170 break;
4171
Jiawei Shao6ae51612018-02-23 14:03:25 +08004172 case GL_COMPUTE_WORK_GROUP_SIZE:
4173 if (context->getClientVersion() < Version(3, 1))
4174 {
4175 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4176 return false;
4177 }
4178
4179 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4180 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4181 // program which has not been linked successfully, or which does not contain objects to
4182 // form a compute shader.
4183 if (!programObject->isLinked())
4184 {
4185 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4186 return false;
4187 }
4188 if (!programObject->hasLinkedComputeShader())
4189 {
4190 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4191 return false;
4192 }
4193 break;
4194
Geoff Langff5b2d52016-09-07 11:32:23 -04004195 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004196 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004197 return false;
4198 }
4199
4200 return true;
4201}
4202
4203bool ValidateGetProgramivRobustANGLE(Context *context,
4204 GLuint program,
4205 GLenum pname,
4206 GLsizei bufSize,
4207 GLsizei *numParams)
4208{
4209 if (!ValidateRobustEntryPoint(context, bufSize))
4210 {
4211 return false;
4212 }
4213
Jamie Madillbe849e42017-05-02 15:49:00 -04004214 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004215 {
4216 return false;
4217 }
4218
4219 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4220 {
4221 return false;
4222 }
4223
4224 return true;
4225}
4226
Geoff Lang740d9022016-10-07 11:20:52 -04004227bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4228 GLenum target,
4229 GLenum pname,
4230 GLsizei bufSize,
4231 GLsizei *length,
4232 GLint *params)
4233{
4234 if (!ValidateRobustEntryPoint(context, bufSize))
4235 {
4236 return false;
4237 }
4238
4239 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4240 {
4241 return false;
4242 }
4243
4244 if (!ValidateRobustBufferSize(context, bufSize, *length))
4245 {
4246 return false;
4247 }
4248
4249 return true;
4250}
4251
Geoff Langd7d0ed32016-10-07 11:33:51 -04004252bool ValidateGetShaderivRobustANGLE(Context *context,
4253 GLuint shader,
4254 GLenum pname,
4255 GLsizei bufSize,
4256 GLsizei *length,
4257 GLint *params)
4258{
4259 if (!ValidateRobustEntryPoint(context, bufSize))
4260 {
4261 return false;
4262 }
4263
4264 if (!ValidateGetShaderivBase(context, shader, pname, length))
4265 {
4266 return false;
4267 }
4268
4269 if (!ValidateRobustBufferSize(context, bufSize, *length))
4270 {
4271 return false;
4272 }
4273
4274 return true;
4275}
4276
Geoff Langc1984ed2016-10-07 12:41:00 -04004277bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4278 GLenum target,
4279 GLenum pname,
4280 GLsizei bufSize,
4281 GLsizei *length,
4282 GLfloat *params)
4283{
4284 if (!ValidateRobustEntryPoint(context, bufSize))
4285 {
4286 return false;
4287 }
4288
4289 if (!ValidateGetTexParameterBase(context, target, pname, length))
4290 {
4291 return false;
4292 }
4293
4294 if (!ValidateRobustBufferSize(context, bufSize, *length))
4295 {
4296 return false;
4297 }
4298
4299 return true;
4300}
4301
Geoff Langc1984ed2016-10-07 12:41:00 -04004302bool ValidateGetTexParameterivRobustANGLE(Context *context,
4303 GLenum target,
4304 GLenum pname,
4305 GLsizei bufSize,
4306 GLsizei *length,
4307 GLint *params)
4308{
4309 if (!ValidateRobustEntryPoint(context, bufSize))
4310 {
4311 return false;
4312 }
4313
4314 if (!ValidateGetTexParameterBase(context, target, pname, length))
4315 {
4316 return false;
4317 }
4318
4319 if (!ValidateRobustBufferSize(context, bufSize, *length))
4320 {
4321 return false;
4322 }
4323
4324 return true;
4325}
4326
Geoff Langc1984ed2016-10-07 12:41:00 -04004327bool ValidateTexParameterfvRobustANGLE(Context *context,
4328 GLenum target,
4329 GLenum pname,
4330 GLsizei bufSize,
4331 const GLfloat *params)
4332{
4333 if (!ValidateRobustEntryPoint(context, bufSize))
4334 {
4335 return false;
4336 }
4337
4338 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4339}
4340
Geoff Langc1984ed2016-10-07 12:41:00 -04004341bool ValidateTexParameterivRobustANGLE(Context *context,
4342 GLenum target,
4343 GLenum pname,
4344 GLsizei bufSize,
4345 const GLint *params)
4346{
4347 if (!ValidateRobustEntryPoint(context, bufSize))
4348 {
4349 return false;
4350 }
4351
4352 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4353}
4354
Geoff Langc1984ed2016-10-07 12:41:00 -04004355bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4356 GLuint sampler,
4357 GLenum pname,
4358 GLuint bufSize,
4359 GLsizei *length,
4360 GLfloat *params)
4361{
4362 if (!ValidateRobustEntryPoint(context, bufSize))
4363 {
4364 return false;
4365 }
4366
4367 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4368 {
4369 return false;
4370 }
4371
4372 if (!ValidateRobustBufferSize(context, bufSize, *length))
4373 {
4374 return false;
4375 }
4376
4377 return true;
4378}
4379
Geoff Langc1984ed2016-10-07 12:41:00 -04004380bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4381 GLuint sampler,
4382 GLenum pname,
4383 GLuint bufSize,
4384 GLsizei *length,
4385 GLint *params)
4386{
4387 if (!ValidateRobustEntryPoint(context, bufSize))
4388 {
4389 return false;
4390 }
4391
4392 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4393 {
4394 return false;
4395 }
4396
4397 if (!ValidateRobustBufferSize(context, bufSize, *length))
4398 {
4399 return false;
4400 }
4401
4402 return true;
4403}
4404
Geoff Langc1984ed2016-10-07 12:41:00 -04004405bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4406 GLuint sampler,
4407 GLenum pname,
4408 GLsizei bufSize,
4409 const GLfloat *params)
4410{
4411 if (!ValidateRobustEntryPoint(context, bufSize))
4412 {
4413 return false;
4414 }
4415
4416 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4417}
4418
Geoff Langc1984ed2016-10-07 12:41:00 -04004419bool ValidateSamplerParameterivRobustANGLE(Context *context,
4420 GLuint sampler,
4421 GLenum pname,
4422 GLsizei bufSize,
4423 const GLint *params)
4424{
4425 if (!ValidateRobustEntryPoint(context, bufSize))
4426 {
4427 return false;
4428 }
4429
4430 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4431}
4432
Geoff Lang0b031062016-10-13 14:30:04 -04004433bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4434 GLuint index,
4435 GLenum pname,
4436 GLsizei bufSize,
4437 GLsizei *length,
4438 GLfloat *params)
4439{
4440 if (!ValidateRobustEntryPoint(context, bufSize))
4441 {
4442 return false;
4443 }
4444
4445 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4446 {
4447 return false;
4448 }
4449
4450 if (!ValidateRobustBufferSize(context, bufSize, *length))
4451 {
4452 return false;
4453 }
4454
4455 return true;
4456}
4457
Geoff Lang0b031062016-10-13 14:30:04 -04004458bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4459 GLuint index,
4460 GLenum pname,
4461 GLsizei bufSize,
4462 GLsizei *length,
4463 GLint *params)
4464{
4465 if (!ValidateRobustEntryPoint(context, bufSize))
4466 {
4467 return false;
4468 }
4469
4470 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4471 {
4472 return false;
4473 }
4474
4475 if (!ValidateRobustBufferSize(context, bufSize, *length))
4476 {
4477 return false;
4478 }
4479
4480 return true;
4481}
4482
Geoff Lang0b031062016-10-13 14:30:04 -04004483bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4484 GLuint index,
4485 GLenum pname,
4486 GLsizei bufSize,
4487 GLsizei *length,
4488 void **pointer)
4489{
4490 if (!ValidateRobustEntryPoint(context, bufSize))
4491 {
4492 return false;
4493 }
4494
4495 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4496 {
4497 return false;
4498 }
4499
4500 if (!ValidateRobustBufferSize(context, bufSize, *length))
4501 {
4502 return false;
4503 }
4504
4505 return true;
4506}
4507
Geoff Lang0b031062016-10-13 14:30:04 -04004508bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4509 GLuint index,
4510 GLenum pname,
4511 GLsizei bufSize,
4512 GLsizei *length,
4513 GLint *params)
4514{
4515 if (!ValidateRobustEntryPoint(context, bufSize))
4516 {
4517 return false;
4518 }
4519
4520 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4521 {
4522 return false;
4523 }
4524
4525 if (!ValidateRobustBufferSize(context, bufSize, *length))
4526 {
4527 return false;
4528 }
4529
4530 return true;
4531}
4532
Geoff Lang0b031062016-10-13 14:30:04 -04004533bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4534 GLuint index,
4535 GLenum pname,
4536 GLsizei bufSize,
4537 GLsizei *length,
4538 GLuint *params)
4539{
4540 if (!ValidateRobustEntryPoint(context, bufSize))
4541 {
4542 return false;
4543 }
4544
4545 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4546 {
4547 return false;
4548 }
4549
4550 if (!ValidateRobustBufferSize(context, bufSize, *length))
4551 {
4552 return false;
4553 }
4554
4555 return true;
4556}
4557
Geoff Lang6899b872016-10-14 11:30:13 -04004558bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4559 GLuint program,
4560 GLuint uniformBlockIndex,
4561 GLenum pname,
4562 GLsizei bufSize,
4563 GLsizei *length,
4564 GLint *params)
4565{
4566 if (!ValidateRobustEntryPoint(context, bufSize))
4567 {
4568 return false;
4569 }
4570
4571 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4572 {
4573 return false;
4574 }
4575
4576 if (!ValidateRobustBufferSize(context, bufSize, *length))
4577 {
4578 return false;
4579 }
4580
4581 return true;
4582}
4583
Geoff Lang0a9661f2016-10-20 10:59:20 -07004584bool ValidateGetInternalFormativRobustANGLE(Context *context,
4585 GLenum target,
4586 GLenum internalformat,
4587 GLenum pname,
4588 GLsizei bufSize,
4589 GLsizei *length,
4590 GLint *params)
4591{
4592 if (!ValidateRobustEntryPoint(context, bufSize))
4593 {
4594 return false;
4595 }
4596
4597 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4598 {
4599 return false;
4600 }
4601
4602 if (!ValidateRobustBufferSize(context, bufSize, *length))
4603 {
4604 return false;
4605 }
4606
4607 return true;
4608}
4609
Shao80957d92017-02-20 21:25:59 +08004610bool ValidateVertexFormatBase(ValidationContext *context,
4611 GLuint attribIndex,
4612 GLint size,
4613 GLenum type,
4614 GLboolean pureInteger)
4615{
4616 const Caps &caps = context->getCaps();
4617 if (attribIndex >= caps.maxVertexAttributes)
4618 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004619 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004620 return false;
4621 }
4622
4623 if (size < 1 || size > 4)
4624 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004625 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004626 return false;
Shao80957d92017-02-20 21:25:59 +08004627 }
4628
4629 switch (type)
4630 {
4631 case GL_BYTE:
4632 case GL_UNSIGNED_BYTE:
4633 case GL_SHORT:
4634 case GL_UNSIGNED_SHORT:
4635 break;
4636
4637 case GL_INT:
4638 case GL_UNSIGNED_INT:
4639 if (context->getClientMajorVersion() < 3)
4640 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004641 context->handleError(InvalidEnum()
4642 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004643 return false;
4644 }
4645 break;
4646
4647 case GL_FIXED:
4648 case GL_FLOAT:
4649 if (pureInteger)
4650 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004651 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004652 return false;
4653 }
4654 break;
4655
4656 case GL_HALF_FLOAT:
4657 if (context->getClientMajorVersion() < 3)
4658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004659 context->handleError(InvalidEnum()
4660 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004661 return false;
4662 }
4663 if (pureInteger)
4664 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004665 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004666 return false;
4667 }
4668 break;
4669
4670 case GL_INT_2_10_10_10_REV:
4671 case GL_UNSIGNED_INT_2_10_10_10_REV:
4672 if (context->getClientMajorVersion() < 3)
4673 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004674 context->handleError(InvalidEnum()
4675 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004676 return false;
4677 }
4678 if (pureInteger)
4679 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004680 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004681 return false;
4682 }
4683 if (size != 4)
4684 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004685 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4686 "UNSIGNED_INT_2_10_10_10_REV and "
4687 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004688 return false;
4689 }
4690 break;
4691
4692 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004693 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004694 return false;
4695 }
4696
4697 return true;
4698}
4699
Geoff Lang76e65652017-03-27 14:58:02 -04004700// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4701// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4702// specified clear value and the type of a buffer that is being cleared generates an
4703// INVALID_OPERATION error instead of producing undefined results
4704bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4705 GLint drawbuffer,
4706 const GLenum *validComponentTypes,
4707 size_t validComponentTypeCount)
4708{
4709 const FramebufferAttachment *attachment =
4710 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4711 if (attachment)
4712 {
4713 GLenum componentType = attachment->getFormat().info->componentType;
4714 const GLenum *end = validComponentTypes + validComponentTypeCount;
4715 if (std::find(validComponentTypes, end, componentType) == end)
4716 {
4717 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004718 InvalidOperation()
4719 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004720 return false;
4721 }
4722 }
4723
4724 return true;
4725}
4726
Corentin Wallezb2931602017-04-11 15:58:57 -04004727bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4728 GLsizei imageSize,
4729 GLsizei dataSize)
4730{
4731 if (!ValidateRobustEntryPoint(context, dataSize))
4732 {
4733 return false;
4734 }
4735
Corentin Wallez336129f2017-10-17 15:55:40 -04004736 gl::Buffer *pixelUnpackBuffer =
4737 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004738 if (pixelUnpackBuffer == nullptr)
4739 {
4740 if (dataSize < imageSize)
4741 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004742 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004743 }
4744 }
4745 return true;
4746}
4747
Jamie Madillbe849e42017-05-02 15:49:00 -04004748bool ValidateGetBufferParameterBase(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004749 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004750 GLenum pname,
4751 bool pointerVersion,
4752 GLsizei *numParams)
4753{
4754 if (numParams)
4755 {
4756 *numParams = 0;
4757 }
4758
Corentin Walleze4477002017-12-01 14:39:58 -05004759 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004760 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004761 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004762 return false;
4763 }
4764
4765 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4766 if (!buffer)
4767 {
4768 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004769 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004770 return false;
4771 }
4772
4773 const Extensions &extensions = context->getExtensions();
4774
4775 switch (pname)
4776 {
4777 case GL_BUFFER_USAGE:
4778 case GL_BUFFER_SIZE:
4779 break;
4780
4781 case GL_BUFFER_ACCESS_OES:
4782 if (!extensions.mapBuffer)
4783 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004784 context->handleError(InvalidEnum()
4785 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004786 return false;
4787 }
4788 break;
4789
4790 case GL_BUFFER_MAPPED:
4791 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4792 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4793 !extensions.mapBufferRange)
4794 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004795 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4796 "GL_OES_mapbuffer or "
4797 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004798 return false;
4799 }
4800 break;
4801
4802 case GL_BUFFER_MAP_POINTER:
4803 if (!pointerVersion)
4804 {
4805 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004806 InvalidEnum()
4807 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004808 return false;
4809 }
4810 break;
4811
4812 case GL_BUFFER_ACCESS_FLAGS:
4813 case GL_BUFFER_MAP_OFFSET:
4814 case GL_BUFFER_MAP_LENGTH:
4815 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4816 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004817 context->handleError(InvalidEnum()
4818 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004819 return false;
4820 }
4821 break;
4822
4823 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004824 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004825 return false;
4826 }
4827
4828 // All buffer parameter queries return one value.
4829 if (numParams)
4830 {
4831 *numParams = 1;
4832 }
4833
4834 return true;
4835}
4836
4837bool ValidateGetRenderbufferParameterivBase(Context *context,
4838 GLenum target,
4839 GLenum pname,
4840 GLsizei *length)
4841{
4842 if (length)
4843 {
4844 *length = 0;
4845 }
4846
4847 if (target != GL_RENDERBUFFER)
4848 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004849 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004850 return false;
4851 }
4852
4853 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4854 if (renderbuffer == nullptr)
4855 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004856 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004857 return false;
4858 }
4859
4860 switch (pname)
4861 {
4862 case GL_RENDERBUFFER_WIDTH:
4863 case GL_RENDERBUFFER_HEIGHT:
4864 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4865 case GL_RENDERBUFFER_RED_SIZE:
4866 case GL_RENDERBUFFER_GREEN_SIZE:
4867 case GL_RENDERBUFFER_BLUE_SIZE:
4868 case GL_RENDERBUFFER_ALPHA_SIZE:
4869 case GL_RENDERBUFFER_DEPTH_SIZE:
4870 case GL_RENDERBUFFER_STENCIL_SIZE:
4871 break;
4872
4873 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4874 if (!context->getExtensions().framebufferMultisample)
4875 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004876 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004877 return false;
4878 }
4879 break;
4880
4881 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004882 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004883 return false;
4884 }
4885
4886 if (length)
4887 {
4888 *length = 1;
4889 }
4890 return true;
4891}
4892
4893bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4894{
4895 if (length)
4896 {
4897 *length = 0;
4898 }
4899
4900 if (GetValidShader(context, shader) == nullptr)
4901 {
4902 return false;
4903 }
4904
4905 switch (pname)
4906 {
4907 case GL_SHADER_TYPE:
4908 case GL_DELETE_STATUS:
4909 case GL_COMPILE_STATUS:
4910 case GL_INFO_LOG_LENGTH:
4911 case GL_SHADER_SOURCE_LENGTH:
4912 break;
4913
4914 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4915 if (!context->getExtensions().translatedShaderSource)
4916 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004917 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004918 return false;
4919 }
4920 break;
4921
4922 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004923 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004924 return false;
4925 }
4926
4927 if (length)
4928 {
4929 *length = 1;
4930 }
4931 return true;
4932}
4933
4934bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4935{
4936 if (length)
4937 {
4938 *length = 0;
4939 }
4940
4941 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4942 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004943 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004944 return false;
4945 }
4946
4947 if (context->getTargetTexture(target) == nullptr)
4948 {
4949 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004950 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004951 return false;
4952 }
4953
4954 switch (pname)
4955 {
4956 case GL_TEXTURE_MAG_FILTER:
4957 case GL_TEXTURE_MIN_FILTER:
4958 case GL_TEXTURE_WRAP_S:
4959 case GL_TEXTURE_WRAP_T:
4960 break;
4961
4962 case GL_TEXTURE_USAGE_ANGLE:
4963 if (!context->getExtensions().textureUsage)
4964 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004965 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004966 return false;
4967 }
4968 break;
4969
4970 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05004971 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04004972 {
Jamie Madillbe849e42017-05-02 15:49:00 -04004973 return false;
4974 }
4975 break;
4976
4977 case GL_TEXTURE_IMMUTABLE_FORMAT:
4978 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4979 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004980 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004981 return false;
4982 }
4983 break;
4984
4985 case GL_TEXTURE_WRAP_R:
4986 case GL_TEXTURE_IMMUTABLE_LEVELS:
4987 case GL_TEXTURE_SWIZZLE_R:
4988 case GL_TEXTURE_SWIZZLE_G:
4989 case GL_TEXTURE_SWIZZLE_B:
4990 case GL_TEXTURE_SWIZZLE_A:
4991 case GL_TEXTURE_BASE_LEVEL:
4992 case GL_TEXTURE_MAX_LEVEL:
4993 case GL_TEXTURE_MIN_LOD:
4994 case GL_TEXTURE_MAX_LOD:
4995 case GL_TEXTURE_COMPARE_MODE:
4996 case GL_TEXTURE_COMPARE_FUNC:
4997 if (context->getClientMajorVersion() < 3)
4998 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004999 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005000 return false;
5001 }
5002 break;
5003
5004 case GL_TEXTURE_SRGB_DECODE_EXT:
5005 if (!context->getExtensions().textureSRGBDecode)
5006 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005007 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005008 return false;
5009 }
5010 break;
5011
Yunchao Hebacaa712018-01-30 14:01:39 +08005012 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5013 if (context->getClientVersion() < Version(3, 1))
5014 {
5015 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5016 return false;
5017 }
5018 break;
5019
Jamie Madillbe849e42017-05-02 15:49:00 -04005020 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005021 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005022 return false;
5023 }
5024
5025 if (length)
5026 {
5027 *length = 1;
5028 }
5029 return true;
5030}
5031
5032bool ValidateGetVertexAttribBase(Context *context,
5033 GLuint index,
5034 GLenum pname,
5035 GLsizei *length,
5036 bool pointer,
5037 bool pureIntegerEntryPoint)
5038{
5039 if (length)
5040 {
5041 *length = 0;
5042 }
5043
5044 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5045 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005046 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005047 return false;
5048 }
5049
5050 if (index >= context->getCaps().maxVertexAttributes)
5051 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005052 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005053 return false;
5054 }
5055
5056 if (pointer)
5057 {
5058 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5059 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005060 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005061 return false;
5062 }
5063 }
5064 else
5065 {
5066 switch (pname)
5067 {
5068 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5069 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5070 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5071 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5072 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5073 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5074 case GL_CURRENT_VERTEX_ATTRIB:
5075 break;
5076
5077 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5078 static_assert(
5079 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5080 "ANGLE extension enums not equal to GL enums.");
5081 if (context->getClientMajorVersion() < 3 &&
5082 !context->getExtensions().instancedArrays)
5083 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005084 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5085 "requires OpenGL ES 3.0 or "
5086 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005087 return false;
5088 }
5089 break;
5090
5091 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5092 if (context->getClientMajorVersion() < 3)
5093 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005094 context->handleError(
5095 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005096 return false;
5097 }
5098 break;
5099
5100 case GL_VERTEX_ATTRIB_BINDING:
5101 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5102 if (context->getClientVersion() < ES_3_1)
5103 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005104 context->handleError(InvalidEnum()
5105 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005106 return false;
5107 }
5108 break;
5109
5110 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005111 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005112 return false;
5113 }
5114 }
5115
5116 if (length)
5117 {
5118 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5119 {
5120 *length = 4;
5121 }
5122 else
5123 {
5124 *length = 1;
5125 }
5126 }
5127
5128 return true;
5129}
5130
Jamie Madill4928b7c2017-06-20 12:57:39 -04005131bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005132 GLint x,
5133 GLint y,
5134 GLsizei width,
5135 GLsizei height,
5136 GLenum format,
5137 GLenum type,
5138 GLsizei bufSize,
5139 GLsizei *length,
5140 GLsizei *columns,
5141 GLsizei *rows,
5142 void *pixels)
5143{
5144 if (length != nullptr)
5145 {
5146 *length = 0;
5147 }
5148 if (rows != nullptr)
5149 {
5150 *rows = 0;
5151 }
5152 if (columns != nullptr)
5153 {
5154 *columns = 0;
5155 }
5156
5157 if (width < 0 || height < 0)
5158 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005159 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005160 return false;
5161 }
5162
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005163 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005164
5165 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5166 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005167 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005168 return false;
5169 }
5170
5171 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5172 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005173 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005174 return false;
5175 }
5176
5177 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5178 ASSERT(framebuffer);
5179
5180 if (framebuffer->getReadBufferState() == GL_NONE)
5181 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005182 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005183 return false;
5184 }
5185
5186 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5187 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5188 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5189 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5190 // situation is an application error that would lead to a crash in ANGLE.
5191 if (readBuffer == nullptr)
5192 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005193 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005194 return false;
5195 }
5196
Martin Radev28031682017-07-28 14:47:56 +03005197 // ANGLE_multiview, Revision 1:
5198 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5199 // current read framebuffer is not NONE.
5200 if (readBuffer->getMultiviewLayout() != GL_NONE)
5201 {
5202 context->handleError(InvalidFramebufferOperation()
5203 << "Attempting to read from a multi-view framebuffer.");
5204 return false;
5205 }
5206
Geoff Lang280ba992017-04-18 16:30:58 -04005207 if (context->getExtensions().webglCompatibility)
5208 {
5209 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5210 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5211 // and type before validating the combination of format and type. However, the
5212 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5213 // verifies that GL_INVALID_OPERATION is generated.
5214 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5215 // dEQP/WebGL.
5216 if (!ValidReadPixelsFormatEnum(context, format))
5217 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005218 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005219 return false;
5220 }
5221
5222 if (!ValidReadPixelsTypeEnum(context, type))
5223 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005224 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005225 return false;
5226 }
5227 }
5228
Jamie Madill4928b7c2017-06-20 12:57:39 -04005229 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5230 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005231 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5232
5233 bool validFormatTypeCombination =
5234 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5235
5236 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5237 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005238 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005239 return false;
5240 }
5241
5242 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005243 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005244 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5245 {
5246 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005247 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005248 return false;
5249 }
5250
5251 // .. the data would be packed to the buffer object such that the memory writes required
5252 // would exceed the data store size.
5253 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5254 const gl::Extents size(width, height, 1);
5255 const auto &pack = context->getGLState().getPackState();
5256
5257 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5258 if (endByteOrErr.isError())
5259 {
5260 context->handleError(endByteOrErr.getError());
5261 return false;
5262 }
5263
5264 size_t endByte = endByteOrErr.getResult();
5265 if (bufSize >= 0)
5266 {
5267 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5268 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005269 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005270 return false;
5271 }
5272 }
5273
5274 if (pixelPackBuffer != nullptr)
5275 {
5276 CheckedNumeric<size_t> checkedEndByte(endByte);
5277 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5278 checkedEndByte += checkedOffset;
5279
5280 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5281 {
5282 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005283 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005284 return false;
5285 }
5286 }
5287
5288 if (pixelPackBuffer == nullptr && length != nullptr)
5289 {
5290 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5291 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005292 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005293 return false;
5294 }
5295
5296 *length = static_cast<GLsizei>(endByte);
5297 }
5298
Geoff Langa953b522018-02-21 16:56:23 -05005299 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005300 angle::CheckedNumeric<int> clippedExtent(length);
5301 if (start < 0)
5302 {
5303 // "subtract" the area that is less than 0
5304 clippedExtent += start;
5305 }
5306
Geoff Langa953b522018-02-21 16:56:23 -05005307 angle::CheckedNumeric<int> readExtent = start;
5308 readExtent += length;
5309 if (!readExtent.IsValid())
5310 {
5311 return false;
5312 }
5313
5314 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005315 {
5316 // Subtract the region to the right of the read buffer
5317 clippedExtent -= (readExtent - bufferSize);
5318 }
5319
5320 if (!clippedExtent.IsValid())
5321 {
Geoff Langa953b522018-02-21 16:56:23 -05005322 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005323 }
5324
Geoff Langa953b522018-02-21 16:56:23 -05005325 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5326 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005327 };
5328
Geoff Langa953b522018-02-21 16:56:23 -05005329 GLsizei writtenColumns = 0;
5330 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5331 {
5332 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5333 return false;
5334 }
5335
5336 GLsizei writtenRows = 0;
5337 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5338 {
5339 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5340 return false;
5341 }
5342
Jamie Madillbe849e42017-05-02 15:49:00 -04005343 if (columns != nullptr)
5344 {
Geoff Langa953b522018-02-21 16:56:23 -05005345 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005346 }
5347
5348 if (rows != nullptr)
5349 {
Geoff Langa953b522018-02-21 16:56:23 -05005350 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005351 }
5352
5353 return true;
5354}
5355
5356template <typename ParamType>
5357bool ValidateTexParameterBase(Context *context,
5358 GLenum target,
5359 GLenum pname,
5360 GLsizei bufSize,
5361 const ParamType *params)
5362{
5363 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5364 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005365 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005366 return false;
5367 }
5368
5369 if (context->getTargetTexture(target) == nullptr)
5370 {
5371 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005372 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005373 return false;
5374 }
5375
5376 const GLsizei minBufSize = 1;
5377 if (bufSize >= 0 && bufSize < minBufSize)
5378 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005379 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005380 return false;
5381 }
5382
5383 switch (pname)
5384 {
5385 case GL_TEXTURE_WRAP_R:
5386 case GL_TEXTURE_SWIZZLE_R:
5387 case GL_TEXTURE_SWIZZLE_G:
5388 case GL_TEXTURE_SWIZZLE_B:
5389 case GL_TEXTURE_SWIZZLE_A:
5390 case GL_TEXTURE_BASE_LEVEL:
5391 case GL_TEXTURE_MAX_LEVEL:
5392 case GL_TEXTURE_COMPARE_MODE:
5393 case GL_TEXTURE_COMPARE_FUNC:
5394 case GL_TEXTURE_MIN_LOD:
5395 case GL_TEXTURE_MAX_LOD:
5396 if (context->getClientMajorVersion() < 3)
5397 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005398 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005399 return false;
5400 }
5401 if (target == GL_TEXTURE_EXTERNAL_OES &&
5402 !context->getExtensions().eglImageExternalEssl3)
5403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005404 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5405 "available without "
5406 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005407 return false;
5408 }
5409 break;
5410
5411 default:
5412 break;
5413 }
5414
JiangYizhou4cff8d62017-07-06 14:54:09 +08005415 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5416 {
5417 switch (pname)
5418 {
5419 case GL_TEXTURE_MIN_FILTER:
5420 case GL_TEXTURE_MAG_FILTER:
5421 case GL_TEXTURE_WRAP_S:
5422 case GL_TEXTURE_WRAP_T:
5423 case GL_TEXTURE_WRAP_R:
5424 case GL_TEXTURE_MIN_LOD:
5425 case GL_TEXTURE_MAX_LOD:
5426 case GL_TEXTURE_COMPARE_MODE:
5427 case GL_TEXTURE_COMPARE_FUNC:
5428 context->handleError(InvalidEnum()
5429 << "Invalid parameter for 2D multisampled textures.");
5430 return false;
5431 }
5432 }
5433
Jamie Madillbe849e42017-05-02 15:49:00 -04005434 switch (pname)
5435 {
5436 case GL_TEXTURE_WRAP_S:
5437 case GL_TEXTURE_WRAP_T:
5438 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005439 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005440 bool restrictedWrapModes =
5441 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5442 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5443 {
5444 return false;
5445 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005446 }
5447 break;
5448
5449 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005450 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005451 bool restrictedMinFilter =
5452 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5453 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5454 {
5455 return false;
5456 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005457 }
5458 break;
5459
5460 case GL_TEXTURE_MAG_FILTER:
5461 if (!ValidateTextureMagFilterValue(context, params))
5462 {
5463 return false;
5464 }
5465 break;
5466
5467 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005468 if (!context->getExtensions().textureUsage)
5469 {
5470 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5471 return false;
5472 }
5473
Jamie Madillbe849e42017-05-02 15:49:00 -04005474 switch (ConvertToGLenum(params[0]))
5475 {
5476 case GL_NONE:
5477 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5478 break;
5479
5480 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005481 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005482 return false;
5483 }
5484 break;
5485
5486 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Jamie Madillbe849e42017-05-02 15:49:00 -04005487 {
Luc Ferron1b1a8642018-01-23 15:12:01 -05005488 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5489 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5490 {
5491 return false;
5492 }
5493 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
Jamie Madillbe849e42017-05-02 15:49:00 -04005494 }
5495 break;
5496
5497 case GL_TEXTURE_MIN_LOD:
5498 case GL_TEXTURE_MAX_LOD:
5499 // any value is permissible
5500 break;
5501
5502 case GL_TEXTURE_COMPARE_MODE:
5503 if (!ValidateTextureCompareModeValue(context, params))
5504 {
5505 return false;
5506 }
5507 break;
5508
5509 case GL_TEXTURE_COMPARE_FUNC:
5510 if (!ValidateTextureCompareFuncValue(context, params))
5511 {
5512 return false;
5513 }
5514 break;
5515
5516 case GL_TEXTURE_SWIZZLE_R:
5517 case GL_TEXTURE_SWIZZLE_G:
5518 case GL_TEXTURE_SWIZZLE_B:
5519 case GL_TEXTURE_SWIZZLE_A:
5520 switch (ConvertToGLenum(params[0]))
5521 {
5522 case GL_RED:
5523 case GL_GREEN:
5524 case GL_BLUE:
5525 case GL_ALPHA:
5526 case GL_ZERO:
5527 case GL_ONE:
5528 break;
5529
5530 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005531 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005532 return false;
5533 }
5534 break;
5535
5536 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005537 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005538 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005539 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005540 return false;
5541 }
5542 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5543 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005544 context->handleError(InvalidOperation()
5545 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005546 return false;
5547 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005548 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5549 {
5550 context->handleError(InvalidOperation()
5551 << "Base level must be 0 for multisampled textures.");
5552 return false;
5553 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005554 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5555 {
5556 context->handleError(InvalidOperation()
5557 << "Base level must be 0 for rectangle textures.");
5558 return false;
5559 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005560 break;
5561
5562 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005563 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005564 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005565 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005566 return false;
5567 }
5568 break;
5569
5570 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5571 if (context->getClientVersion() < Version(3, 1))
5572 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005573 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005574 return false;
5575 }
5576 switch (ConvertToGLenum(params[0]))
5577 {
5578 case GL_DEPTH_COMPONENT:
5579 case GL_STENCIL_INDEX:
5580 break;
5581
5582 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005583 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005584 return false;
5585 }
5586 break;
5587
5588 case GL_TEXTURE_SRGB_DECODE_EXT:
5589 if (!ValidateTextureSRGBDecodeValue(context, params))
5590 {
5591 return false;
5592 }
5593 break;
5594
5595 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005596 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005597 return false;
5598 }
5599
5600 return true;
5601}
5602
5603template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5604template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5605
Jamie Madill12e957f2017-08-26 21:42:26 -04005606bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5607{
5608 if (index >= MAX_VERTEX_ATTRIBS)
5609 {
5610 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5611 return false;
5612 }
5613
5614 return true;
5615}
5616
5617bool ValidateGetActiveUniformBlockivBase(Context *context,
5618 GLuint program,
5619 GLuint uniformBlockIndex,
5620 GLenum pname,
5621 GLsizei *length)
5622{
5623 if (length)
5624 {
5625 *length = 0;
5626 }
5627
5628 if (context->getClientMajorVersion() < 3)
5629 {
5630 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5631 return false;
5632 }
5633
5634 Program *programObject = GetValidProgram(context, program);
5635 if (!programObject)
5636 {
5637 return false;
5638 }
5639
5640 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5641 {
5642 context->handleError(InvalidValue()
5643 << "uniformBlockIndex exceeds active uniform block count.");
5644 return false;
5645 }
5646
5647 switch (pname)
5648 {
5649 case GL_UNIFORM_BLOCK_BINDING:
5650 case GL_UNIFORM_BLOCK_DATA_SIZE:
5651 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5652 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5653 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5654 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5655 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5656 break;
5657
5658 default:
5659 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5660 return false;
5661 }
5662
5663 if (length)
5664 {
5665 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5666 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005667 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005668 programObject->getUniformBlockByIndex(uniformBlockIndex);
5669 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5670 }
5671 else
5672 {
5673 *length = 1;
5674 }
5675 }
5676
5677 return true;
5678}
5679
Jamie Madill9696d072017-08-26 23:19:57 -04005680template <typename ParamType>
5681bool ValidateSamplerParameterBase(Context *context,
5682 GLuint sampler,
5683 GLenum pname,
5684 GLsizei bufSize,
5685 ParamType *params)
5686{
5687 if (context->getClientMajorVersion() < 3)
5688 {
5689 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5690 return false;
5691 }
5692
5693 if (!context->isSampler(sampler))
5694 {
5695 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5696 return false;
5697 }
5698
5699 const GLsizei minBufSize = 1;
5700 if (bufSize >= 0 && bufSize < minBufSize)
5701 {
5702 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5703 return false;
5704 }
5705
5706 switch (pname)
5707 {
5708 case GL_TEXTURE_WRAP_S:
5709 case GL_TEXTURE_WRAP_T:
5710 case GL_TEXTURE_WRAP_R:
5711 if (!ValidateTextureWrapModeValue(context, params, false))
5712 {
5713 return false;
5714 }
5715 break;
5716
5717 case GL_TEXTURE_MIN_FILTER:
5718 if (!ValidateTextureMinFilterValue(context, params, false))
5719 {
5720 return false;
5721 }
5722 break;
5723
5724 case GL_TEXTURE_MAG_FILTER:
5725 if (!ValidateTextureMagFilterValue(context, params))
5726 {
5727 return false;
5728 }
5729 break;
5730
5731 case GL_TEXTURE_MIN_LOD:
5732 case GL_TEXTURE_MAX_LOD:
5733 // any value is permissible
5734 break;
5735
5736 case GL_TEXTURE_COMPARE_MODE:
5737 if (!ValidateTextureCompareModeValue(context, params))
5738 {
5739 return false;
5740 }
5741 break;
5742
5743 case GL_TEXTURE_COMPARE_FUNC:
5744 if (!ValidateTextureCompareFuncValue(context, params))
5745 {
5746 return false;
5747 }
5748 break;
5749
5750 case GL_TEXTURE_SRGB_DECODE_EXT:
5751 if (!ValidateTextureSRGBDecodeValue(context, params))
5752 {
5753 return false;
5754 }
5755 break;
5756
Luc Ferron1b1a8642018-01-23 15:12:01 -05005757 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5758 {
5759 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5760 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5761 {
5762 return false;
5763 }
5764 }
5765 break;
5766
Jamie Madill9696d072017-08-26 23:19:57 -04005767 default:
5768 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5769 return false;
5770 }
5771
5772 return true;
5773}
5774
5775template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5776template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5777
5778bool ValidateGetSamplerParameterBase(Context *context,
5779 GLuint sampler,
5780 GLenum pname,
5781 GLsizei *length)
5782{
5783 if (length)
5784 {
5785 *length = 0;
5786 }
5787
5788 if (context->getClientMajorVersion() < 3)
5789 {
5790 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5791 return false;
5792 }
5793
5794 if (!context->isSampler(sampler))
5795 {
5796 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5797 return false;
5798 }
5799
5800 switch (pname)
5801 {
5802 case GL_TEXTURE_WRAP_S:
5803 case GL_TEXTURE_WRAP_T:
5804 case GL_TEXTURE_WRAP_R:
5805 case GL_TEXTURE_MIN_FILTER:
5806 case GL_TEXTURE_MAG_FILTER:
5807 case GL_TEXTURE_MIN_LOD:
5808 case GL_TEXTURE_MAX_LOD:
5809 case GL_TEXTURE_COMPARE_MODE:
5810 case GL_TEXTURE_COMPARE_FUNC:
5811 break;
5812
Luc Ferron1b1a8642018-01-23 15:12:01 -05005813 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5814 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
5815 {
5816 return false;
5817 }
5818 break;
5819
Jamie Madill9696d072017-08-26 23:19:57 -04005820 case GL_TEXTURE_SRGB_DECODE_EXT:
5821 if (!context->getExtensions().textureSRGBDecode)
5822 {
5823 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5824 return false;
5825 }
5826 break;
5827
5828 default:
5829 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5830 return false;
5831 }
5832
5833 if (length)
5834 {
5835 *length = 1;
5836 }
5837 return true;
5838}
5839
5840bool ValidateGetInternalFormativBase(Context *context,
5841 GLenum target,
5842 GLenum internalformat,
5843 GLenum pname,
5844 GLsizei bufSize,
5845 GLsizei *numParams)
5846{
5847 if (numParams)
5848 {
5849 *numParams = 0;
5850 }
5851
5852 if (context->getClientMajorVersion() < 3)
5853 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005854 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005855 return false;
5856 }
5857
5858 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5859 if (!formatCaps.renderable)
5860 {
5861 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5862 return false;
5863 }
5864
5865 switch (target)
5866 {
5867 case GL_RENDERBUFFER:
5868 break;
5869
5870 case GL_TEXTURE_2D_MULTISAMPLE:
5871 if (context->getClientVersion() < ES_3_1)
5872 {
5873 context->handleError(InvalidOperation()
5874 << "Texture target requires at least OpenGL ES 3.1.");
5875 return false;
5876 }
5877 break;
5878
5879 default:
5880 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5881 return false;
5882 }
5883
5884 if (bufSize < 0)
5885 {
5886 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5887 return false;
5888 }
5889
5890 GLsizei maxWriteParams = 0;
5891 switch (pname)
5892 {
5893 case GL_NUM_SAMPLE_COUNTS:
5894 maxWriteParams = 1;
5895 break;
5896
5897 case GL_SAMPLES:
5898 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5899 break;
5900
5901 default:
5902 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5903 return false;
5904 }
5905
5906 if (numParams)
5907 {
5908 // glGetInternalFormativ will not overflow bufSize
5909 *numParams = std::min(bufSize, maxWriteParams);
5910 }
5911
5912 return true;
5913}
5914
Jamie Madillc29968b2016-01-20 11:17:23 -05005915} // namespace gl