blob: 1d948f88c7b7f6adc25265e05a18ed46c0d68ac8 [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
622 // No-op zero primitive count
623 return (primcount > 0);
624}
625
626bool ValidateDrawArraysInstancedBase(Context *context,
627 GLenum mode,
628 GLint first,
629 GLsizei count,
630 GLsizei primcount)
631{
632 if (primcount < 0)
633 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700634 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400635 return false;
636 }
637
638 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
639 {
640 return false;
641 }
642
643 // No-op if zero primitive count
644 return (primcount > 0);
645}
646
Corentin Wallez0dc97812017-06-22 14:38:44 -0400647bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400648{
649 // Verify there is at least one active attribute with a divisor of zero
650 const State &state = context->getGLState();
651
652 Program *program = state.getProgram();
653
654 const auto &attribs = state.getVertexArray()->getVertexAttributes();
655 const auto &bindings = state.getVertexArray()->getVertexBindings();
656 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
657 {
658 const VertexAttribute &attrib = attribs[attributeIndex];
659 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300660 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400661 {
662 return true;
663 }
664 }
665
Brandon Jonesafa75152017-07-21 13:11:29 -0700666 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400667 return false;
668}
669
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500670bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
671{
672 switch (target)
673 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800674 case GL_TEXTURE_3D:
675 case GL_TEXTURE_2D_ARRAY:
676 return true;
677 default:
678 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400679 }
680}
681
He Yunchao11b038b2016-11-22 21:24:04 +0800682bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
683{
684 switch (target)
685 {
686 case GL_TEXTURE_2D:
687 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
688 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
689 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
690 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
691 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
692 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
693 case GL_TEXTURE_3D:
694 case GL_TEXTURE_2D_ARRAY:
695 case GL_TEXTURE_2D_MULTISAMPLE:
696 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400697 case GL_TEXTURE_RECTANGLE_ANGLE:
698 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800699 default:
700 return false;
701 }
702}
703
Geoff Lange8afa902017-09-27 15:00:43 -0400704bool ValidFramebufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500705{
He Yunchaoced53ae2016-11-29 15:00:51 +0800706 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
707 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400708 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500709
710 switch (target)
711 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800712 case GL_FRAMEBUFFER:
713 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400714
He Yunchaoced53ae2016-11-29 15:00:51 +0800715 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800716 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400717 return (context->getExtensions().framebufferBlit ||
718 context->getClientMajorVersion() >= 3);
719
He Yunchaoced53ae2016-11-29 15:00:51 +0800720 default:
721 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500722 }
723}
724
Jamie Madillc29968b2016-01-20 11:17:23 -0500725bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400726{
Jamie Madillc29968b2016-01-20 11:17:23 -0500727 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400728 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -0400729 switch (target)
730 {
Jamie Madillc29968b2016-01-20 11:17:23 -0500731 case GL_TEXTURE_2D:
732 maxDimension = caps.max2DTextureSize;
733 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800734 case GL_TEXTURE_CUBE_MAP:
735 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
736 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
737 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
738 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
739 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
740 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
741 maxDimension = caps.maxCubeMapTextureSize;
742 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400743 case GL_TEXTURE_RECTANGLE_ANGLE:
744 return level == 0;
He Yunchaoced53ae2016-11-29 15:00:51 +0800745 case GL_TEXTURE_3D:
746 maxDimension = caps.max3DTextureSize;
747 break;
748 case GL_TEXTURE_2D_ARRAY:
749 maxDimension = caps.max2DTextureSize;
750 break;
He Yunchao11b038b2016-11-22 21:24:04 +0800751 case GL_TEXTURE_2D_MULTISAMPLE:
752 maxDimension = caps.max2DTextureSize;
753 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800754 default:
755 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400756 }
757
Brandon Jones6cad5662017-06-14 13:25:13 -0700758 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400759}
760
Brandon Jones6cad5662017-06-14 13:25:13 -0700761bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -0700762 GLenum target,
763 GLint level,
764 GLsizei width,
765 GLsizei height,
766 GLsizei depth,
767 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400768{
Brandon Jones6cad5662017-06-14 13:25:13 -0700769 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400770 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700771 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400772 return false;
773 }
Austin Kinross08528e12015-10-07 16:24:40 -0700774 // TexSubImage parameters can be NPOT without textureNPOT extension,
775 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500776 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500777 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500778 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400779 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400780 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700781 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400782 return false;
783 }
784
785 if (!ValidMipLevel(context, target, level))
786 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700787 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400788 return false;
789 }
790
791 return true;
792}
793
Geoff Lang966c9402017-04-18 12:38:27 -0400794bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
795{
796 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
797 (size % blockSize == 0);
798}
799
Jamie Madillc29968b2016-01-20 11:17:23 -0500800bool ValidCompressedImageSize(const ValidationContext *context,
801 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400802 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500803 GLsizei width,
804 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400805{
Geoff Langca271392017-04-05 12:30:00 -0400806 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400807 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400808 {
809 return false;
810 }
811
Geoff Lang966c9402017-04-18 12:38:27 -0400812 if (width < 0 || height < 0)
813 {
814 return false;
815 }
816
817 if (CompressedTextureFormatRequiresExactSize(internalFormat))
818 {
819 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
820 // block size for level 0 but WebGL disallows this.
821 bool smallerThanBlockSizeAllowed =
822 level > 0 || !context->getExtensions().webglCompatibility;
823
824 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
825 smallerThanBlockSizeAllowed) ||
826 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
827 smallerThanBlockSizeAllowed))
828 {
829 return false;
830 }
831 }
832
833 return true;
834}
835
836bool ValidCompressedSubImageSize(const ValidationContext *context,
837 GLenum internalFormat,
838 GLint xoffset,
839 GLint yoffset,
840 GLsizei width,
841 GLsizei height,
842 size_t textureWidth,
843 size_t textureHeight)
844{
845 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
846 if (!formatInfo.compressed)
847 {
848 return false;
849 }
850
Geoff Lang44ff5a72017-02-03 15:15:43 -0500851 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400852 {
853 return false;
854 }
855
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500856 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400857 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500858 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400859 yoffset % formatInfo.compressedBlockHeight != 0)
860 {
861 return false;
862 }
863
864 // Allowed to either have data that is a multiple of block size or is smaller than the block
865 // size but fills the entire mip
866 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
867 static_cast<size_t>(width) == textureWidth &&
868 static_cast<size_t>(height) == textureHeight;
869 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
870 (height % formatInfo.compressedBlockHeight) == 0;
871 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400872 {
873 return false;
874 }
875 }
876
Geoff Langd4f180b2013-09-24 13:57:44 -0400877 return true;
878}
879
Geoff Langff5b2d52016-09-07 11:32:23 -0400880bool ValidImageDataSize(ValidationContext *context,
881 GLenum textureTarget,
882 GLsizei width,
883 GLsizei height,
884 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400885 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400886 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400887 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400888 GLsizei imageSize)
889{
Corentin Wallez336129f2017-10-17 15:55:40 -0400890 gl::Buffer *pixelUnpackBuffer =
891 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400892 if (pixelUnpackBuffer == nullptr && imageSize < 0)
893 {
894 // Checks are not required
895 return true;
896 }
897
898 // ...the data would be unpacked from the buffer object such that the memory reads required
899 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400900 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
901 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400902 const gl::Extents size(width, height, depth);
903 const auto &unpack = context->getGLState().getUnpackState();
904
905 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
906 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
907 if (endByteOrErr.isError())
908 {
909 context->handleError(endByteOrErr.getError());
910 return false;
911 }
912
913 GLuint endByte = endByteOrErr.getResult();
914
915 if (pixelUnpackBuffer)
916 {
917 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
918 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
919 checkedEndByte += checkedOffset;
920
921 if (!checkedEndByte.IsValid() ||
922 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
923 {
924 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500925 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -0400926 return false;
927 }
928 }
929 else
930 {
931 ASSERT(imageSize >= 0);
932 if (pixels == nullptr && imageSize != 0)
933 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500934 context->handleError(InvalidOperation()
935 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400936 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400937 }
938
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400939 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400940 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500941 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400942 return false;
943 }
944 }
945
946 return true;
947}
948
Geoff Lang37dde692014-01-31 16:34:54 -0500949bool ValidQueryType(const Context *context, GLenum queryType)
950{
He Yunchaoced53ae2016-11-29 15:00:51 +0800951 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
952 "GL extension enums not equal.");
953 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
954 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -0500955
956 switch (queryType)
957 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800958 case GL_ANY_SAMPLES_PASSED:
959 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400960 return context->getClientMajorVersion() >= 3 ||
961 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +0800962 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
963 return (context->getClientMajorVersion() >= 3);
964 case GL_TIME_ELAPSED_EXT:
965 return context->getExtensions().disjointTimerQuery;
966 case GL_COMMANDS_COMPLETED_CHROMIUM:
967 return context->getExtensions().syncQuery;
968 default:
969 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500970 }
971}
972
Geoff Lang2d62ab72017-03-23 16:54:40 -0400973bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
974 GLenum type,
975 GLboolean normalized,
976 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400977 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400978 bool pureInteger)
979{
980 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400981 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
982 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
983 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
984 // parameter exceeds 255.
985 constexpr GLsizei kMaxWebGLStride = 255;
986 if (stride > kMaxWebGLStride)
987 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500988 context->handleError(InvalidValue()
989 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -0400990 return false;
991 }
992
993 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
994 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
995 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
996 // or an INVALID_OPERATION error is generated.
997 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
998 size_t typeSize = GetVertexFormatTypeSize(internalType);
999
1000 ASSERT(isPow2(typeSize) && typeSize > 0);
1001 size_t sizeMask = (typeSize - 1);
1002 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1003 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001004 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001005 return false;
1006 }
1007
1008 if ((stride & sizeMask) != 0)
1009 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001010 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001011 return false;
1012 }
1013
1014 return true;
1015}
1016
Jamie Madillef300b12016-10-07 15:12:09 -04001017Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001018{
He Yunchaoced53ae2016-11-29 15:00:51 +08001019 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1020 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1021 // or program object and INVALID_OPERATION if the provided name identifies an object
1022 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001023
Dian Xiang769769a2015-09-09 15:20:08 -07001024 Program *validProgram = context->getProgram(id);
1025
1026 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001027 {
Dian Xiang769769a2015-09-09 15:20:08 -07001028 if (context->getShader(id))
1029 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001030 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001031 }
1032 else
1033 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001034 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001035 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001036 }
Dian Xiang769769a2015-09-09 15:20:08 -07001037
1038 return validProgram;
1039}
1040
Jamie Madillef300b12016-10-07 15:12:09 -04001041Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001042{
1043 // See ValidProgram for spec details.
1044
1045 Shader *validShader = context->getShader(id);
1046
1047 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001048 {
Dian Xiang769769a2015-09-09 15:20:08 -07001049 if (context->getProgram(id))
1050 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001051 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001052 }
1053 else
1054 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001055 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001056 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001057 }
Dian Xiang769769a2015-09-09 15:20:08 -07001058
1059 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001060}
1061
Geoff Langb1196682014-07-23 13:47:29 -04001062bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001063{
Geoff Langfa125c92017-10-24 13:01:46 -04001064 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001065 {
Geoff Langfa125c92017-10-24 13:01:46 -04001066 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1067 {
1068 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1069 return false;
1070 }
Jamie Madillb4472272014-07-03 10:38:55 -04001071
Geoff Langfa125c92017-10-24 13:01:46 -04001072 // Color attachment 0 is validated below because it is always valid
1073 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001074 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001075 {
Geoff Langfa125c92017-10-24 13:01:46 -04001076 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001077 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001078 }
1079 }
1080 else
1081 {
1082 switch (attachment)
1083 {
Geoff Langfa125c92017-10-24 13:01:46 -04001084 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001085 case GL_DEPTH_ATTACHMENT:
1086 case GL_STENCIL_ATTACHMENT:
1087 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001088
He Yunchaoced53ae2016-11-29 15:00:51 +08001089 case GL_DEPTH_STENCIL_ATTACHMENT:
1090 if (!context->getExtensions().webglCompatibility &&
1091 context->getClientMajorVersion() < 3)
1092 {
Geoff Langfa125c92017-10-24 13:01:46 -04001093 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001094 return false;
1095 }
1096 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001097
He Yunchaoced53ae2016-11-29 15:00:51 +08001098 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001099 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001100 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001101 }
1102 }
1103
1104 return true;
1105}
1106
Jamie Madille8fb6402017-02-14 17:56:40 -05001107bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001108 GLenum target,
1109 GLsizei samples,
1110 GLenum internalformat,
1111 GLsizei width,
1112 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001113{
1114 switch (target)
1115 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001116 case GL_RENDERBUFFER:
1117 break;
1118 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001119 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001120 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001121 }
1122
1123 if (width < 0 || height < 0 || samples < 0)
1124 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001125 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001126 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001127 }
1128
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001129 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1130 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1131
1132 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001133 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001134 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001135 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001136 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001137 }
1138
1139 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1140 // 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 -08001141 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001142 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1143 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001144 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001145 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001146 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001147 }
1148
Geoff Langaae65a42014-05-26 12:43:44 -04001149 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001150 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001151 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001152 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001153 }
1154
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001155 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001156 if (handle == 0)
1157 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001158 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001159 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001160 }
1161
1162 return true;
1163}
1164
He Yunchaoced53ae2016-11-29 15:00:51 +08001165bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1166 GLenum target,
1167 GLenum attachment,
1168 GLenum renderbuffertarget,
1169 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001170{
Geoff Lange8afa902017-09-27 15:00:43 -04001171 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001172 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001173 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001174 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001175 }
1176
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001177 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001178
Jamie Madill84115c92015-04-23 15:00:07 -04001179 ASSERT(framebuffer);
1180 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001181 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001182 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001183 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001184 }
1185
Jamie Madillb4472272014-07-03 10:38:55 -04001186 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001187 {
Jamie Madillb4472272014-07-03 10:38:55 -04001188 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001189 }
1190
Jamie Madillab9d82c2014-01-21 16:38:14 -05001191 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1192 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1193 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1194 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1195 if (renderbuffer != 0)
1196 {
1197 if (!context->getRenderbuffer(renderbuffer))
1198 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001199 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001200 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001201 }
1202 }
1203
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001204 return true;
1205}
1206
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001207bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001208 GLint srcX0,
1209 GLint srcY0,
1210 GLint srcX1,
1211 GLint srcY1,
1212 GLint dstX0,
1213 GLint dstY0,
1214 GLint dstX1,
1215 GLint dstY1,
1216 GLbitfield mask,
1217 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001218{
1219 switch (filter)
1220 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001221 case GL_NEAREST:
1222 break;
1223 case GL_LINEAR:
1224 break;
1225 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001226 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001227 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001228 }
1229
1230 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1231 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001232 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001233 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001234 }
1235
1236 if (mask == 0)
1237 {
1238 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1239 // buffers are copied.
1240 return false;
1241 }
1242
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001243 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1244 // color buffer, leaving only nearest being unfiltered from above
1245 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1246 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001247 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001248 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001249 }
1250
Jamie Madill51f40ec2016-06-15 14:06:00 -04001251 const auto &glState = context->getGLState();
1252 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1253 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001254
1255 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001256 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001257 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001258 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001259 }
1260
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001261 if (readFramebuffer->id() == drawFramebuffer->id())
1262 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001263 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001264 return false;
1265 }
1266
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001267 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001268 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001269 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001270 return false;
1271 }
1272
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001273 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001274 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001275 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001276 return false;
1277 }
1278
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001279 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001280 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001281 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001282 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001283 }
1284
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001285 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1286
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001287 if (mask & GL_COLOR_BUFFER_BIT)
1288 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001289 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001290 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001291
He Yunchao66a41a22016-12-15 16:45:05 +08001292 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001293 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001294 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001295
Geoff Langa15472a2015-08-11 11:48:03 -04001296 for (size_t drawbufferIdx = 0;
1297 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001298 {
Geoff Langa15472a2015-08-11 11:48:03 -04001299 const FramebufferAttachment *attachment =
1300 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1301 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001302 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001303 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001304
Geoff Langb2f3d052013-08-13 12:49:27 -04001305 // The GL ES 3.0.2 spec (pg 193) states that:
1306 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001307 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1308 // as well
1309 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1310 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001311 // Changes with EXT_color_buffer_float:
1312 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001313 GLenum readComponentType = readFormat.info->componentType;
1314 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001315 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001316 readComponentType == GL_SIGNED_NORMALIZED);
1317 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1318 drawComponentType == GL_SIGNED_NORMALIZED);
1319
1320 if (extensions.colorBufferFloat)
1321 {
1322 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1323 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1324
1325 if (readFixedOrFloat != drawFixedOrFloat)
1326 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001327 context->handleError(InvalidOperation()
1328 << "If the read buffer contains fixed-point or "
1329 "floating-point values, the draw buffer must "
1330 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001331 return false;
1332 }
1333 }
1334 else if (readFixedPoint != drawFixedPoint)
1335 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001336 context->handleError(InvalidOperation()
1337 << "If the read buffer contains fixed-point values, "
1338 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001339 return false;
1340 }
1341
1342 if (readComponentType == GL_UNSIGNED_INT &&
1343 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001344 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001345 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001346 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001347 }
1348
Jamie Madill6163c752015-12-07 16:32:59 -05001349 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001350 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001351 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001352 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001353 }
1354
Jamie Madilla3944d42016-07-22 22:13:26 -04001355 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001356 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001357 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001358 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001359 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001360 }
Geoff Lange4915782017-04-12 15:19:07 -04001361
1362 if (context->getExtensions().webglCompatibility &&
1363 *readColorBuffer == *attachment)
1364 {
1365 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001366 InvalidOperation()
1367 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001368 return false;
1369 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001370 }
1371 }
1372
Jamie Madilla3944d42016-07-22 22:13:26 -04001373 if ((readFormat.info->componentType == GL_INT ||
1374 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1375 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001376 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001377 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001378 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001379 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001380 }
He Yunchao66a41a22016-12-15 16:45:05 +08001381 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1382 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1383 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1384 // situation is an application error that would lead to a crash in ANGLE.
1385 else if (drawFramebuffer->hasEnabledDrawBuffer())
1386 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001387 context->handleError(
1388 InvalidOperation()
1389 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001390 return false;
1391 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001392 }
1393
He Yunchaoced53ae2016-11-29 15:00:51 +08001394 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001395 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1396 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001397 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001398 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001399 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001400 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001401 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001402 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001403 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001404
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001405 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001406 {
Kenneth Russell69382852017-07-21 16:38:44 -04001407 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001408 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001409 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001410 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001411 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001412
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001413 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001414 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001415 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001416 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001417 }
Geoff Lange4915782017-04-12 15:19:07 -04001418
1419 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1420 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001421 context->handleError(
1422 InvalidOperation()
1423 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001424 return false;
1425 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001426 }
He Yunchao66a41a22016-12-15 16:45:05 +08001427 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1428 else if (drawBuffer)
1429 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001430 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1431 "depth/stencil attachment of a "
1432 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001433 return false;
1434 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001435 }
1436 }
1437
Martin Radeva3ed4572017-07-27 18:29:37 +03001438 // ANGLE_multiview, Revision 1:
1439 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1440 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1441 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1442 {
1443 context->handleError(InvalidFramebufferOperation()
1444 << "Attempt to read from a multi-view framebuffer.");
1445 return false;
1446 }
1447 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1448 {
1449 context->handleError(InvalidFramebufferOperation()
1450 << "Attempt to write to a multi-view framebuffer.");
1451 return false;
1452 }
1453
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001454 return true;
1455}
1456
Jamie Madill4928b7c2017-06-20 12:57:39 -04001457bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001458 GLint x,
1459 GLint y,
1460 GLsizei width,
1461 GLsizei height,
1462 GLenum format,
1463 GLenum type,
1464 GLsizei bufSize,
1465 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001466 GLsizei *columns,
1467 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001468 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001469{
1470 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001471 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001472 return false;
1473 }
1474
Geoff Lang62fce5b2016-09-30 10:46:35 -04001475 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001476 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001477 {
Geoff Langb1196682014-07-23 13:47:29 -04001478 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001479 }
1480
Geoff Lang62fce5b2016-09-30 10:46:35 -04001481 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001482 {
Geoff Langb1196682014-07-23 13:47:29 -04001483 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001484 }
1485
Jamie Madillc29968b2016-01-20 11:17:23 -05001486 return true;
1487}
1488
1489bool ValidateReadnPixelsEXT(Context *context,
1490 GLint x,
1491 GLint y,
1492 GLsizei width,
1493 GLsizei height,
1494 GLenum format,
1495 GLenum type,
1496 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001497 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001498{
1499 if (bufSize < 0)
1500 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001501 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001502 return false;
1503 }
1504
Geoff Lang62fce5b2016-09-30 10:46:35 -04001505 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001506 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001507}
Jamie Madill26e91952014-03-05 15:01:27 -05001508
Jamie Madill4928b7c2017-06-20 12:57:39 -04001509bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001510 GLint x,
1511 GLint y,
1512 GLsizei width,
1513 GLsizei height,
1514 GLenum format,
1515 GLenum type,
1516 GLsizei bufSize,
1517 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001518 GLsizei *columns,
1519 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001520 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001521{
1522 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001523 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001524 return false;
1525 }
1526
Geoff Lange93daba2017-03-30 13:54:40 -04001527 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1528 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001529 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001530 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001531 }
1532
Geoff Lang62fce5b2016-09-30 10:46:35 -04001533 if (!ValidateRobustBufferSize(context, bufSize, *length))
1534 {
1535 return false;
1536 }
1537
1538 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001539}
1540
Jamie Madillf0e04492017-08-26 15:28:42 -04001541bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001542{
1543 if (!context->getExtensions().occlusionQueryBoolean &&
1544 !context->getExtensions().disjointTimerQuery)
1545 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001546 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001547 return false;
1548 }
1549
Olli Etuaho41997e72016-03-10 13:38:39 +02001550 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001551}
1552
Jamie Madillf0e04492017-08-26 15:28:42 -04001553bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001554{
1555 if (!context->getExtensions().occlusionQueryBoolean &&
1556 !context->getExtensions().disjointTimerQuery)
1557 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001558 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001559 return false;
1560 }
1561
Olli Etuaho41997e72016-03-10 13:38:39 +02001562 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001563}
1564
Jamie Madillf0e04492017-08-26 15:28:42 -04001565bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1566{
1567 if (!context->getExtensions().occlusionQueryBoolean &&
1568 !context->getExtensions().disjointTimerQuery)
1569 {
1570 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1571 return false;
1572 }
1573
1574 return true;
1575}
1576
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001577bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001578{
1579 if (!ValidQueryType(context, target))
1580 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001581 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001582 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001583 }
1584
1585 if (id == 0)
1586 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001587 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001588 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001589 }
1590
1591 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1592 // of zero, if the active query object name for <target> is non-zero (for the
1593 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1594 // the active query for either target is non-zero), if <id> is the name of an
1595 // existing query object whose type does not match <target>, or if <id> is the
1596 // active query object name for any query type, the error INVALID_OPERATION is
1597 // generated.
1598
1599 // Ensure no other queries are active
1600 // NOTE: If other queries than occlusion are supported, we will need to check
1601 // separately that:
1602 // a) The query ID passed is not the current active query for any target/type
1603 // b) There are no active queries for the requested target (and in the case
1604 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1605 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001606
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001607 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001608 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001609 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001610 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001611 }
1612
1613 Query *queryObject = context->getQuery(id, true, target);
1614
1615 // check that name was obtained with glGenQueries
1616 if (!queryObject)
1617 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001618 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001619 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001620 }
1621
1622 // check for type mismatch
1623 if (queryObject->getType() != target)
1624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001625 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001626 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001627 }
1628
1629 return true;
1630}
1631
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001632bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1633{
1634 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001635 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001636 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001637 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001638 return false;
1639 }
1640
1641 return ValidateBeginQueryBase(context, target, id);
1642}
1643
1644bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001645{
1646 if (!ValidQueryType(context, target))
1647 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001648 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001649 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001650 }
1651
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001652 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001653
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001654 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001655 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001656 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001657 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001658 }
1659
Jamie Madill45c785d2014-05-13 14:09:34 -04001660 return true;
1661}
1662
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001663bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1664{
1665 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001666 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001667 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001668 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001669 return false;
1670 }
1671
1672 return ValidateEndQueryBase(context, target);
1673}
1674
1675bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1676{
1677 if (!context->getExtensions().disjointTimerQuery)
1678 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001679 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001680 return false;
1681 }
1682
1683 if (target != GL_TIMESTAMP_EXT)
1684 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001685 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001686 return false;
1687 }
1688
1689 Query *queryObject = context->getQuery(id, true, target);
1690 if (queryObject == nullptr)
1691 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001692 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001693 return false;
1694 }
1695
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001696 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001697 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001698 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001699 return false;
1700 }
1701
1702 return true;
1703}
1704
Geoff Lang2186c382016-10-14 10:54:54 -04001705bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001706{
Geoff Lang2186c382016-10-14 10:54:54 -04001707 if (numParams)
1708 {
1709 *numParams = 0;
1710 }
1711
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001712 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1713 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001714 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001715 return false;
1716 }
1717
1718 switch (pname)
1719 {
1720 case GL_CURRENT_QUERY_EXT:
1721 if (target == GL_TIMESTAMP_EXT)
1722 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001723 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001724 return false;
1725 }
1726 break;
1727 case GL_QUERY_COUNTER_BITS_EXT:
1728 if (!context->getExtensions().disjointTimerQuery ||
1729 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1730 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001731 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001732 return false;
1733 }
1734 break;
1735 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001736 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001737 return false;
1738 }
1739
Geoff Lang2186c382016-10-14 10:54:54 -04001740 if (numParams)
1741 {
1742 // All queries return only one value
1743 *numParams = 1;
1744 }
1745
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001746 return true;
1747}
1748
1749bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1750{
1751 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001752 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001753 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001754 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001755 return false;
1756 }
1757
Geoff Lang2186c382016-10-14 10:54:54 -04001758 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001759}
1760
Geoff Lang2186c382016-10-14 10:54:54 -04001761bool ValidateGetQueryivRobustANGLE(Context *context,
1762 GLenum target,
1763 GLenum pname,
1764 GLsizei bufSize,
1765 GLsizei *length,
1766 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001767{
Geoff Lang2186c382016-10-14 10:54:54 -04001768 if (!ValidateRobustEntryPoint(context, bufSize))
1769 {
1770 return false;
1771 }
1772
1773 if (!ValidateGetQueryivBase(context, target, pname, length))
1774 {
1775 return false;
1776 }
1777
1778 if (!ValidateRobustBufferSize(context, bufSize, *length))
1779 {
1780 return false;
1781 }
1782
1783 return true;
1784}
1785
1786bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1787{
1788 if (numParams)
1789 {
1790 *numParams = 0;
1791 }
1792
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001793 Query *queryObject = context->getQuery(id, false, GL_NONE);
1794
1795 if (!queryObject)
1796 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001797 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001798 return false;
1799 }
1800
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001801 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001802 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001803 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001804 return false;
1805 }
1806
1807 switch (pname)
1808 {
1809 case GL_QUERY_RESULT_EXT:
1810 case GL_QUERY_RESULT_AVAILABLE_EXT:
1811 break;
1812
1813 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001814 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001815 return false;
1816 }
1817
Geoff Lang2186c382016-10-14 10:54:54 -04001818 if (numParams)
1819 {
1820 *numParams = 1;
1821 }
1822
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001823 return true;
1824}
1825
1826bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1827{
1828 if (!context->getExtensions().disjointTimerQuery)
1829 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001830 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001831 return false;
1832 }
Geoff Lang2186c382016-10-14 10:54:54 -04001833 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1834}
1835
1836bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1837 GLuint id,
1838 GLenum pname,
1839 GLsizei bufSize,
1840 GLsizei *length,
1841 GLint *params)
1842{
1843 if (!context->getExtensions().disjointTimerQuery)
1844 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001845 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001846 return false;
1847 }
1848
1849 if (!ValidateRobustEntryPoint(context, bufSize))
1850 {
1851 return false;
1852 }
1853
1854 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1855 {
1856 return false;
1857 }
1858
1859 if (!ValidateRobustBufferSize(context, bufSize, *length))
1860 {
1861 return false;
1862 }
1863
1864 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001865}
1866
1867bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1868{
1869 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001870 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001871 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001872 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001873 return false;
1874 }
Geoff Lang2186c382016-10-14 10:54:54 -04001875 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1876}
1877
1878bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1879 GLuint id,
1880 GLenum pname,
1881 GLsizei bufSize,
1882 GLsizei *length,
1883 GLuint *params)
1884{
1885 if (!context->getExtensions().disjointTimerQuery &&
1886 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1887 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001888 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001889 return false;
1890 }
1891
1892 if (!ValidateRobustEntryPoint(context, bufSize))
1893 {
1894 return false;
1895 }
1896
1897 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1898 {
1899 return false;
1900 }
1901
1902 if (!ValidateRobustBufferSize(context, bufSize, *length))
1903 {
1904 return false;
1905 }
1906
1907 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001908}
1909
1910bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1911{
1912 if (!context->getExtensions().disjointTimerQuery)
1913 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001914 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001915 return false;
1916 }
Geoff Lang2186c382016-10-14 10:54:54 -04001917 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1918}
1919
1920bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1921 GLuint id,
1922 GLenum pname,
1923 GLsizei bufSize,
1924 GLsizei *length,
1925 GLint64 *params)
1926{
1927 if (!context->getExtensions().disjointTimerQuery)
1928 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001929 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001930 return false;
1931 }
1932
1933 if (!ValidateRobustEntryPoint(context, bufSize))
1934 {
1935 return false;
1936 }
1937
1938 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1939 {
1940 return false;
1941 }
1942
1943 if (!ValidateRobustBufferSize(context, bufSize, *length))
1944 {
1945 return false;
1946 }
1947
1948 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001949}
1950
1951bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1952{
1953 if (!context->getExtensions().disjointTimerQuery)
1954 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001955 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001956 return false;
1957 }
Geoff Lang2186c382016-10-14 10:54:54 -04001958 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1959}
1960
1961bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1962 GLuint id,
1963 GLenum pname,
1964 GLsizei bufSize,
1965 GLsizei *length,
1966 GLuint64 *params)
1967{
1968 if (!context->getExtensions().disjointTimerQuery)
1969 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001970 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001971 return false;
1972 }
1973
1974 if (!ValidateRobustEntryPoint(context, bufSize))
1975 {
1976 return false;
1977 }
1978
1979 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1980 {
1981 return false;
1982 }
1983
1984 if (!ValidateRobustBufferSize(context, bufSize, *length))
1985 {
1986 return false;
1987 }
1988
1989 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001990}
1991
Jiajia Qin5451d532017-11-16 17:16:34 +08001992bool ValidateUniformCommonBase(ValidationContext *context,
1993 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05001994 GLint location,
1995 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08001996 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05001997{
Jiajia Qin5451d532017-11-16 17:16:34 +08001998 // TODO(Jiajia): Add image uniform check in future.
1999 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002000 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002001 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002002 return false;
2003 }
2004
Jiajia Qin5451d532017-11-16 17:16:34 +08002005 if (!program)
2006 {
2007 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2008 return false;
2009 }
2010
2011 if (!program->isLinked())
2012 {
2013 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2014 return false;
2015 }
2016
2017 if (location == -1)
2018 {
2019 // Silently ignore the uniform command
2020 return false;
2021 }
2022
2023 const auto &uniformLocations = program->getUniformLocations();
2024 size_t castedLocation = static_cast<size_t>(location);
2025 if (castedLocation >= uniformLocations.size())
2026 {
2027 context->handleError(InvalidOperation() << "Invalid uniform location");
2028 return false;
2029 }
2030
2031 const auto &uniformLocation = uniformLocations[castedLocation];
2032 if (uniformLocation.ignored)
2033 {
2034 // Silently ignore the uniform command
2035 return false;
2036 }
2037
2038 if (!uniformLocation.used())
2039 {
2040 context->handleError(InvalidOperation());
2041 return false;
2042 }
2043
2044 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2045
2046 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2047 if (!uniform.isArray() && count > 1)
2048 {
2049 context->handleError(InvalidOperation());
2050 return false;
2051 }
2052
2053 *uniformOut = &uniform;
2054 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002055}
2056
Jiajia Qin5451d532017-11-16 17:16:34 +08002057bool ValidateUniform1ivValue(ValidationContext *context,
2058 GLenum uniformType,
2059 GLsizei count,
2060 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002061{
Jiajia Qin5451d532017-11-16 17:16:34 +08002062 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2063 // It is compatible with INT or BOOL.
2064 // Do these cheap tests first, for a little extra speed.
2065 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002066 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002067 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002068 }
2069
Jiajia Qin5451d532017-11-16 17:16:34 +08002070 if (IsSamplerType(uniformType))
2071 {
2072 // Check that the values are in range.
2073 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2074 for (GLsizei i = 0; i < count; ++i)
2075 {
2076 if (value[i] < 0 || value[i] >= max)
2077 {
2078 context->handleError(InvalidValue() << "sampler uniform value out of range");
2079 return false;
2080 }
2081 }
2082 return true;
2083 }
2084
2085 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2086 return false;
2087}
2088
2089bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2090{
2091 // Check that the value type is compatible with uniform type.
2092 // Do the cheaper test first, for a little extra speed.
2093 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2094 {
2095 return true;
2096 }
2097
2098 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2099 return false;
2100}
2101
2102bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2103{
2104 // Check that the value type is compatible with uniform type.
2105 if (valueType == uniformType)
2106 {
2107 return true;
2108 }
2109
2110 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2111 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002112}
2113
Jamie Madillc1d770e2017-04-13 17:31:24 -04002114bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002115{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002116 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002117 gl::Program *programObject = context->getGLState().getProgram();
2118 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2119 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002120}
2121
Jamie Madillbe849e42017-05-02 15:49:00 -04002122bool ValidateUniform1iv(ValidationContext *context,
2123 GLint location,
2124 GLsizei count,
2125 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002126{
2127 const LinkedUniform *uniform = nullptr;
2128 gl::Program *programObject = context->getGLState().getProgram();
2129 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2130 ValidateUniform1ivValue(context, uniform->type, count, value);
2131}
2132
Jamie Madillc1d770e2017-04-13 17:31:24 -04002133bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002134 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002135 GLint location,
2136 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002137 GLboolean transpose)
2138{
Geoff Lang92019432017-11-20 13:09:34 -05002139 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002140 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002141 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002142 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002143 }
2144
Jamie Madill62d31cb2015-09-11 13:25:51 -04002145 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002146 gl::Program *programObject = context->getGLState().getProgram();
2147 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2148 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002149}
2150
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002151bool ValidateStateQuery(ValidationContext *context,
2152 GLenum pname,
2153 GLenum *nativeType,
2154 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002155{
2156 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2157 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002158 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002159 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002160 }
2161
Jamie Madill0af26e12015-03-05 19:54:33 -05002162 const Caps &caps = context->getCaps();
2163
Jamie Madill893ab082014-05-16 16:56:10 -04002164 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2165 {
2166 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2167
Jamie Madill0af26e12015-03-05 19:54:33 -05002168 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002169 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002170 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002171 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002172 }
2173 }
2174
2175 switch (pname)
2176 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002177 case GL_TEXTURE_BINDING_2D:
2178 case GL_TEXTURE_BINDING_CUBE_MAP:
2179 case GL_TEXTURE_BINDING_3D:
2180 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002181 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002182 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002183 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2184 if (!context->getExtensions().textureRectangle)
2185 {
2186 context->handleError(InvalidEnum()
2187 << "ANGLE_texture_rectangle extension not present");
2188 return false;
2189 }
2190 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002191 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2192 if (!context->getExtensions().eglStreamConsumerExternal &&
2193 !context->getExtensions().eglImageExternal)
2194 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002195 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2196 "nor GL_OES_EGL_image_external "
2197 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002198 return false;
2199 }
2200 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002201
He Yunchaoced53ae2016-11-29 15:00:51 +08002202 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2203 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002204 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002205 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2206 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002207 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002208 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002209 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002210 }
2211
Jamie Madill51f40ec2016-06-15 14:06:00 -04002212 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2213 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002214
2215 if (framebuffer->getReadBufferState() == GL_NONE)
2216 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002217 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002218 return false;
2219 }
2220
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002221 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002222 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002223 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002224 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002225 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002226 }
2227 }
2228 break;
2229
He Yunchaoced53ae2016-11-29 15:00:51 +08002230 default:
2231 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002232 }
2233
2234 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002235 if (*numParams == 0)
2236 {
2237 return false;
2238 }
2239
2240 return true;
2241}
2242
2243bool ValidateRobustStateQuery(ValidationContext *context,
2244 GLenum pname,
2245 GLsizei bufSize,
2246 GLenum *nativeType,
2247 unsigned int *numParams)
2248{
2249 if (!ValidateRobustEntryPoint(context, bufSize))
2250 {
2251 return false;
2252 }
2253
2254 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2255 {
2256 return false;
2257 }
2258
2259 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002260 {
2261 return false;
2262 }
2263
2264 return true;
2265}
2266
Jamie Madillc29968b2016-01-20 11:17:23 -05002267bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2268 GLenum target,
2269 GLint level,
2270 GLenum internalformat,
2271 bool isSubImage,
2272 GLint xoffset,
2273 GLint yoffset,
2274 GLint zoffset,
2275 GLint x,
2276 GLint y,
2277 GLsizei width,
2278 GLsizei height,
2279 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002280 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002281{
Brandon Jones6cad5662017-06-14 13:25:13 -07002282 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002283 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002284 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2285 return false;
2286 }
2287
2288 if (width < 0 || height < 0)
2289 {
2290 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002291 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002292 }
2293
He Yunchaoced53ae2016-11-29 15:00:51 +08002294 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2295 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002296 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002297 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002298 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002299 }
2300
2301 if (border != 0)
2302 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002303 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002304 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002305 }
2306
2307 if (!ValidMipLevel(context, target, level))
2308 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002309 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002310 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002311 }
2312
Jamie Madill51f40ec2016-06-15 14:06:00 -04002313 const auto &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002314 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002315 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002316 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002317 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002318 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002319 }
2320
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002321 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002322 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002323 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002324 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002325 }
2326
Martin Radev138064f2016-07-15 12:03:41 +03002327 if (readFramebuffer->getReadBufferState() == GL_NONE)
2328 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002329 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002330 return false;
2331 }
2332
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002333 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2334 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002335 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002336 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002337 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2338 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002339 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002340 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002341 return false;
2342 }
2343
Martin Radev04e2c3b2017-07-27 16:54:35 +03002344 // ANGLE_multiview spec, Revision 1:
2345 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2346 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2347 // is not NONE.
2348 if (source->getMultiviewLayout() != GL_NONE)
2349 {
2350 context->handleError(InvalidFramebufferOperation()
2351 << "The active read framebuffer object has multiview attachments.");
2352 return false;
2353 }
2354
Geoff Langaae65a42014-05-26 12:43:44 -04002355 const gl::Caps &caps = context->getCaps();
2356
Geoff Langaae65a42014-05-26 12:43:44 -04002357 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002358 switch (target)
2359 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002360 case GL_TEXTURE_2D:
2361 maxDimension = caps.max2DTextureSize;
2362 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002363
He Yunchaoced53ae2016-11-29 15:00:51 +08002364 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2365 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2366 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2367 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2368 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2369 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2370 maxDimension = caps.maxCubeMapTextureSize;
2371 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002372
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002373 case GL_TEXTURE_RECTANGLE_ANGLE:
2374 maxDimension = caps.maxRectangleTextureSize;
2375 break;
2376
He Yunchaoced53ae2016-11-29 15:00:51 +08002377 case GL_TEXTURE_2D_ARRAY:
2378 maxDimension = caps.max2DTextureSize;
2379 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002380
He Yunchaoced53ae2016-11-29 15:00:51 +08002381 case GL_TEXTURE_3D:
2382 maxDimension = caps.max3DTextureSize;
2383 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002384
He Yunchaoced53ae2016-11-29 15:00:51 +08002385 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002386 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002387 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002388 }
2389
Jamie Madillc29968b2016-01-20 11:17:23 -05002390 gl::Texture *texture =
2391 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002392 if (!texture)
2393 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002394 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002395 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002396 }
2397
Geoff Lang69cce582015-09-17 13:20:36 -04002398 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002399 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002400 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002401 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002402 }
2403
Geoff Langca271392017-04-05 12:30:00 -04002404 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002405 isSubImage ? *texture->getFormat(target, level).info
2406 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002407
Geoff Lang966c9402017-04-18 12:38:27 -04002408 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002409 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002410 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002411 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002412 }
2413
2414 if (isSubImage)
2415 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002416 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2417 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2418 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002419 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002420 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002421 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002422 }
2423 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002424 else
2425 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002426 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002427 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002428 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002429 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002430 }
2431
Geoff Langeb66a6e2016-10-31 13:06:12 -04002432 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002433 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002434 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002435 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002436 }
2437
2438 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002439 if (static_cast<int>(width) > maxLevelDimension ||
2440 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002441 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002442 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002443 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002444 }
2445 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002446
Jamie Madill0c8abca2016-07-22 20:21:26 -04002447 if (textureFormatOut)
2448 {
2449 *textureFormatOut = texture->getFormat(target, level);
2450 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002451
2452 // Detect texture copying feedback loops for WebGL.
2453 if (context->getExtensions().webglCompatibility)
2454 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002455 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002456 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002457 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002458 return false;
2459 }
2460 }
2461
Jamie Madill560a8d82014-05-21 13:06:20 -04002462 return true;
2463}
2464
Jiajia Qind9671222016-11-29 16:30:31 +08002465bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002466{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002467 switch (mode)
2468 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002469 case GL_POINTS:
2470 case GL_LINES:
2471 case GL_LINE_LOOP:
2472 case GL_LINE_STRIP:
2473 case GL_TRIANGLES:
2474 case GL_TRIANGLE_STRIP:
2475 case GL_TRIANGLE_FAN:
2476 break;
2477 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002478 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002479 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002480 }
2481
Jamie Madill250d33f2014-06-06 17:09:03 -04002482 if (count < 0)
2483 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002484 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002485 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002486 }
2487
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002488 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002489
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002490 const Extensions &extensions = context->getExtensions();
2491
2492 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2493 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2494 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2495 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002496 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002497 // Check for mapped buffers
2498 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002499 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002500 {
2501 context->handleError(InvalidOperation());
2502 return false;
2503 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002504 }
2505
Jamie Madillcbcde722017-01-06 14:50:00 -05002506 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2507 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002508 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002509 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002510 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002511 const FramebufferAttachment *dsAttachment =
2512 framebuffer->getStencilOrDepthStencilAttachment();
2513 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002514 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002515 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002516
2517 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2518 bool differentWritemasks =
2519 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2520 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2521 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2522 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2523
2524 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002525 {
Martin Radevffe754b2017-07-31 10:38:07 +03002526 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002527 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002528 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2529 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002530 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002531 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002532 return false;
2533 }
Jamie Madillac528012014-06-20 13:21:23 -04002534 }
2535
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002536 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002537 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002538 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002539 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002540 }
2541
Geoff Lang7dd2e102014-11-10 15:19:26 -05002542 gl::Program *program = state.getProgram();
2543 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002544 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002545 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002546 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002547 }
2548
Yunchao Hecddcb592017-11-13 15:27:35 +08002549 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2550 // vertex shader stage or fragment shader stage is a undefined behaviour.
2551 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2552 // produce undefined result.
Yunchao Heece12532017-11-21 15:50:21 +08002553 if (!program->hasLinkedVertexShader() || !program->hasLinkedFragmentShader())
Yunchao Hecddcb592017-11-13 15:27:35 +08002554 {
2555 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2556 "vertex shader stage or fragment shader stage.");
2557 return false;
2558 }
2559
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002560 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002561 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002562 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002563 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002564 }
2565
Martin Radevffe754b2017-07-31 10:38:07 +03002566 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002567 {
Martin Radevda8e2572017-09-12 17:21:16 +03002568 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002569 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002570 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002571 {
2572 context->handleError(InvalidOperation() << "The number of views in the active program "
2573 "and draw framebuffer does not match.");
2574 return false;
2575 }
Martin Radev7e69f762017-07-27 14:54:13 +03002576
2577 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2578 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2579 framebufferNumViews > 1)
2580 {
2581 context->handleError(InvalidOperation()
2582 << "There is an active transform feedback object "
2583 "when the number of views in the active draw "
2584 "framebuffer is greater than 1.");
2585 return false;
2586 }
Martin Radevffe754b2017-07-31 10:38:07 +03002587
2588 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2589 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2590 {
2591 context->handleError(InvalidOperation() << "There is an active query for target "
2592 "GL_TIME_ELAPSED_EXT when the number of "
2593 "views in the active draw framebuffer is "
2594 "greater than 1.");
2595 return false;
2596 }
Martin Radev7cf61662017-07-26 17:10:53 +03002597 }
2598
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002599 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002600 for (unsigned int uniformBlockIndex = 0;
2601 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002602 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002603 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002604 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002605 const OffsetBindingPointer<Buffer> &uniformBuffer =
2606 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002607
Geoff Lang5d124a62015-09-15 13:03:27 -04002608 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002609 {
2610 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002611 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002612 InvalidOperation()
2613 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002614 return false;
2615 }
2616
Geoff Lang5d124a62015-09-15 13:03:27 -04002617 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002618 if (uniformBufferSize == 0)
2619 {
2620 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002621 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002622 }
2623
Jamie Madill62d31cb2015-09-11 13:25:51 -04002624 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002625 {
2626 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002627 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002628 InvalidOperation()
2629 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002630 return false;
2631 }
2632 }
2633
Geoff Lange0cff192017-05-30 13:04:56 -04002634 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002635 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002636 {
Geoff Lange0cff192017-05-30 13:04:56 -04002637 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002638 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2639 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002640 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002641 return false;
2642 }
Geoff Lange0cff192017-05-30 13:04:56 -04002643
Geoff Lang9ab5b822017-05-30 16:19:23 -04002644 // Detect that the vertex shader input types match the attribute types
2645 if (!ValidateVertexShaderAttributeTypeMatch(context))
2646 {
2647 return false;
2648 }
2649
Geoff Lange0cff192017-05-30 13:04:56 -04002650 // Detect that the color buffer types match the fragment shader output types
2651 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2652 {
2653 return false;
2654 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002655 }
2656
Jamie Madill250d33f2014-06-06 17:09:03 -04002657 // No-op if zero count
2658 return (count > 0);
2659}
2660
Jamie Madillc1d770e2017-04-13 17:31:24 -04002661bool ValidateDrawArraysCommon(ValidationContext *context,
2662 GLenum mode,
2663 GLint first,
2664 GLsizei count,
2665 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002666{
Jamie Madillfd716582014-06-06 17:09:04 -04002667 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002668 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002669 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002670 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002671 }
2672
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002673 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002674 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002675 if (curTransformFeedback && curTransformFeedback->isActive() &&
2676 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002677 {
2678 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002679 // that does not match the current transform feedback object's draw mode (if transform
2680 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002681 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002682 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002683 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002684 }
2685
Jiajia Qind9671222016-11-29 16:30:31 +08002686 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002687 {
2688 return false;
2689 }
2690
Corentin Wallez71168a02016-12-19 15:11:18 -08002691 // Check the computation of maxVertex doesn't overflow.
2692 // - first < 0 or count < 0 have been checked as an error condition
2693 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2694 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2695 ASSERT(count > 0 && first >= 0);
2696 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2697 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002698 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002699 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002700 return false;
2701 }
2702
Corentin Wallez71168a02016-12-19 15:11:18 -08002703 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002704 {
2705 return false;
2706 }
2707
2708 return true;
2709}
2710
He Yunchaoced53ae2016-11-29 15:00:51 +08002711bool ValidateDrawArraysInstancedANGLE(Context *context,
2712 GLenum mode,
2713 GLint first,
2714 GLsizei count,
2715 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002716{
Geoff Lang63c5a592017-09-27 14:08:16 -04002717 if (!context->getExtensions().instancedArrays)
2718 {
2719 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2720 return false;
2721 }
2722
Corentin Wallez170efbf2017-05-02 13:45:01 -04002723 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002724 {
2725 return false;
2726 }
2727
Corentin Wallez0dc97812017-06-22 14:38:44 -04002728 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002729}
2730
Jiajia Qind9671222016-11-29 16:30:31 +08002731bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002732{
Jamie Madill250d33f2014-06-06 17:09:03 -04002733 switch (type)
2734 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002735 case GL_UNSIGNED_BYTE:
2736 case GL_UNSIGNED_SHORT:
2737 break;
2738 case GL_UNSIGNED_INT:
2739 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2740 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002741 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002742 return false;
2743 }
2744 break;
2745 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002746 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002747 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002748 }
2749
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002750 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002751
2752 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002753 if (curTransformFeedback && curTransformFeedback->isActive() &&
2754 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002755 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002756 // It is an invalid operation to call DrawElements, DrawRangeElements or
2757 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002758 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002759 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002760 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002761 }
2762
Jiajia Qind9671222016-11-29 16:30:31 +08002763 return true;
2764}
2765
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002766bool ValidateDrawElementsCommon(ValidationContext *context,
2767 GLenum mode,
2768 GLsizei count,
2769 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002770 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002771 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002772{
2773 if (!ValidateDrawElementsBase(context, type))
2774 return false;
2775
2776 const State &state = context->getGLState();
2777
Corentin Wallez170efbf2017-05-02 13:45:01 -04002778 if (!ValidateDrawBase(context, mode, count))
2779 {
2780 return false;
2781 }
2782
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002783 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2784 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2785 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2786 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002787 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002788 // Check for mapped buffers
2789 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002790 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002791 {
2792 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2793 return false;
2794 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002795 }
2796
He Yunchaoced53ae2016-11-29 15:00:51 +08002797 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002798 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002799
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002800 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2801
2802 if (context->getExtensions().webglCompatibility)
2803 {
2804 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2805 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2806 {
2807 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2808 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2809 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002810 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002811 return false;
2812 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002813
2814 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2815 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2816 // error is generated.
2817 if (reinterpret_cast<intptr_t>(indices) < 0)
2818 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002819 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002820 return false;
2821 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002822 }
2823
2824 if (context->getExtensions().webglCompatibility ||
2825 !context->getGLState().areClientArraysEnabled())
2826 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002827 if (!elementArrayBuffer && count > 0)
2828 {
2829 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2830 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2831 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002832 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002833 return false;
2834 }
2835 }
2836
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002837 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002838 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002839 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002840 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002841 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2842 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2843 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2844 constexpr uint64_t kMaxTypeSize = 8;
2845 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2846 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2847 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002848
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002849 uint64_t typeSize = typeBytes;
2850 uint64_t elementCount = static_cast<uint64_t>(count);
2851 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2852
2853 // Doing the multiplication here is overflow-safe
2854 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2855
2856 // The offset can be any value, check for overflows
2857 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2858 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002859 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002860 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002861 return false;
2862 }
2863
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002864 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2865 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002866 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002867 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002868 return false;
2869 }
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002870
Corentin Wallez487653b2017-09-01 17:17:55 -04002871 ASSERT(isPow2(typeSize) && typeSize > 0);
2872 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002873 {
2874 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
2875 return false;
2876 }
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002877 }
2878 else if (!indices)
2879 {
2880 // This is an application error that would normally result in a crash,
2881 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002882 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04002883 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002884 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002885 }
2886
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002887 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002888 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002889 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2890 // access is enabled.
2891 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2892 {
2893 return false;
2894 }
2895 }
2896 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:
Xinghua Cao971f8502017-10-17 13:01:24 +08004164 case GL_COMPUTE_WORK_GROUP_SIZE:
jchen1058f67be2017-10-27 08:59:27 +08004165 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004166 if (context->getClientVersion() < Version(3, 1))
4167 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004168 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004169 return false;
4170 }
4171 break;
4172
Geoff Langff5b2d52016-09-07 11:32:23 -04004173 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004174 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004175 return false;
4176 }
4177
4178 return true;
4179}
4180
4181bool ValidateGetProgramivRobustANGLE(Context *context,
4182 GLuint program,
4183 GLenum pname,
4184 GLsizei bufSize,
4185 GLsizei *numParams)
4186{
4187 if (!ValidateRobustEntryPoint(context, bufSize))
4188 {
4189 return false;
4190 }
4191
Jamie Madillbe849e42017-05-02 15:49:00 -04004192 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004193 {
4194 return false;
4195 }
4196
4197 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4198 {
4199 return false;
4200 }
4201
4202 return true;
4203}
4204
Geoff Lang740d9022016-10-07 11:20:52 -04004205bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4206 GLenum target,
4207 GLenum pname,
4208 GLsizei bufSize,
4209 GLsizei *length,
4210 GLint *params)
4211{
4212 if (!ValidateRobustEntryPoint(context, bufSize))
4213 {
4214 return false;
4215 }
4216
4217 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4218 {
4219 return false;
4220 }
4221
4222 if (!ValidateRobustBufferSize(context, bufSize, *length))
4223 {
4224 return false;
4225 }
4226
4227 return true;
4228}
4229
Geoff Langd7d0ed32016-10-07 11:33:51 -04004230bool ValidateGetShaderivRobustANGLE(Context *context,
4231 GLuint shader,
4232 GLenum pname,
4233 GLsizei bufSize,
4234 GLsizei *length,
4235 GLint *params)
4236{
4237 if (!ValidateRobustEntryPoint(context, bufSize))
4238 {
4239 return false;
4240 }
4241
4242 if (!ValidateGetShaderivBase(context, shader, pname, length))
4243 {
4244 return false;
4245 }
4246
4247 if (!ValidateRobustBufferSize(context, bufSize, *length))
4248 {
4249 return false;
4250 }
4251
4252 return true;
4253}
4254
Geoff Langc1984ed2016-10-07 12:41:00 -04004255bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4256 GLenum target,
4257 GLenum pname,
4258 GLsizei bufSize,
4259 GLsizei *length,
4260 GLfloat *params)
4261{
4262 if (!ValidateRobustEntryPoint(context, bufSize))
4263 {
4264 return false;
4265 }
4266
4267 if (!ValidateGetTexParameterBase(context, target, pname, length))
4268 {
4269 return false;
4270 }
4271
4272 if (!ValidateRobustBufferSize(context, bufSize, *length))
4273 {
4274 return false;
4275 }
4276
4277 return true;
4278}
4279
Geoff Langc1984ed2016-10-07 12:41:00 -04004280bool ValidateGetTexParameterivRobustANGLE(Context *context,
4281 GLenum target,
4282 GLenum pname,
4283 GLsizei bufSize,
4284 GLsizei *length,
4285 GLint *params)
4286{
4287 if (!ValidateRobustEntryPoint(context, bufSize))
4288 {
4289 return false;
4290 }
4291
4292 if (!ValidateGetTexParameterBase(context, target, pname, length))
4293 {
4294 return false;
4295 }
4296
4297 if (!ValidateRobustBufferSize(context, bufSize, *length))
4298 {
4299 return false;
4300 }
4301
4302 return true;
4303}
4304
Geoff Langc1984ed2016-10-07 12:41:00 -04004305bool ValidateTexParameterfvRobustANGLE(Context *context,
4306 GLenum target,
4307 GLenum pname,
4308 GLsizei bufSize,
4309 const GLfloat *params)
4310{
4311 if (!ValidateRobustEntryPoint(context, bufSize))
4312 {
4313 return false;
4314 }
4315
4316 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4317}
4318
Geoff Langc1984ed2016-10-07 12:41:00 -04004319bool ValidateTexParameterivRobustANGLE(Context *context,
4320 GLenum target,
4321 GLenum pname,
4322 GLsizei bufSize,
4323 const GLint *params)
4324{
4325 if (!ValidateRobustEntryPoint(context, bufSize))
4326 {
4327 return false;
4328 }
4329
4330 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4331}
4332
Geoff Langc1984ed2016-10-07 12:41:00 -04004333bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4334 GLuint sampler,
4335 GLenum pname,
4336 GLuint bufSize,
4337 GLsizei *length,
4338 GLfloat *params)
4339{
4340 if (!ValidateRobustEntryPoint(context, bufSize))
4341 {
4342 return false;
4343 }
4344
4345 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4346 {
4347 return false;
4348 }
4349
4350 if (!ValidateRobustBufferSize(context, bufSize, *length))
4351 {
4352 return false;
4353 }
4354
4355 return true;
4356}
4357
Geoff Langc1984ed2016-10-07 12:41:00 -04004358bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4359 GLuint sampler,
4360 GLenum pname,
4361 GLuint bufSize,
4362 GLsizei *length,
4363 GLint *params)
4364{
4365 if (!ValidateRobustEntryPoint(context, bufSize))
4366 {
4367 return false;
4368 }
4369
4370 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4371 {
4372 return false;
4373 }
4374
4375 if (!ValidateRobustBufferSize(context, bufSize, *length))
4376 {
4377 return false;
4378 }
4379
4380 return true;
4381}
4382
Geoff Langc1984ed2016-10-07 12:41:00 -04004383bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4384 GLuint sampler,
4385 GLenum pname,
4386 GLsizei bufSize,
4387 const GLfloat *params)
4388{
4389 if (!ValidateRobustEntryPoint(context, bufSize))
4390 {
4391 return false;
4392 }
4393
4394 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4395}
4396
Geoff Langc1984ed2016-10-07 12:41:00 -04004397bool ValidateSamplerParameterivRobustANGLE(Context *context,
4398 GLuint sampler,
4399 GLenum pname,
4400 GLsizei bufSize,
4401 const GLint *params)
4402{
4403 if (!ValidateRobustEntryPoint(context, bufSize))
4404 {
4405 return false;
4406 }
4407
4408 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4409}
4410
Geoff Lang0b031062016-10-13 14:30:04 -04004411bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4412 GLuint index,
4413 GLenum pname,
4414 GLsizei bufSize,
4415 GLsizei *length,
4416 GLfloat *params)
4417{
4418 if (!ValidateRobustEntryPoint(context, bufSize))
4419 {
4420 return false;
4421 }
4422
4423 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4424 {
4425 return false;
4426 }
4427
4428 if (!ValidateRobustBufferSize(context, bufSize, *length))
4429 {
4430 return false;
4431 }
4432
4433 return true;
4434}
4435
Geoff Lang0b031062016-10-13 14:30:04 -04004436bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4437 GLuint index,
4438 GLenum pname,
4439 GLsizei bufSize,
4440 GLsizei *length,
4441 GLint *params)
4442{
4443 if (!ValidateRobustEntryPoint(context, bufSize))
4444 {
4445 return false;
4446 }
4447
4448 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4449 {
4450 return false;
4451 }
4452
4453 if (!ValidateRobustBufferSize(context, bufSize, *length))
4454 {
4455 return false;
4456 }
4457
4458 return true;
4459}
4460
Geoff Lang0b031062016-10-13 14:30:04 -04004461bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4462 GLuint index,
4463 GLenum pname,
4464 GLsizei bufSize,
4465 GLsizei *length,
4466 void **pointer)
4467{
4468 if (!ValidateRobustEntryPoint(context, bufSize))
4469 {
4470 return false;
4471 }
4472
4473 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4474 {
4475 return false;
4476 }
4477
4478 if (!ValidateRobustBufferSize(context, bufSize, *length))
4479 {
4480 return false;
4481 }
4482
4483 return true;
4484}
4485
Geoff Lang0b031062016-10-13 14:30:04 -04004486bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4487 GLuint index,
4488 GLenum pname,
4489 GLsizei bufSize,
4490 GLsizei *length,
4491 GLint *params)
4492{
4493 if (!ValidateRobustEntryPoint(context, bufSize))
4494 {
4495 return false;
4496 }
4497
4498 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4499 {
4500 return false;
4501 }
4502
4503 if (!ValidateRobustBufferSize(context, bufSize, *length))
4504 {
4505 return false;
4506 }
4507
4508 return true;
4509}
4510
Geoff Lang0b031062016-10-13 14:30:04 -04004511bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4512 GLuint index,
4513 GLenum pname,
4514 GLsizei bufSize,
4515 GLsizei *length,
4516 GLuint *params)
4517{
4518 if (!ValidateRobustEntryPoint(context, bufSize))
4519 {
4520 return false;
4521 }
4522
4523 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4524 {
4525 return false;
4526 }
4527
4528 if (!ValidateRobustBufferSize(context, bufSize, *length))
4529 {
4530 return false;
4531 }
4532
4533 return true;
4534}
4535
Geoff Lang6899b872016-10-14 11:30:13 -04004536bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4537 GLuint program,
4538 GLuint uniformBlockIndex,
4539 GLenum pname,
4540 GLsizei bufSize,
4541 GLsizei *length,
4542 GLint *params)
4543{
4544 if (!ValidateRobustEntryPoint(context, bufSize))
4545 {
4546 return false;
4547 }
4548
4549 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4550 {
4551 return false;
4552 }
4553
4554 if (!ValidateRobustBufferSize(context, bufSize, *length))
4555 {
4556 return false;
4557 }
4558
4559 return true;
4560}
4561
Geoff Lang0a9661f2016-10-20 10:59:20 -07004562bool ValidateGetInternalFormativRobustANGLE(Context *context,
4563 GLenum target,
4564 GLenum internalformat,
4565 GLenum pname,
4566 GLsizei bufSize,
4567 GLsizei *length,
4568 GLint *params)
4569{
4570 if (!ValidateRobustEntryPoint(context, bufSize))
4571 {
4572 return false;
4573 }
4574
4575 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4576 {
4577 return false;
4578 }
4579
4580 if (!ValidateRobustBufferSize(context, bufSize, *length))
4581 {
4582 return false;
4583 }
4584
4585 return true;
4586}
4587
Shao80957d92017-02-20 21:25:59 +08004588bool ValidateVertexFormatBase(ValidationContext *context,
4589 GLuint attribIndex,
4590 GLint size,
4591 GLenum type,
4592 GLboolean pureInteger)
4593{
4594 const Caps &caps = context->getCaps();
4595 if (attribIndex >= caps.maxVertexAttributes)
4596 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004597 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004598 return false;
4599 }
4600
4601 if (size < 1 || size > 4)
4602 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004603 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004604 return false;
Shao80957d92017-02-20 21:25:59 +08004605 }
4606
4607 switch (type)
4608 {
4609 case GL_BYTE:
4610 case GL_UNSIGNED_BYTE:
4611 case GL_SHORT:
4612 case GL_UNSIGNED_SHORT:
4613 break;
4614
4615 case GL_INT:
4616 case GL_UNSIGNED_INT:
4617 if (context->getClientMajorVersion() < 3)
4618 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004619 context->handleError(InvalidEnum()
4620 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004621 return false;
4622 }
4623 break;
4624
4625 case GL_FIXED:
4626 case GL_FLOAT:
4627 if (pureInteger)
4628 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004629 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004630 return false;
4631 }
4632 break;
4633
4634 case GL_HALF_FLOAT:
4635 if (context->getClientMajorVersion() < 3)
4636 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004637 context->handleError(InvalidEnum()
4638 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004639 return false;
4640 }
4641 if (pureInteger)
4642 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004643 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004644 return false;
4645 }
4646 break;
4647
4648 case GL_INT_2_10_10_10_REV:
4649 case GL_UNSIGNED_INT_2_10_10_10_REV:
4650 if (context->getClientMajorVersion() < 3)
4651 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004652 context->handleError(InvalidEnum()
4653 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004654 return false;
4655 }
4656 if (pureInteger)
4657 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004658 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004659 return false;
4660 }
4661 if (size != 4)
4662 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004663 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4664 "UNSIGNED_INT_2_10_10_10_REV and "
4665 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004666 return false;
4667 }
4668 break;
4669
4670 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004671 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004672 return false;
4673 }
4674
4675 return true;
4676}
4677
Geoff Lang76e65652017-03-27 14:58:02 -04004678// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4679// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4680// specified clear value and the type of a buffer that is being cleared generates an
4681// INVALID_OPERATION error instead of producing undefined results
4682bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4683 GLint drawbuffer,
4684 const GLenum *validComponentTypes,
4685 size_t validComponentTypeCount)
4686{
4687 const FramebufferAttachment *attachment =
4688 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4689 if (attachment)
4690 {
4691 GLenum componentType = attachment->getFormat().info->componentType;
4692 const GLenum *end = validComponentTypes + validComponentTypeCount;
4693 if (std::find(validComponentTypes, end, componentType) == end)
4694 {
4695 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004696 InvalidOperation()
4697 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004698 return false;
4699 }
4700 }
4701
4702 return true;
4703}
4704
Corentin Wallezb2931602017-04-11 15:58:57 -04004705bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4706 GLsizei imageSize,
4707 GLsizei dataSize)
4708{
4709 if (!ValidateRobustEntryPoint(context, dataSize))
4710 {
4711 return false;
4712 }
4713
Corentin Wallez336129f2017-10-17 15:55:40 -04004714 gl::Buffer *pixelUnpackBuffer =
4715 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004716 if (pixelUnpackBuffer == nullptr)
4717 {
4718 if (dataSize < imageSize)
4719 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004720 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004721 }
4722 }
4723 return true;
4724}
4725
Jamie Madillbe849e42017-05-02 15:49:00 -04004726bool ValidateGetBufferParameterBase(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004727 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004728 GLenum pname,
4729 bool pointerVersion,
4730 GLsizei *numParams)
4731{
4732 if (numParams)
4733 {
4734 *numParams = 0;
4735 }
4736
Corentin Walleze4477002017-12-01 14:39:58 -05004737 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004738 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004739 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004740 return false;
4741 }
4742
4743 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4744 if (!buffer)
4745 {
4746 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004747 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004748 return false;
4749 }
4750
4751 const Extensions &extensions = context->getExtensions();
4752
4753 switch (pname)
4754 {
4755 case GL_BUFFER_USAGE:
4756 case GL_BUFFER_SIZE:
4757 break;
4758
4759 case GL_BUFFER_ACCESS_OES:
4760 if (!extensions.mapBuffer)
4761 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004762 context->handleError(InvalidEnum()
4763 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004764 return false;
4765 }
4766 break;
4767
4768 case GL_BUFFER_MAPPED:
4769 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4770 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4771 !extensions.mapBufferRange)
4772 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004773 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4774 "GL_OES_mapbuffer or "
4775 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004776 return false;
4777 }
4778 break;
4779
4780 case GL_BUFFER_MAP_POINTER:
4781 if (!pointerVersion)
4782 {
4783 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004784 InvalidEnum()
4785 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004786 return false;
4787 }
4788 break;
4789
4790 case GL_BUFFER_ACCESS_FLAGS:
4791 case GL_BUFFER_MAP_OFFSET:
4792 case GL_BUFFER_MAP_LENGTH:
4793 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4794 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004795 context->handleError(InvalidEnum()
4796 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004797 return false;
4798 }
4799 break;
4800
4801 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004802 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004803 return false;
4804 }
4805
4806 // All buffer parameter queries return one value.
4807 if (numParams)
4808 {
4809 *numParams = 1;
4810 }
4811
4812 return true;
4813}
4814
4815bool ValidateGetRenderbufferParameterivBase(Context *context,
4816 GLenum target,
4817 GLenum pname,
4818 GLsizei *length)
4819{
4820 if (length)
4821 {
4822 *length = 0;
4823 }
4824
4825 if (target != GL_RENDERBUFFER)
4826 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004827 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004828 return false;
4829 }
4830
4831 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4832 if (renderbuffer == nullptr)
4833 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004834 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004835 return false;
4836 }
4837
4838 switch (pname)
4839 {
4840 case GL_RENDERBUFFER_WIDTH:
4841 case GL_RENDERBUFFER_HEIGHT:
4842 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4843 case GL_RENDERBUFFER_RED_SIZE:
4844 case GL_RENDERBUFFER_GREEN_SIZE:
4845 case GL_RENDERBUFFER_BLUE_SIZE:
4846 case GL_RENDERBUFFER_ALPHA_SIZE:
4847 case GL_RENDERBUFFER_DEPTH_SIZE:
4848 case GL_RENDERBUFFER_STENCIL_SIZE:
4849 break;
4850
4851 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4852 if (!context->getExtensions().framebufferMultisample)
4853 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004854 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004855 return false;
4856 }
4857 break;
4858
4859 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004860 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004861 return false;
4862 }
4863
4864 if (length)
4865 {
4866 *length = 1;
4867 }
4868 return true;
4869}
4870
4871bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4872{
4873 if (length)
4874 {
4875 *length = 0;
4876 }
4877
4878 if (GetValidShader(context, shader) == nullptr)
4879 {
4880 return false;
4881 }
4882
4883 switch (pname)
4884 {
4885 case GL_SHADER_TYPE:
4886 case GL_DELETE_STATUS:
4887 case GL_COMPILE_STATUS:
4888 case GL_INFO_LOG_LENGTH:
4889 case GL_SHADER_SOURCE_LENGTH:
4890 break;
4891
4892 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4893 if (!context->getExtensions().translatedShaderSource)
4894 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004895 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004896 return false;
4897 }
4898 break;
4899
4900 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004901 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004902 return false;
4903 }
4904
4905 if (length)
4906 {
4907 *length = 1;
4908 }
4909 return true;
4910}
4911
4912bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4913{
4914 if (length)
4915 {
4916 *length = 0;
4917 }
4918
4919 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4920 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004921 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004922 return false;
4923 }
4924
4925 if (context->getTargetTexture(target) == nullptr)
4926 {
4927 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004928 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004929 return false;
4930 }
4931
4932 switch (pname)
4933 {
4934 case GL_TEXTURE_MAG_FILTER:
4935 case GL_TEXTURE_MIN_FILTER:
4936 case GL_TEXTURE_WRAP_S:
4937 case GL_TEXTURE_WRAP_T:
4938 break;
4939
4940 case GL_TEXTURE_USAGE_ANGLE:
4941 if (!context->getExtensions().textureUsage)
4942 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004943 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004944 return false;
4945 }
4946 break;
4947
4948 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05004949 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04004950 {
Jamie Madillbe849e42017-05-02 15:49:00 -04004951 return false;
4952 }
4953 break;
4954
4955 case GL_TEXTURE_IMMUTABLE_FORMAT:
4956 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4957 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004958 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004959 return false;
4960 }
4961 break;
4962
4963 case GL_TEXTURE_WRAP_R:
4964 case GL_TEXTURE_IMMUTABLE_LEVELS:
4965 case GL_TEXTURE_SWIZZLE_R:
4966 case GL_TEXTURE_SWIZZLE_G:
4967 case GL_TEXTURE_SWIZZLE_B:
4968 case GL_TEXTURE_SWIZZLE_A:
4969 case GL_TEXTURE_BASE_LEVEL:
4970 case GL_TEXTURE_MAX_LEVEL:
4971 case GL_TEXTURE_MIN_LOD:
4972 case GL_TEXTURE_MAX_LOD:
4973 case GL_TEXTURE_COMPARE_MODE:
4974 case GL_TEXTURE_COMPARE_FUNC:
4975 if (context->getClientMajorVersion() < 3)
4976 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004977 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004978 return false;
4979 }
4980 break;
4981
4982 case GL_TEXTURE_SRGB_DECODE_EXT:
4983 if (!context->getExtensions().textureSRGBDecode)
4984 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004985 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004986 return false;
4987 }
4988 break;
4989
4990 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004991 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004992 return false;
4993 }
4994
4995 if (length)
4996 {
4997 *length = 1;
4998 }
4999 return true;
5000}
5001
5002bool ValidateGetVertexAttribBase(Context *context,
5003 GLuint index,
5004 GLenum pname,
5005 GLsizei *length,
5006 bool pointer,
5007 bool pureIntegerEntryPoint)
5008{
5009 if (length)
5010 {
5011 *length = 0;
5012 }
5013
5014 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5015 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005016 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005017 return false;
5018 }
5019
5020 if (index >= context->getCaps().maxVertexAttributes)
5021 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005022 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005023 return false;
5024 }
5025
5026 if (pointer)
5027 {
5028 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5029 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005030 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005031 return false;
5032 }
5033 }
5034 else
5035 {
5036 switch (pname)
5037 {
5038 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5039 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5040 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5041 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5042 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5043 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5044 case GL_CURRENT_VERTEX_ATTRIB:
5045 break;
5046
5047 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5048 static_assert(
5049 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5050 "ANGLE extension enums not equal to GL enums.");
5051 if (context->getClientMajorVersion() < 3 &&
5052 !context->getExtensions().instancedArrays)
5053 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005054 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5055 "requires OpenGL ES 3.0 or "
5056 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005057 return false;
5058 }
5059 break;
5060
5061 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5062 if (context->getClientMajorVersion() < 3)
5063 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005064 context->handleError(
5065 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005066 return false;
5067 }
5068 break;
5069
5070 case GL_VERTEX_ATTRIB_BINDING:
5071 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5072 if (context->getClientVersion() < ES_3_1)
5073 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005074 context->handleError(InvalidEnum()
5075 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005076 return false;
5077 }
5078 break;
5079
5080 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005081 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005082 return false;
5083 }
5084 }
5085
5086 if (length)
5087 {
5088 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5089 {
5090 *length = 4;
5091 }
5092 else
5093 {
5094 *length = 1;
5095 }
5096 }
5097
5098 return true;
5099}
5100
Jamie Madill4928b7c2017-06-20 12:57:39 -04005101bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005102 GLint x,
5103 GLint y,
5104 GLsizei width,
5105 GLsizei height,
5106 GLenum format,
5107 GLenum type,
5108 GLsizei bufSize,
5109 GLsizei *length,
5110 GLsizei *columns,
5111 GLsizei *rows,
5112 void *pixels)
5113{
5114 if (length != nullptr)
5115 {
5116 *length = 0;
5117 }
5118 if (rows != nullptr)
5119 {
5120 *rows = 0;
5121 }
5122 if (columns != nullptr)
5123 {
5124 *columns = 0;
5125 }
5126
5127 if (width < 0 || height < 0)
5128 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005129 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005130 return false;
5131 }
5132
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005133 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005134
5135 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5136 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005137 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005138 return false;
5139 }
5140
5141 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5142 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005143 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005144 return false;
5145 }
5146
5147 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5148 ASSERT(framebuffer);
5149
5150 if (framebuffer->getReadBufferState() == GL_NONE)
5151 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005152 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005153 return false;
5154 }
5155
5156 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5157 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5158 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5159 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5160 // situation is an application error that would lead to a crash in ANGLE.
5161 if (readBuffer == nullptr)
5162 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005163 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005164 return false;
5165 }
5166
Martin Radev28031682017-07-28 14:47:56 +03005167 // ANGLE_multiview, Revision 1:
5168 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5169 // current read framebuffer is not NONE.
5170 if (readBuffer->getMultiviewLayout() != GL_NONE)
5171 {
5172 context->handleError(InvalidFramebufferOperation()
5173 << "Attempting to read from a multi-view framebuffer.");
5174 return false;
5175 }
5176
Geoff Lang280ba992017-04-18 16:30:58 -04005177 if (context->getExtensions().webglCompatibility)
5178 {
5179 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5180 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5181 // and type before validating the combination of format and type. However, the
5182 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5183 // verifies that GL_INVALID_OPERATION is generated.
5184 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5185 // dEQP/WebGL.
5186 if (!ValidReadPixelsFormatEnum(context, format))
5187 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005188 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005189 return false;
5190 }
5191
5192 if (!ValidReadPixelsTypeEnum(context, type))
5193 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005194 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005195 return false;
5196 }
5197 }
5198
Jamie Madill4928b7c2017-06-20 12:57:39 -04005199 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5200 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005201 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5202
5203 bool validFormatTypeCombination =
5204 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5205
5206 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5207 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005208 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005209 return false;
5210 }
5211
5212 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005213 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005214 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5215 {
5216 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005217 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005218 return false;
5219 }
5220
5221 // .. the data would be packed to the buffer object such that the memory writes required
5222 // would exceed the data store size.
5223 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5224 const gl::Extents size(width, height, 1);
5225 const auto &pack = context->getGLState().getPackState();
5226
5227 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5228 if (endByteOrErr.isError())
5229 {
5230 context->handleError(endByteOrErr.getError());
5231 return false;
5232 }
5233
5234 size_t endByte = endByteOrErr.getResult();
5235 if (bufSize >= 0)
5236 {
5237 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5238 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005239 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005240 return false;
5241 }
5242 }
5243
5244 if (pixelPackBuffer != nullptr)
5245 {
5246 CheckedNumeric<size_t> checkedEndByte(endByte);
5247 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5248 checkedEndByte += checkedOffset;
5249
5250 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5251 {
5252 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005253 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005254 return false;
5255 }
5256 }
5257
5258 if (pixelPackBuffer == nullptr && length != nullptr)
5259 {
5260 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5261 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005262 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005263 return false;
5264 }
5265
5266 *length = static_cast<GLsizei>(endByte);
5267 }
5268
5269 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5270 angle::CheckedNumeric<int> clippedExtent(length);
5271 if (start < 0)
5272 {
5273 // "subtract" the area that is less than 0
5274 clippedExtent += start;
5275 }
5276
5277 const int readExtent = start + length;
5278 if (readExtent > bufferSize)
5279 {
5280 // Subtract the region to the right of the read buffer
5281 clippedExtent -= (readExtent - bufferSize);
5282 }
5283
5284 if (!clippedExtent.IsValid())
5285 {
5286 return 0;
5287 }
5288
5289 return std::max(clippedExtent.ValueOrDie(), 0);
5290 };
5291
5292 if (columns != nullptr)
5293 {
5294 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5295 }
5296
5297 if (rows != nullptr)
5298 {
5299 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5300 }
5301
5302 return true;
5303}
5304
5305template <typename ParamType>
5306bool ValidateTexParameterBase(Context *context,
5307 GLenum target,
5308 GLenum pname,
5309 GLsizei bufSize,
5310 const ParamType *params)
5311{
5312 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5313 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005314 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005315 return false;
5316 }
5317
5318 if (context->getTargetTexture(target) == nullptr)
5319 {
5320 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005321 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005322 return false;
5323 }
5324
5325 const GLsizei minBufSize = 1;
5326 if (bufSize >= 0 && bufSize < minBufSize)
5327 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005328 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005329 return false;
5330 }
5331
5332 switch (pname)
5333 {
5334 case GL_TEXTURE_WRAP_R:
5335 case GL_TEXTURE_SWIZZLE_R:
5336 case GL_TEXTURE_SWIZZLE_G:
5337 case GL_TEXTURE_SWIZZLE_B:
5338 case GL_TEXTURE_SWIZZLE_A:
5339 case GL_TEXTURE_BASE_LEVEL:
5340 case GL_TEXTURE_MAX_LEVEL:
5341 case GL_TEXTURE_COMPARE_MODE:
5342 case GL_TEXTURE_COMPARE_FUNC:
5343 case GL_TEXTURE_MIN_LOD:
5344 case GL_TEXTURE_MAX_LOD:
5345 if (context->getClientMajorVersion() < 3)
5346 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005347 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005348 return false;
5349 }
5350 if (target == GL_TEXTURE_EXTERNAL_OES &&
5351 !context->getExtensions().eglImageExternalEssl3)
5352 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005353 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5354 "available without "
5355 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005356 return false;
5357 }
5358 break;
5359
5360 default:
5361 break;
5362 }
5363
JiangYizhou4cff8d62017-07-06 14:54:09 +08005364 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5365 {
5366 switch (pname)
5367 {
5368 case GL_TEXTURE_MIN_FILTER:
5369 case GL_TEXTURE_MAG_FILTER:
5370 case GL_TEXTURE_WRAP_S:
5371 case GL_TEXTURE_WRAP_T:
5372 case GL_TEXTURE_WRAP_R:
5373 case GL_TEXTURE_MIN_LOD:
5374 case GL_TEXTURE_MAX_LOD:
5375 case GL_TEXTURE_COMPARE_MODE:
5376 case GL_TEXTURE_COMPARE_FUNC:
5377 context->handleError(InvalidEnum()
5378 << "Invalid parameter for 2D multisampled textures.");
5379 return false;
5380 }
5381 }
5382
Jamie Madillbe849e42017-05-02 15:49:00 -04005383 switch (pname)
5384 {
5385 case GL_TEXTURE_WRAP_S:
5386 case GL_TEXTURE_WRAP_T:
5387 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005388 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005389 bool restrictedWrapModes =
5390 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5391 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5392 {
5393 return false;
5394 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005395 }
5396 break;
5397
5398 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005399 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005400 bool restrictedMinFilter =
5401 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5402 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5403 {
5404 return false;
5405 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005406 }
5407 break;
5408
5409 case GL_TEXTURE_MAG_FILTER:
5410 if (!ValidateTextureMagFilterValue(context, params))
5411 {
5412 return false;
5413 }
5414 break;
5415
5416 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005417 if (!context->getExtensions().textureUsage)
5418 {
5419 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5420 return false;
5421 }
5422
Jamie Madillbe849e42017-05-02 15:49:00 -04005423 switch (ConvertToGLenum(params[0]))
5424 {
5425 case GL_NONE:
5426 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5427 break;
5428
5429 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005430 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005431 return false;
5432 }
5433 break;
5434
5435 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Jamie Madillbe849e42017-05-02 15:49:00 -04005436 {
Luc Ferron1b1a8642018-01-23 15:12:01 -05005437 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5438 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5439 {
5440 return false;
5441 }
5442 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
Jamie Madillbe849e42017-05-02 15:49:00 -04005443 }
5444 break;
5445
5446 case GL_TEXTURE_MIN_LOD:
5447 case GL_TEXTURE_MAX_LOD:
5448 // any value is permissible
5449 break;
5450
5451 case GL_TEXTURE_COMPARE_MODE:
5452 if (!ValidateTextureCompareModeValue(context, params))
5453 {
5454 return false;
5455 }
5456 break;
5457
5458 case GL_TEXTURE_COMPARE_FUNC:
5459 if (!ValidateTextureCompareFuncValue(context, params))
5460 {
5461 return false;
5462 }
5463 break;
5464
5465 case GL_TEXTURE_SWIZZLE_R:
5466 case GL_TEXTURE_SWIZZLE_G:
5467 case GL_TEXTURE_SWIZZLE_B:
5468 case GL_TEXTURE_SWIZZLE_A:
5469 switch (ConvertToGLenum(params[0]))
5470 {
5471 case GL_RED:
5472 case GL_GREEN:
5473 case GL_BLUE:
5474 case GL_ALPHA:
5475 case GL_ZERO:
5476 case GL_ONE:
5477 break;
5478
5479 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005480 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005481 return false;
5482 }
5483 break;
5484
5485 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005486 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005488 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005489 return false;
5490 }
5491 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5492 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005493 context->handleError(InvalidOperation()
5494 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005495 return false;
5496 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005497 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5498 {
5499 context->handleError(InvalidOperation()
5500 << "Base level must be 0 for multisampled textures.");
5501 return false;
5502 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005503 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5504 {
5505 context->handleError(InvalidOperation()
5506 << "Base level must be 0 for rectangle textures.");
5507 return false;
5508 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005509 break;
5510
5511 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005512 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005513 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005514 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005515 return false;
5516 }
5517 break;
5518
5519 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5520 if (context->getClientVersion() < Version(3, 1))
5521 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005522 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005523 return false;
5524 }
5525 switch (ConvertToGLenum(params[0]))
5526 {
5527 case GL_DEPTH_COMPONENT:
5528 case GL_STENCIL_INDEX:
5529 break;
5530
5531 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005532 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005533 return false;
5534 }
5535 break;
5536
5537 case GL_TEXTURE_SRGB_DECODE_EXT:
5538 if (!ValidateTextureSRGBDecodeValue(context, params))
5539 {
5540 return false;
5541 }
5542 break;
5543
5544 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005545 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005546 return false;
5547 }
5548
5549 return true;
5550}
5551
5552template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5553template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5554
Jamie Madill12e957f2017-08-26 21:42:26 -04005555bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5556{
5557 if (index >= MAX_VERTEX_ATTRIBS)
5558 {
5559 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5560 return false;
5561 }
5562
5563 return true;
5564}
5565
5566bool ValidateGetActiveUniformBlockivBase(Context *context,
5567 GLuint program,
5568 GLuint uniformBlockIndex,
5569 GLenum pname,
5570 GLsizei *length)
5571{
5572 if (length)
5573 {
5574 *length = 0;
5575 }
5576
5577 if (context->getClientMajorVersion() < 3)
5578 {
5579 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5580 return false;
5581 }
5582
5583 Program *programObject = GetValidProgram(context, program);
5584 if (!programObject)
5585 {
5586 return false;
5587 }
5588
5589 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5590 {
5591 context->handleError(InvalidValue()
5592 << "uniformBlockIndex exceeds active uniform block count.");
5593 return false;
5594 }
5595
5596 switch (pname)
5597 {
5598 case GL_UNIFORM_BLOCK_BINDING:
5599 case GL_UNIFORM_BLOCK_DATA_SIZE:
5600 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5601 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5602 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5603 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5604 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5605 break;
5606
5607 default:
5608 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5609 return false;
5610 }
5611
5612 if (length)
5613 {
5614 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5615 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005616 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005617 programObject->getUniformBlockByIndex(uniformBlockIndex);
5618 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5619 }
5620 else
5621 {
5622 *length = 1;
5623 }
5624 }
5625
5626 return true;
5627}
5628
Jamie Madill9696d072017-08-26 23:19:57 -04005629template <typename ParamType>
5630bool ValidateSamplerParameterBase(Context *context,
5631 GLuint sampler,
5632 GLenum pname,
5633 GLsizei bufSize,
5634 ParamType *params)
5635{
5636 if (context->getClientMajorVersion() < 3)
5637 {
5638 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5639 return false;
5640 }
5641
5642 if (!context->isSampler(sampler))
5643 {
5644 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5645 return false;
5646 }
5647
5648 const GLsizei minBufSize = 1;
5649 if (bufSize >= 0 && bufSize < minBufSize)
5650 {
5651 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5652 return false;
5653 }
5654
5655 switch (pname)
5656 {
5657 case GL_TEXTURE_WRAP_S:
5658 case GL_TEXTURE_WRAP_T:
5659 case GL_TEXTURE_WRAP_R:
5660 if (!ValidateTextureWrapModeValue(context, params, false))
5661 {
5662 return false;
5663 }
5664 break;
5665
5666 case GL_TEXTURE_MIN_FILTER:
5667 if (!ValidateTextureMinFilterValue(context, params, false))
5668 {
5669 return false;
5670 }
5671 break;
5672
5673 case GL_TEXTURE_MAG_FILTER:
5674 if (!ValidateTextureMagFilterValue(context, params))
5675 {
5676 return false;
5677 }
5678 break;
5679
5680 case GL_TEXTURE_MIN_LOD:
5681 case GL_TEXTURE_MAX_LOD:
5682 // any value is permissible
5683 break;
5684
5685 case GL_TEXTURE_COMPARE_MODE:
5686 if (!ValidateTextureCompareModeValue(context, params))
5687 {
5688 return false;
5689 }
5690 break;
5691
5692 case GL_TEXTURE_COMPARE_FUNC:
5693 if (!ValidateTextureCompareFuncValue(context, params))
5694 {
5695 return false;
5696 }
5697 break;
5698
5699 case GL_TEXTURE_SRGB_DECODE_EXT:
5700 if (!ValidateTextureSRGBDecodeValue(context, params))
5701 {
5702 return false;
5703 }
5704 break;
5705
Luc Ferron1b1a8642018-01-23 15:12:01 -05005706 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5707 {
5708 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5709 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5710 {
5711 return false;
5712 }
5713 }
5714 break;
5715
Jamie Madill9696d072017-08-26 23:19:57 -04005716 default:
5717 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5718 return false;
5719 }
5720
5721 return true;
5722}
5723
5724template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5725template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5726
5727bool ValidateGetSamplerParameterBase(Context *context,
5728 GLuint sampler,
5729 GLenum pname,
5730 GLsizei *length)
5731{
5732 if (length)
5733 {
5734 *length = 0;
5735 }
5736
5737 if (context->getClientMajorVersion() < 3)
5738 {
5739 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5740 return false;
5741 }
5742
5743 if (!context->isSampler(sampler))
5744 {
5745 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5746 return false;
5747 }
5748
5749 switch (pname)
5750 {
5751 case GL_TEXTURE_WRAP_S:
5752 case GL_TEXTURE_WRAP_T:
5753 case GL_TEXTURE_WRAP_R:
5754 case GL_TEXTURE_MIN_FILTER:
5755 case GL_TEXTURE_MAG_FILTER:
5756 case GL_TEXTURE_MIN_LOD:
5757 case GL_TEXTURE_MAX_LOD:
5758 case GL_TEXTURE_COMPARE_MODE:
5759 case GL_TEXTURE_COMPARE_FUNC:
5760 break;
5761
Luc Ferron1b1a8642018-01-23 15:12:01 -05005762 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5763 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
5764 {
5765 return false;
5766 }
5767 break;
5768
Jamie Madill9696d072017-08-26 23:19:57 -04005769 case GL_TEXTURE_SRGB_DECODE_EXT:
5770 if (!context->getExtensions().textureSRGBDecode)
5771 {
5772 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5773 return false;
5774 }
5775 break;
5776
5777 default:
5778 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5779 return false;
5780 }
5781
5782 if (length)
5783 {
5784 *length = 1;
5785 }
5786 return true;
5787}
5788
5789bool ValidateGetInternalFormativBase(Context *context,
5790 GLenum target,
5791 GLenum internalformat,
5792 GLenum pname,
5793 GLsizei bufSize,
5794 GLsizei *numParams)
5795{
5796 if (numParams)
5797 {
5798 *numParams = 0;
5799 }
5800
5801 if (context->getClientMajorVersion() < 3)
5802 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005803 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005804 return false;
5805 }
5806
5807 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5808 if (!formatCaps.renderable)
5809 {
5810 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5811 return false;
5812 }
5813
5814 switch (target)
5815 {
5816 case GL_RENDERBUFFER:
5817 break;
5818
5819 case GL_TEXTURE_2D_MULTISAMPLE:
5820 if (context->getClientVersion() < ES_3_1)
5821 {
5822 context->handleError(InvalidOperation()
5823 << "Texture target requires at least OpenGL ES 3.1.");
5824 return false;
5825 }
5826 break;
5827
5828 default:
5829 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5830 return false;
5831 }
5832
5833 if (bufSize < 0)
5834 {
5835 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5836 return false;
5837 }
5838
5839 GLsizei maxWriteParams = 0;
5840 switch (pname)
5841 {
5842 case GL_NUM_SAMPLE_COUNTS:
5843 maxWriteParams = 1;
5844 break;
5845
5846 case GL_SAMPLES:
5847 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5848 break;
5849
5850 default:
5851 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5852 return false;
5853 }
5854
5855 if (numParams)
5856 {
5857 // glGetInternalFormativ will not overflow bufSize
5858 *numParams = std::min(bufSize, maxWriteParams);
5859 }
5860
5861 return true;
5862}
5863
Jamie Madillc29968b2016-01-20 11:17:23 -05005864} // namespace gl