blob: 6bd91379c4eb83f4fcd520874346fb2ccfe8150a [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040012#include "libANGLE/Display.h"
Brandon Jones6cad5662017-06-14 13:25:13 -070013#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Framebuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
Geoff Langa8406172015-07-21 16:53:39 -040016#include "libANGLE/Image.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050017#include "libANGLE/Program.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Query.h"
19#include "libANGLE/Texture.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/TransformFeedback.h"
21#include "libANGLE/VertexArray.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040022#include "libANGLE/formatutils.h"
jchen10a99ed552017-09-22 08:10:32 +080023#include "libANGLE/queryconversions.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040024#include "libANGLE/validationES2.h"
25#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040026
27#include "common/mathutil.h"
28#include "common/utilities.h"
29
Jamie Madille2e406c2016-06-02 13:04:10 -040030using namespace angle;
31
Geoff Lange8ebe7f2013-08-05 15:03:13 -040032namespace gl
33{
Jamie Madill1ca74672015-07-21 15:14:11 -040034namespace
35{
Luc Ferron9dbaeba2018-02-01 07:26:59 -050036bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
37{
38 // List of compressed format that require that the texture size is smaller than or a multiple of
39 // the compressed block size.
40 switch (internalFormat)
41 {
42 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
43 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
44 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
45 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
46 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
47 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
48 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
49 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
50 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
51 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
52 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
53 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
54 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
55 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
56 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
57 return true;
jchen10a99ed552017-09-22 08:10:32 +080058
Luc Ferron9dbaeba2018-02-01 07:26:59 -050059 default:
60 return false;
61 }
62}
63bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
64{
65 // Compressed sub textures have additional formats that requires exact size.
66 // ES 3.1, Section 8.7, Page 171
67 return CompressedTextureFormatRequiresExactSize(internalFormat) ||
68 IsETC2EACFormat(internalFormat);
69}
Jamie Madill5b772312018-03-08 20:28:32 -050070bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex, GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040071{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070072 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040073 const gl::Program *program = state.getProgram();
74
Corentin Wallez327411e2016-12-09 11:09:17 -050075 bool webglCompatibility = context->getExtensions().webglCompatibility;
76
Jamie Madill231c7f52017-04-26 13:45:37 -040077 const VertexArray *vao = state.getVertexArray();
78 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080079 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madilld078c682018-01-02 11:50:24 -050080 for (size_t attributeIndex : vao->getEnabledAttributesMask())
Jamie Madill1ca74672015-07-21 15:14:11 -040081 {
82 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallez672f7f32017-06-15 17:42:17 -040083
84 // No need to range check for disabled attribs.
85 if (!attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040086 {
Corentin Wallezfd456442016-12-21 17:57:00 -050087 continue;
88 }
Jamie Madill1ca74672015-07-21 15:14:11 -040089
Jamie Madill231c7f52017-04-26 13:45:37 -040090 // If we have no buffer, then we either get an error, or there are no more checks to be
91 // done.
Corentin Wallez672f7f32017-06-15 17:42:17 -040092 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
93 gl::Buffer *buffer = binding.getBuffer().get();
Corentin Wallezfd456442016-12-21 17:57:00 -050094 if (!buffer)
95 {
Geoff Langfeb8c682017-02-13 16:07:35 -050096 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -050097 {
98 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050099 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
100 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
101 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
102 // error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700103 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
Corentin Wallezfd456442016-12-21 17:57:00 -0500104 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -0500105 }
Corentin Wallezfd456442016-12-21 17:57:00 -0500106 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -0400107 {
108 // This is an application error that would normally result in a crash,
109 // but we catch it and return an error
Brandon Jonesafa75152017-07-21 13:11:29 -0700110 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
Jamie Madill1ca74672015-07-21 15:14:11 -0400111 return false;
112 }
Corentin Wallezfd456442016-12-21 17:57:00 -0500113 continue;
114 }
115
Corentin Wallez672f7f32017-06-15 17:42:17 -0400116 // This needs to come after the check for client arrays as even unused attributes cannot use
117 // client-side arrays
118 if (!program->isAttribLocationActive(attributeIndex))
119 {
120 continue;
121 }
122
Corentin Wallezfd456442016-12-21 17:57:00 -0500123 // If we're drawing zero vertices, we have enough data.
124 if (vertexCount <= 0 || primcount <= 0)
125 {
126 continue;
127 }
128
129 GLint maxVertexElement = 0;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300130 GLuint divisor = binding.getDivisor();
131 if (divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500132 {
133 maxVertexElement = maxVertex;
134 }
135 else
136 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300137 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500138 }
139
140 // We do manual overflow checks here instead of using safe_math.h because it was
141 // a bottleneck. Thanks to some properties of GL we know inequalities that can
142 // help us make the overflow checks faster.
143
144 // The max possible attribSize is 16 for a vector of 4 32 bit values.
145 constexpr uint64_t kMaxAttribSize = 16;
146 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
147 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
148
149 // We know attribStride is given as a GLsizei which is typedefed to int.
150 // We also know an upper bound for attribSize.
151 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800152 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500153 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
154 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
155
156 // Computing the max offset using uint64_t without attrib.offset is overflow
157 // safe. Note: Last vertex element does not take the full stride!
158 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
159 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
160
161 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800162 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
163 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500164 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700165 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500166 return false;
167 }
168 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
169
170 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
171 // We can return INVALID_OPERATION if our vertex attribute does not have
172 // enough backing data.
173 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
174 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700175 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500176 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400177 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800178
179 if (webglCompatibility && buffer->isBoundForTransformFeedbackAndOtherUse())
180 {
181 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
182 VertexBufferBoundForTransformFeedback);
183 return false;
184 }
Jamie Madill1ca74672015-07-21 15:14:11 -0400185 }
186
187 return true;
188}
189
Jamie Madill5b772312018-03-08 20:28:32 -0500190bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400191{
192 switch (type)
193 {
194 // Types referenced in Table 3.4 of the ES 2.0.25 spec
195 case GL_UNSIGNED_BYTE:
196 case GL_UNSIGNED_SHORT_4_4_4_4:
197 case GL_UNSIGNED_SHORT_5_5_5_1:
198 case GL_UNSIGNED_SHORT_5_6_5:
199 return context->getClientVersion() >= ES_2_0;
200
201 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
202 case GL_BYTE:
203 case GL_INT:
204 case GL_SHORT:
205 case GL_UNSIGNED_INT:
206 case GL_UNSIGNED_INT_10F_11F_11F_REV:
207 case GL_UNSIGNED_INT_24_8:
208 case GL_UNSIGNED_INT_2_10_10_10_REV:
209 case GL_UNSIGNED_INT_5_9_9_9_REV:
210 case GL_UNSIGNED_SHORT:
211 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
212 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
213 return context->getClientVersion() >= ES_3_0;
214
215 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400216 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
217 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400218
219 case GL_HALF_FLOAT:
220 return context->getClientVersion() >= ES_3_0 ||
221 context->getExtensions().textureHalfFloat;
222
223 case GL_HALF_FLOAT_OES:
224 return context->getExtensions().colorBufferHalfFloat;
225
226 default:
227 return false;
228 }
229}
230
Jamie Madill5b772312018-03-08 20:28:32 -0500231bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400232{
233 switch (format)
234 {
235 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
236 case GL_RGBA:
237 case GL_RGB:
238 case GL_ALPHA:
239 return context->getClientVersion() >= ES_2_0;
240
241 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
242 case GL_RG:
243 case GL_RED:
244 case GL_RGBA_INTEGER:
245 case GL_RGB_INTEGER:
246 case GL_RG_INTEGER:
247 case GL_RED_INTEGER:
248 return context->getClientVersion() >= ES_3_0;
249
250 case GL_SRGB_ALPHA_EXT:
251 case GL_SRGB_EXT:
252 return context->getExtensions().sRGB;
253
254 case GL_BGRA_EXT:
255 return context->getExtensions().readFormatBGRA;
256
257 default:
258 return false;
259 }
260}
261
Jamie Madill5b772312018-03-08 20:28:32 -0500262bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400263 GLenum framebufferComponentType,
264 GLenum format,
265 GLenum type)
266{
267 switch (framebufferComponentType)
268 {
269 case GL_UNSIGNED_NORMALIZED:
270 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
271 // ReadPixels with BGRA even if the extension is not present
272 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
273 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
274 type == GL_UNSIGNED_BYTE);
275
276 case GL_SIGNED_NORMALIZED:
277 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
278
279 case GL_INT:
280 return (format == GL_RGBA_INTEGER && type == GL_INT);
281
282 case GL_UNSIGNED_INT:
283 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
284
285 case GL_FLOAT:
286 return (format == GL_RGBA && type == GL_FLOAT);
287
288 default:
289 UNREACHABLE();
290 return false;
291 }
292}
293
Geoff Langc1984ed2016-10-07 12:41:00 -0400294template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400295bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400296{
297 switch (ConvertToGLenum(params[0]))
298 {
299 case GL_CLAMP_TO_EDGE:
300 break;
301
302 case GL_REPEAT:
303 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400304 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400305 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400306 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700307 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400308 return false;
309 }
310 break;
311
312 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700313 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400314 return false;
315 }
316
317 return true;
318}
319
320template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400321bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400322{
323 switch (ConvertToGLenum(params[0]))
324 {
325 case GL_NEAREST:
326 case GL_LINEAR:
327 break;
328
329 case GL_NEAREST_MIPMAP_NEAREST:
330 case GL_LINEAR_MIPMAP_NEAREST:
331 case GL_NEAREST_MIPMAP_LINEAR:
332 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400333 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400334 {
335 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700336 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400337 return false;
338 }
339 break;
340
341 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700342 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400343 return false;
344 }
345
346 return true;
347}
348
349template <typename ParamType>
350bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
351{
352 switch (ConvertToGLenum(params[0]))
353 {
354 case GL_NEAREST:
355 case GL_LINEAR:
356 break;
357
358 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700359 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400360 return false;
361 }
362
363 return true;
364}
365
366template <typename ParamType>
367bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
368{
369 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
370 switch (ConvertToGLenum(params[0]))
371 {
372 case GL_NONE:
373 case GL_COMPARE_REF_TO_TEXTURE:
374 break;
375
376 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700377 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400378 return false;
379 }
380
381 return true;
382}
383
384template <typename ParamType>
385bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
386{
387 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
388 switch (ConvertToGLenum(params[0]))
389 {
390 case GL_LEQUAL:
391 case GL_GEQUAL:
392 case GL_LESS:
393 case GL_GREATER:
394 case GL_EQUAL:
395 case GL_NOTEQUAL:
396 case GL_ALWAYS:
397 case GL_NEVER:
398 break;
399
400 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700401 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400402 return false;
403 }
404
405 return true;
406}
407
408template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700409bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
410{
411 if (!context->getExtensions().textureSRGBDecode)
412 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700413 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700414 return false;
415 }
416
417 switch (ConvertToGLenum(params[0]))
418 {
419 case GL_DECODE_EXT:
420 case GL_SKIP_DECODE_EXT:
421 break;
422
423 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700424 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700425 return false;
426 }
427
428 return true;
429}
430
Luc Ferron1b1a8642018-01-23 15:12:01 -0500431bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
432{
433 if (!context->getExtensions().textureFilterAnisotropic)
434 {
435 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
436 return false;
437 }
438
439 return true;
440}
441
442bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
443{
444 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
445 {
446 return false;
447 }
448
449 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
450
451 if (paramValue < 1 || paramValue > largest)
452 {
453 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
454 return false;
455 }
456
457 return true;
458}
459
Jamie Madill5b772312018-03-08 20:28:32 -0500460bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400461{
462 const Program *program = context->getGLState().getProgram();
463 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
464
Brandon Jonesc405ae72017-12-06 14:15:03 -0800465 if (!ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
466 framebuffer->getDrawBufferTypeMask().to_ulong(),
467 program->getActiveOutputVariables().to_ulong(),
468 framebuffer->getDrawBufferMask().to_ulong()))
Geoff Lange0cff192017-05-30 13:04:56 -0400469 {
Brandon Jones76746f92017-11-22 11:44:41 -0800470 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
471 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400472 }
473
474 return true;
475}
476
Jamie Madill5b772312018-03-08 20:28:32 -0500477bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400478{
Jamie Madillcac94a92017-11-10 10:09:32 -0500479 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400480 const Program *program = context->getGLState().getProgram();
481 const VertexArray *vao = context->getGLState().getVertexArray();
482
Brandon Jonesc405ae72017-12-06 14:15:03 -0800483 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
484 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
485 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
486
487 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
488 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
489 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
490
491 if (!ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
492 program->getAttributesMask().to_ulong(), 0xFFFF))
Geoff Lang9ab5b822017-05-30 16:19:23 -0400493 {
Brandon Jonesc405ae72017-12-06 14:15:03 -0800494 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexShaderTypeMismatch);
495 return false;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400496 }
Geoff Lang9ab5b822017-05-30 16:19:23 -0400497 return true;
498}
499
Jiawei Shaofccebff2018-03-08 13:51:02 +0800500bool IsCompatibleDrawModeWithGeometryShader(GLenum drawMode,
501 GLenum geometryShaderInputPrimitiveType)
502{
503 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
504 switch (geometryShaderInputPrimitiveType)
505 {
506 case GL_POINTS:
507 return drawMode == GL_POINTS;
508 case GL_LINES:
509 return drawMode == GL_LINES || drawMode == GL_LINE_STRIP || drawMode == GL_LINE_LOOP;
510 case GL_LINES_ADJACENCY_EXT:
511 return drawMode == GL_LINES_ADJACENCY_EXT || drawMode == GL_LINE_STRIP_ADJACENCY_EXT;
512 case GL_TRIANGLES:
513 return drawMode == GL_TRIANGLES || drawMode == GL_TRIANGLE_FAN ||
514 drawMode == GL_TRIANGLE_STRIP;
515 case GL_TRIANGLES_ADJACENCY_EXT:
516 return drawMode == GL_TRIANGLES_ADJACENCY_EXT ||
517 drawMode == GL_TRIANGLE_STRIP_ADJACENCY_EXT;
518 default:
519 UNREACHABLE();
520 return false;
521 }
522}
523
Geoff Langf41a7152016-09-19 15:11:17 -0400524} // anonymous namespace
525
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500526bool IsETC2EACFormat(const GLenum format)
527{
528 // ES 3.1, Table 8.19
529 switch (format)
530 {
531 case GL_COMPRESSED_R11_EAC:
532 case GL_COMPRESSED_SIGNED_R11_EAC:
533 case GL_COMPRESSED_RG11_EAC:
534 case GL_COMPRESSED_SIGNED_RG11_EAC:
535 case GL_COMPRESSED_RGB8_ETC2:
536 case GL_COMPRESSED_SRGB8_ETC2:
537 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
538 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
539 case GL_COMPRESSED_RGBA8_ETC2_EAC:
540 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
541 return true;
542
543 default:
544 return false;
545 }
546}
547
Jamie Madill5b772312018-03-08 20:28:32 -0500548bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400549{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800550 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400551 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800552 case TextureType::_2D:
553 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800554 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400555
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800556 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400557 return context->getExtensions().textureRectangle;
558
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800559 case TextureType::_3D:
560 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800561 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500562
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800563 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800564 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400565
He Yunchaoced53ae2016-11-29 15:00:51 +0800566 default:
567 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500568 }
Jamie Madill35d15012013-10-07 10:46:37 -0400569}
570
Jamie Madill5b772312018-03-08 20:28:32 -0500571bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500572{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800573 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500574 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800575 case TextureType::_2D:
576 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500577 return true;
578
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800579 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400580 return context->getExtensions().textureRectangle;
581
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500582 default:
583 return false;
584 }
585}
586
Jamie Madill5b772312018-03-08 20:28:32 -0500587bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500588{
589 switch (target)
590 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800591 case TextureType::_3D:
592 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300593 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500594
595 default:
596 return false;
597 }
598}
599
Ian Ewellbda75592016-04-18 17:25:54 -0400600// Most texture GL calls are not compatible with external textures, so we have a separate validation
601// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500602bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400603{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800604 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400605 (context->getExtensions().eglImageExternal ||
606 context->getExtensions().eglStreamConsumerExternal);
607}
608
Shannon Woods4dfed832014-03-17 20:03:39 -0400609// This function differs from ValidTextureTarget in that the target must be
610// usable as the destination of a 2D operation-- so a cube face is valid, but
611// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400612// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500613bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400614{
615 switch (target)
616 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800617 case TextureTarget::_2D:
618 case TextureTarget::CubeMapNegativeX:
619 case TextureTarget::CubeMapNegativeY:
620 case TextureTarget::CubeMapNegativeZ:
621 case TextureTarget::CubeMapPositiveX:
622 case TextureTarget::CubeMapPositiveY:
623 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800624 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800625 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400626 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800627 default:
628 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500629 }
630}
631
Jamie Madill5b772312018-03-08 20:28:32 -0500632bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -0400633 GLenum mode,
634 GLsizei count,
635 GLenum type,
636 const GLvoid *indices,
637 GLsizei primcount)
638{
639 if (primcount < 0)
640 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700641 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400642 return false;
643 }
644
645 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
646 {
647 return false;
648 }
649
Jamie Madill9fdaa492018-02-16 10:52:11 -0500650 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400651}
652
653bool ValidateDrawArraysInstancedBase(Context *context,
654 GLenum mode,
655 GLint first,
656 GLsizei count,
657 GLsizei primcount)
658{
659 if (primcount < 0)
660 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700661 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400662 return false;
663 }
664
665 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
666 {
667 return false;
668 }
669
Jamie Madill9fdaa492018-02-16 10:52:11 -0500670 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400671}
672
Jamie Madill5b772312018-03-08 20:28:32 -0500673bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400674{
675 // Verify there is at least one active attribute with a divisor of zero
676 const State &state = context->getGLState();
677
678 Program *program = state.getProgram();
679
680 const auto &attribs = state.getVertexArray()->getVertexAttributes();
681 const auto &bindings = state.getVertexArray()->getVertexBindings();
682 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
683 {
684 const VertexAttribute &attrib = attribs[attributeIndex];
685 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300686 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400687 {
688 return true;
689 }
690 }
691
Brandon Jonesafa75152017-07-21 13:11:29 -0700692 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400693 return false;
694}
695
Jamie Madill5b772312018-03-08 20:28:32 -0500696bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500697{
698 switch (target)
699 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800700 case TextureType::_3D:
701 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800702 return true;
703 default:
704 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400705 }
706}
707
Jamie Madill5b772312018-03-08 20:28:32 -0500708bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800709{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800710 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800711 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800712 case TextureType::_2D:
713 case TextureType::_2DArray:
714 case TextureType::_2DMultisample:
715 case TextureType::CubeMap:
716 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800717 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800718 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400719 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800720 default:
721 return false;
722 }
723}
724
Jamie Madill5b772312018-03-08 20:28:32 -0500725bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500726{
He Yunchaoced53ae2016-11-29 15:00:51 +0800727 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
728 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400729 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500730
731 switch (target)
732 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800733 case GL_FRAMEBUFFER:
734 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400735
He Yunchaoced53ae2016-11-29 15:00:51 +0800736 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800737 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400738 return (context->getExtensions().framebufferBlit ||
739 context->getClientMajorVersion() >= 3);
740
He Yunchaoced53ae2016-11-29 15:00:51 +0800741 default:
742 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500743 }
744}
745
Jamie Madill5b772312018-03-08 20:28:32 -0500746bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400747{
Jamie Madillc29968b2016-01-20 11:17:23 -0500748 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400749 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800750 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400751 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800752 case TextureType::_2D:
753 case TextureType::_2DArray:
754 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500755 maxDimension = caps.max2DTextureSize;
756 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800757 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800758 maxDimension = caps.maxCubeMapTextureSize;
759 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800760 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400761 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800762 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800763 maxDimension = caps.max3DTextureSize;
764 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800765 default:
766 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400767 }
768
Brandon Jones6cad5662017-06-14 13:25:13 -0700769 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400770}
771
Jamie Madill5b772312018-03-08 20:28:32 -0500772bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800773 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700774 GLint level,
775 GLsizei width,
776 GLsizei height,
777 GLsizei depth,
778 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400779{
Brandon Jones6cad5662017-06-14 13:25:13 -0700780 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400781 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700782 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400783 return false;
784 }
Austin Kinross08528e12015-10-07 16:24:40 -0700785 // TexSubImage parameters can be NPOT without textureNPOT extension,
786 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500787 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500788 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500789 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400790 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400791 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700792 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400793 return false;
794 }
795
796 if (!ValidMipLevel(context, target, level))
797 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700798 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400799 return false;
800 }
801
802 return true;
803}
804
Geoff Lang966c9402017-04-18 12:38:27 -0400805bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
806{
807 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
808 (size % blockSize == 0);
809}
810
Jamie Madill5b772312018-03-08 20:28:32 -0500811bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500812 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400813 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500814 GLsizei width,
815 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400816{
Geoff Langca271392017-04-05 12:30:00 -0400817 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400818 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400819 {
820 return false;
821 }
822
Geoff Lang966c9402017-04-18 12:38:27 -0400823 if (width < 0 || height < 0)
824 {
825 return false;
826 }
827
828 if (CompressedTextureFormatRequiresExactSize(internalFormat))
829 {
830 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
831 // block size for level 0 but WebGL disallows this.
832 bool smallerThanBlockSizeAllowed =
833 level > 0 || !context->getExtensions().webglCompatibility;
834
835 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
836 smallerThanBlockSizeAllowed) ||
837 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
838 smallerThanBlockSizeAllowed))
839 {
840 return false;
841 }
842 }
843
844 return true;
845}
846
Jamie Madill5b772312018-03-08 20:28:32 -0500847bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400848 GLenum internalFormat,
849 GLint xoffset,
850 GLint yoffset,
851 GLsizei width,
852 GLsizei height,
853 size_t textureWidth,
854 size_t textureHeight)
855{
856 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
857 if (!formatInfo.compressed)
858 {
859 return false;
860 }
861
Geoff Lang44ff5a72017-02-03 15:15:43 -0500862 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400863 {
864 return false;
865 }
866
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500867 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400868 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500869 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400870 yoffset % formatInfo.compressedBlockHeight != 0)
871 {
872 return false;
873 }
874
875 // Allowed to either have data that is a multiple of block size or is smaller than the block
876 // size but fills the entire mip
877 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
878 static_cast<size_t>(width) == textureWidth &&
879 static_cast<size_t>(height) == textureHeight;
880 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
881 (height % formatInfo.compressedBlockHeight) == 0;
882 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400883 {
884 return false;
885 }
886 }
887
Geoff Langd4f180b2013-09-24 13:57:44 -0400888 return true;
889}
890
Jamie Madill5b772312018-03-08 20:28:32 -0500891bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800892 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400893 GLsizei width,
894 GLsizei height,
895 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400896 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400897 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400898 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400899 GLsizei imageSize)
900{
Corentin Wallez336129f2017-10-17 15:55:40 -0400901 gl::Buffer *pixelUnpackBuffer =
902 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400903 if (pixelUnpackBuffer == nullptr && imageSize < 0)
904 {
905 // Checks are not required
906 return true;
907 }
908
909 // ...the data would be unpacked from the buffer object such that the memory reads required
910 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400911 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
912 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400913 const gl::Extents size(width, height, depth);
914 const auto &unpack = context->getGLState().getUnpackState();
915
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800916 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Geoff Langff5b2d52016-09-07 11:32:23 -0400917 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
918 if (endByteOrErr.isError())
919 {
920 context->handleError(endByteOrErr.getError());
921 return false;
922 }
923
924 GLuint endByte = endByteOrErr.getResult();
925
926 if (pixelUnpackBuffer)
927 {
928 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
929 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
930 checkedEndByte += checkedOffset;
931
932 if (!checkedEndByte.IsValid() ||
933 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
934 {
935 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500936 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -0400937 return false;
938 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800939 if (context->getExtensions().webglCompatibility &&
940 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
941 {
942 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
943 PixelUnpackBufferBoundForTransformFeedback);
944 return false;
945 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400946 }
947 else
948 {
949 ASSERT(imageSize >= 0);
950 if (pixels == nullptr && imageSize != 0)
951 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500952 context->handleError(InvalidOperation()
953 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400954 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400955 }
956
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400957 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400958 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500959 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400960 return false;
961 }
962 }
963
964 return true;
965}
966
Geoff Lang37dde692014-01-31 16:34:54 -0500967bool ValidQueryType(const Context *context, GLenum queryType)
968{
He Yunchaoced53ae2016-11-29 15:00:51 +0800969 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
970 "GL extension enums not equal.");
971 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
972 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -0500973
974 switch (queryType)
975 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800976 case GL_ANY_SAMPLES_PASSED:
977 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400978 return context->getClientMajorVersion() >= 3 ||
979 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +0800980 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
981 return (context->getClientMajorVersion() >= 3);
982 case GL_TIME_ELAPSED_EXT:
983 return context->getExtensions().disjointTimerQuery;
984 case GL_COMMANDS_COMPLETED_CHROMIUM:
985 return context->getExtensions().syncQuery;
Jiawei Shaod2fa07e2018-03-15 09:20:25 +0800986 case GL_PRIMITIVES_GENERATED_EXT:
987 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +0800988 default:
989 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500990 }
991}
992
Jamie Madill5b772312018-03-08 20:28:32 -0500993bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400994 GLenum type,
995 GLboolean normalized,
996 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400997 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400998 bool pureInteger)
999{
1000 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001001 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1002 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1003 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1004 // parameter exceeds 255.
1005 constexpr GLsizei kMaxWebGLStride = 255;
1006 if (stride > kMaxWebGLStride)
1007 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001008 context->handleError(InvalidValue()
1009 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001010 return false;
1011 }
1012
1013 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1014 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1015 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1016 // or an INVALID_OPERATION error is generated.
1017 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1018 size_t typeSize = GetVertexFormatTypeSize(internalType);
1019
1020 ASSERT(isPow2(typeSize) && typeSize > 0);
1021 size_t sizeMask = (typeSize - 1);
1022 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1023 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001024 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001025 return false;
1026 }
1027
1028 if ((stride & sizeMask) != 0)
1029 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001030 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001031 return false;
1032 }
1033
1034 return true;
1035}
1036
Jamie Madill5b772312018-03-08 20:28:32 -05001037Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001038{
He Yunchaoced53ae2016-11-29 15:00:51 +08001039 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1040 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1041 // or program object and INVALID_OPERATION if the provided name identifies an object
1042 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001043
Dian Xiang769769a2015-09-09 15:20:08 -07001044 Program *validProgram = context->getProgram(id);
1045
1046 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001047 {
Dian Xiang769769a2015-09-09 15:20:08 -07001048 if (context->getShader(id))
1049 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001050 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001051 }
1052 else
1053 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001054 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001055 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001056 }
Dian Xiang769769a2015-09-09 15:20:08 -07001057
1058 return validProgram;
1059}
1060
Jamie Madill5b772312018-03-08 20:28:32 -05001061Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001062{
1063 // See ValidProgram for spec details.
1064
1065 Shader *validShader = context->getShader(id);
1066
1067 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001068 {
Dian Xiang769769a2015-09-09 15:20:08 -07001069 if (context->getProgram(id))
1070 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001071 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001072 }
1073 else
1074 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001075 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001076 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001077 }
Dian Xiang769769a2015-09-09 15:20:08 -07001078
1079 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001080}
1081
Geoff Langb1196682014-07-23 13:47:29 -04001082bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001083{
Geoff Langfa125c92017-10-24 13:01:46 -04001084 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001085 {
Geoff Langfa125c92017-10-24 13:01:46 -04001086 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1087 {
1088 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1089 return false;
1090 }
Jamie Madillb4472272014-07-03 10:38:55 -04001091
Geoff Langfa125c92017-10-24 13:01:46 -04001092 // Color attachment 0 is validated below because it is always valid
1093 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001094 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001095 {
Geoff Langfa125c92017-10-24 13:01:46 -04001096 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001097 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001098 }
1099 }
1100 else
1101 {
1102 switch (attachment)
1103 {
Geoff Langfa125c92017-10-24 13:01:46 -04001104 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001105 case GL_DEPTH_ATTACHMENT:
1106 case GL_STENCIL_ATTACHMENT:
1107 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001108
He Yunchaoced53ae2016-11-29 15:00:51 +08001109 case GL_DEPTH_STENCIL_ATTACHMENT:
1110 if (!context->getExtensions().webglCompatibility &&
1111 context->getClientMajorVersion() < 3)
1112 {
Geoff Langfa125c92017-10-24 13:01:46 -04001113 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001114 return false;
1115 }
1116 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001117
He Yunchaoced53ae2016-11-29 15:00:51 +08001118 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001119 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001120 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001121 }
1122 }
1123
1124 return true;
1125}
1126
Jamie Madill5b772312018-03-08 20:28:32 -05001127bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001128 GLenum target,
1129 GLsizei samples,
1130 GLenum internalformat,
1131 GLsizei width,
1132 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001133{
1134 switch (target)
1135 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001136 case GL_RENDERBUFFER:
1137 break;
1138 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001139 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001140 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001141 }
1142
1143 if (width < 0 || height < 0 || samples < 0)
1144 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001145 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001146 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001147 }
1148
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001149 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1150 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1151
1152 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001153 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001154 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001155 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001156 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001157 }
1158
1159 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1160 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
Corentin Walleze0902642014-11-04 12:32:15 -08001161 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001162 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1163 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001164 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001165 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001166 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001167 }
1168
Geoff Langaae65a42014-05-26 12:43:44 -04001169 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001170 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001171 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001172 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001173 }
1174
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001175 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001176 if (handle == 0)
1177 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001178 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001179 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001180 }
1181
1182 return true;
1183}
1184
He Yunchaoced53ae2016-11-29 15:00:51 +08001185bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1186 GLenum target,
1187 GLenum attachment,
1188 GLenum renderbuffertarget,
1189 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001190{
Geoff Lange8afa902017-09-27 15:00:43 -04001191 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001193 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001194 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001195 }
1196
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001197 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001198
Jamie Madill84115c92015-04-23 15:00:07 -04001199 ASSERT(framebuffer);
1200 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001201 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001202 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001203 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001204 }
1205
Jamie Madillb4472272014-07-03 10:38:55 -04001206 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001207 {
Jamie Madillb4472272014-07-03 10:38:55 -04001208 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001209 }
1210
Jamie Madillab9d82c2014-01-21 16:38:14 -05001211 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1212 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1213 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1214 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1215 if (renderbuffer != 0)
1216 {
1217 if (!context->getRenderbuffer(renderbuffer))
1218 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001219 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001220 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001221 }
1222 }
1223
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001224 return true;
1225}
1226
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001227bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001228 GLint srcX0,
1229 GLint srcY0,
1230 GLint srcX1,
1231 GLint srcY1,
1232 GLint dstX0,
1233 GLint dstY0,
1234 GLint dstX1,
1235 GLint dstY1,
1236 GLbitfield mask,
1237 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001238{
1239 switch (filter)
1240 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001241 case GL_NEAREST:
1242 break;
1243 case GL_LINEAR:
1244 break;
1245 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001246 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001247 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001248 }
1249
1250 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1251 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001252 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001253 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001254 }
1255
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001256 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1257 // color buffer, leaving only nearest being unfiltered from above
1258 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1259 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001260 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001261 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001262 }
1263
Jamie Madill51f40ec2016-06-15 14:06:00 -04001264 const auto &glState = context->getGLState();
1265 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1266 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001267
1268 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001269 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001270 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001271 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001272 }
1273
Jamie Madille98b1b52018-03-08 09:47:23 -05001274 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madill48faf802014-11-06 15:27:22 -05001275 {
Jamie Madill48faf802014-11-06 15:27:22 -05001276 return false;
1277 }
1278
Jamie Madille98b1b52018-03-08 09:47:23 -05001279 if (!ValidateFramebufferComplete(context, drawFramebuffer, true))
Jamie Madill48faf802014-11-06 15:27:22 -05001280 {
Jamie Madill48faf802014-11-06 15:27:22 -05001281 return false;
1282 }
1283
Qin Jiajiaaef92162018-02-27 13:51:44 +08001284 if (readFramebuffer->id() == drawFramebuffer->id())
1285 {
1286 context->handleError(InvalidOperation());
1287 return false;
1288 }
1289
Jamie Madille98b1b52018-03-08 09:47:23 -05001290 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001291 {
Geoff Langb1196682014-07-23 13:47:29 -04001292 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001293 }
1294
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001295 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1296
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001297 if (mask & GL_COLOR_BUFFER_BIT)
1298 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001299 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001300 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001301
He Yunchao66a41a22016-12-15 16:45:05 +08001302 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001303 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001304 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001305
Geoff Langa15472a2015-08-11 11:48:03 -04001306 for (size_t drawbufferIdx = 0;
1307 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001308 {
Geoff Langa15472a2015-08-11 11:48:03 -04001309 const FramebufferAttachment *attachment =
1310 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1311 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001312 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001313 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001314
Geoff Langb2f3d052013-08-13 12:49:27 -04001315 // The GL ES 3.0.2 spec (pg 193) states that:
1316 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001317 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1318 // as well
1319 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1320 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001321 // Changes with EXT_color_buffer_float:
1322 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001323 GLenum readComponentType = readFormat.info->componentType;
1324 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001325 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001326 readComponentType == GL_SIGNED_NORMALIZED);
1327 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1328 drawComponentType == GL_SIGNED_NORMALIZED);
1329
1330 if (extensions.colorBufferFloat)
1331 {
1332 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1333 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1334
1335 if (readFixedOrFloat != drawFixedOrFloat)
1336 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001337 context->handleError(InvalidOperation()
1338 << "If the read buffer contains fixed-point or "
1339 "floating-point values, the draw buffer must "
1340 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001341 return false;
1342 }
1343 }
1344 else if (readFixedPoint != drawFixedPoint)
1345 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001346 context->handleError(InvalidOperation()
1347 << "If the read buffer contains fixed-point values, "
1348 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001349 return false;
1350 }
1351
1352 if (readComponentType == GL_UNSIGNED_INT &&
1353 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001354 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001355 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001356 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001357 }
1358
Jamie Madill6163c752015-12-07 16:32:59 -05001359 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001360 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001361 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001362 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001363 }
1364
Jamie Madilla3944d42016-07-22 22:13:26 -04001365 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001366 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001367 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001368 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001369 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001370 }
Geoff Lange4915782017-04-12 15:19:07 -04001371
1372 if (context->getExtensions().webglCompatibility &&
1373 *readColorBuffer == *attachment)
1374 {
1375 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001376 InvalidOperation()
1377 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001378 return false;
1379 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001380 }
1381 }
1382
Jamie Madilla3944d42016-07-22 22:13:26 -04001383 if ((readFormat.info->componentType == GL_INT ||
1384 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1385 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001386 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001387 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001388 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001389 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001390 }
He Yunchao66a41a22016-12-15 16:45:05 +08001391 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1392 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1393 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1394 // situation is an application error that would lead to a crash in ANGLE.
1395 else if (drawFramebuffer->hasEnabledDrawBuffer())
1396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001397 context->handleError(
1398 InvalidOperation()
1399 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001400 return false;
1401 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001402 }
1403
He Yunchaoced53ae2016-11-29 15:00:51 +08001404 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001405 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1406 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001407 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001408 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001409 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001410 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001411 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001412 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001413 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001414
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001415 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001416 {
Kenneth Russell69382852017-07-21 16:38:44 -04001417 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001418 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001419 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001420 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001421 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001422
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001423 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001424 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001425 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001426 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001427 }
Geoff Lange4915782017-04-12 15:19:07 -04001428
1429 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1430 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001431 context->handleError(
1432 InvalidOperation()
1433 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001434 return false;
1435 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001436 }
He Yunchao66a41a22016-12-15 16:45:05 +08001437 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1438 else if (drawBuffer)
1439 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001440 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1441 "depth/stencil attachment of a "
1442 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001443 return false;
1444 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001445 }
1446 }
1447
Martin Radeva3ed4572017-07-27 18:29:37 +03001448 // ANGLE_multiview, Revision 1:
1449 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1450 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1451 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1452 {
1453 context->handleError(InvalidFramebufferOperation()
1454 << "Attempt to read from a multi-view framebuffer.");
1455 return false;
1456 }
1457 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1458 {
1459 context->handleError(InvalidFramebufferOperation()
1460 << "Attempt to write to a multi-view framebuffer.");
1461 return false;
1462 }
1463
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001464 return true;
1465}
1466
Jamie Madill4928b7c2017-06-20 12:57:39 -04001467bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001468 GLint x,
1469 GLint y,
1470 GLsizei width,
1471 GLsizei height,
1472 GLenum format,
1473 GLenum type,
1474 GLsizei bufSize,
1475 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001476 GLsizei *columns,
1477 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001478 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001479{
1480 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001481 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001482 return false;
1483 }
1484
Geoff Lang62fce5b2016-09-30 10:46:35 -04001485 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001486 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001487 {
Geoff Langb1196682014-07-23 13:47:29 -04001488 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001489 }
1490
Geoff Lang62fce5b2016-09-30 10:46:35 -04001491 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001492 {
Geoff Langb1196682014-07-23 13:47:29 -04001493 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001494 }
1495
Jamie Madillc29968b2016-01-20 11:17:23 -05001496 return true;
1497}
1498
1499bool ValidateReadnPixelsEXT(Context *context,
1500 GLint x,
1501 GLint y,
1502 GLsizei width,
1503 GLsizei height,
1504 GLenum format,
1505 GLenum type,
1506 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001507 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001508{
1509 if (bufSize < 0)
1510 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001511 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001512 return false;
1513 }
1514
Geoff Lang62fce5b2016-09-30 10:46:35 -04001515 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001516 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001517}
Jamie Madill26e91952014-03-05 15:01:27 -05001518
Jamie Madill4928b7c2017-06-20 12:57:39 -04001519bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001520 GLint x,
1521 GLint y,
1522 GLsizei width,
1523 GLsizei height,
1524 GLenum format,
1525 GLenum type,
1526 GLsizei bufSize,
1527 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001528 GLsizei *columns,
1529 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001530 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001531{
1532 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001533 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001534 return false;
1535 }
1536
Geoff Lange93daba2017-03-30 13:54:40 -04001537 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1538 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001539 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001540 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001541 }
1542
Geoff Lang62fce5b2016-09-30 10:46:35 -04001543 if (!ValidateRobustBufferSize(context, bufSize, *length))
1544 {
1545 return false;
1546 }
1547
1548 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001549}
1550
Jamie Madillf0e04492017-08-26 15:28:42 -04001551bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001552{
1553 if (!context->getExtensions().occlusionQueryBoolean &&
1554 !context->getExtensions().disjointTimerQuery)
1555 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001556 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001557 return false;
1558 }
1559
Olli Etuaho41997e72016-03-10 13:38:39 +02001560 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001561}
1562
Jamie Madillf0e04492017-08-26 15:28:42 -04001563bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001564{
1565 if (!context->getExtensions().occlusionQueryBoolean &&
1566 !context->getExtensions().disjointTimerQuery)
1567 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001568 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001569 return false;
1570 }
1571
Olli Etuaho41997e72016-03-10 13:38:39 +02001572 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001573}
1574
Jamie Madillf0e04492017-08-26 15:28:42 -04001575bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1576{
1577 if (!context->getExtensions().occlusionQueryBoolean &&
1578 !context->getExtensions().disjointTimerQuery)
1579 {
1580 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1581 return false;
1582 }
1583
1584 return true;
1585}
1586
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001587bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001588{
1589 if (!ValidQueryType(context, target))
1590 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001591 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001592 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001593 }
1594
1595 if (id == 0)
1596 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001597 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001598 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001599 }
1600
1601 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1602 // of zero, if the active query object name for <target> is non-zero (for the
1603 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1604 // the active query for either target is non-zero), if <id> is the name of an
1605 // existing query object whose type does not match <target>, or if <id> is the
1606 // active query object name for any query type, the error INVALID_OPERATION is
1607 // generated.
1608
1609 // Ensure no other queries are active
1610 // NOTE: If other queries than occlusion are supported, we will need to check
1611 // separately that:
1612 // a) The query ID passed is not the current active query for any target/type
1613 // b) There are no active queries for the requested target (and in the case
1614 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1615 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001616
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001617 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001618 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001619 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001620 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001621 }
1622
1623 Query *queryObject = context->getQuery(id, true, target);
1624
1625 // check that name was obtained with glGenQueries
1626 if (!queryObject)
1627 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001628 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001629 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001630 }
1631
1632 // check for type mismatch
1633 if (queryObject->getType() != target)
1634 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001635 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001636 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001637 }
1638
1639 return true;
1640}
1641
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001642bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1643{
1644 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001645 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001646 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001647 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001648 return false;
1649 }
1650
1651 return ValidateBeginQueryBase(context, target, id);
1652}
1653
1654bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001655{
1656 if (!ValidQueryType(context, target))
1657 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001658 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001659 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001660 }
1661
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001662 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001663
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001664 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001665 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001666 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001667 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001668 }
1669
Jamie Madill45c785d2014-05-13 14:09:34 -04001670 return true;
1671}
1672
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001673bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1674{
1675 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001676 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001677 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001678 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001679 return false;
1680 }
1681
1682 return ValidateEndQueryBase(context, target);
1683}
1684
1685bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1686{
1687 if (!context->getExtensions().disjointTimerQuery)
1688 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001689 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001690 return false;
1691 }
1692
1693 if (target != GL_TIMESTAMP_EXT)
1694 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001695 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001696 return false;
1697 }
1698
1699 Query *queryObject = context->getQuery(id, true, target);
1700 if (queryObject == nullptr)
1701 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001702 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001703 return false;
1704 }
1705
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001706 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001707 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001708 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001709 return false;
1710 }
1711
1712 return true;
1713}
1714
Geoff Lang2186c382016-10-14 10:54:54 -04001715bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001716{
Geoff Lang2186c382016-10-14 10:54:54 -04001717 if (numParams)
1718 {
1719 *numParams = 0;
1720 }
1721
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001722 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1723 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001724 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001725 return false;
1726 }
1727
1728 switch (pname)
1729 {
1730 case GL_CURRENT_QUERY_EXT:
1731 if (target == GL_TIMESTAMP_EXT)
1732 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001733 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001734 return false;
1735 }
1736 break;
1737 case GL_QUERY_COUNTER_BITS_EXT:
1738 if (!context->getExtensions().disjointTimerQuery ||
1739 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1740 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001741 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001742 return false;
1743 }
1744 break;
1745 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001746 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001747 return false;
1748 }
1749
Geoff Lang2186c382016-10-14 10:54:54 -04001750 if (numParams)
1751 {
1752 // All queries return only one value
1753 *numParams = 1;
1754 }
1755
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001756 return true;
1757}
1758
1759bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1760{
1761 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001762 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001763 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001764 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001765 return false;
1766 }
1767
Geoff Lang2186c382016-10-14 10:54:54 -04001768 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001769}
1770
Geoff Lang2186c382016-10-14 10:54:54 -04001771bool ValidateGetQueryivRobustANGLE(Context *context,
1772 GLenum target,
1773 GLenum pname,
1774 GLsizei bufSize,
1775 GLsizei *length,
1776 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001777{
Geoff Lang2186c382016-10-14 10:54:54 -04001778 if (!ValidateRobustEntryPoint(context, bufSize))
1779 {
1780 return false;
1781 }
1782
1783 if (!ValidateGetQueryivBase(context, target, pname, length))
1784 {
1785 return false;
1786 }
1787
1788 if (!ValidateRobustBufferSize(context, bufSize, *length))
1789 {
1790 return false;
1791 }
1792
1793 return true;
1794}
1795
1796bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1797{
1798 if (numParams)
1799 {
1800 *numParams = 0;
1801 }
1802
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001803 Query *queryObject = context->getQuery(id, false, GL_NONE);
1804
1805 if (!queryObject)
1806 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001807 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001808 return false;
1809 }
1810
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001811 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001812 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001813 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001814 return false;
1815 }
1816
1817 switch (pname)
1818 {
1819 case GL_QUERY_RESULT_EXT:
1820 case GL_QUERY_RESULT_AVAILABLE_EXT:
1821 break;
1822
1823 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001824 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001825 return false;
1826 }
1827
Geoff Lang2186c382016-10-14 10:54:54 -04001828 if (numParams)
1829 {
1830 *numParams = 1;
1831 }
1832
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001833 return true;
1834}
1835
1836bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1837{
1838 if (!context->getExtensions().disjointTimerQuery)
1839 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001840 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001841 return false;
1842 }
Geoff Lang2186c382016-10-14 10:54:54 -04001843 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1844}
1845
1846bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1847 GLuint id,
1848 GLenum pname,
1849 GLsizei bufSize,
1850 GLsizei *length,
1851 GLint *params)
1852{
1853 if (!context->getExtensions().disjointTimerQuery)
1854 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001855 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001856 return false;
1857 }
1858
1859 if (!ValidateRobustEntryPoint(context, bufSize))
1860 {
1861 return false;
1862 }
1863
1864 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1865 {
1866 return false;
1867 }
1868
1869 if (!ValidateRobustBufferSize(context, bufSize, *length))
1870 {
1871 return false;
1872 }
1873
1874 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001875}
1876
1877bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1878{
1879 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001880 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001881 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001882 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001883 return false;
1884 }
Geoff Lang2186c382016-10-14 10:54:54 -04001885 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1886}
1887
1888bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1889 GLuint id,
1890 GLenum pname,
1891 GLsizei bufSize,
1892 GLsizei *length,
1893 GLuint *params)
1894{
1895 if (!context->getExtensions().disjointTimerQuery &&
1896 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1897 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001898 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001899 return false;
1900 }
1901
1902 if (!ValidateRobustEntryPoint(context, bufSize))
1903 {
1904 return false;
1905 }
1906
1907 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1908 {
1909 return false;
1910 }
1911
1912 if (!ValidateRobustBufferSize(context, bufSize, *length))
1913 {
1914 return false;
1915 }
1916
1917 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001918}
1919
1920bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1921{
1922 if (!context->getExtensions().disjointTimerQuery)
1923 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001924 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001925 return false;
1926 }
Geoff Lang2186c382016-10-14 10:54:54 -04001927 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1928}
1929
1930bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1931 GLuint id,
1932 GLenum pname,
1933 GLsizei bufSize,
1934 GLsizei *length,
1935 GLint64 *params)
1936{
1937 if (!context->getExtensions().disjointTimerQuery)
1938 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001939 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001940 return false;
1941 }
1942
1943 if (!ValidateRobustEntryPoint(context, bufSize))
1944 {
1945 return false;
1946 }
1947
1948 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1949 {
1950 return false;
1951 }
1952
1953 if (!ValidateRobustBufferSize(context, bufSize, *length))
1954 {
1955 return false;
1956 }
1957
1958 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001959}
1960
1961bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1962{
1963 if (!context->getExtensions().disjointTimerQuery)
1964 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001965 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001966 return false;
1967 }
Geoff Lang2186c382016-10-14 10:54:54 -04001968 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1969}
1970
1971bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1972 GLuint id,
1973 GLenum pname,
1974 GLsizei bufSize,
1975 GLsizei *length,
1976 GLuint64 *params)
1977{
1978 if (!context->getExtensions().disjointTimerQuery)
1979 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001980 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001981 return false;
1982 }
1983
1984 if (!ValidateRobustEntryPoint(context, bufSize))
1985 {
1986 return false;
1987 }
1988
1989 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1990 {
1991 return false;
1992 }
1993
1994 if (!ValidateRobustBufferSize(context, bufSize, *length))
1995 {
1996 return false;
1997 }
1998
1999 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002000}
2001
Jamie Madill5b772312018-03-08 20:28:32 -05002002bool ValidateUniformCommonBase(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002003 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002004 GLint location,
2005 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002006 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002007{
Jiajia Qin5451d532017-11-16 17:16:34 +08002008 // TODO(Jiajia): Add image uniform check in future.
2009 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002010 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002011 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002012 return false;
2013 }
2014
Jiajia Qin5451d532017-11-16 17:16:34 +08002015 if (!program)
2016 {
2017 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2018 return false;
2019 }
2020
2021 if (!program->isLinked())
2022 {
2023 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2024 return false;
2025 }
2026
2027 if (location == -1)
2028 {
2029 // Silently ignore the uniform command
2030 return false;
2031 }
2032
2033 const auto &uniformLocations = program->getUniformLocations();
2034 size_t castedLocation = static_cast<size_t>(location);
2035 if (castedLocation >= uniformLocations.size())
2036 {
2037 context->handleError(InvalidOperation() << "Invalid uniform location");
2038 return false;
2039 }
2040
2041 const auto &uniformLocation = uniformLocations[castedLocation];
2042 if (uniformLocation.ignored)
2043 {
2044 // Silently ignore the uniform command
2045 return false;
2046 }
2047
2048 if (!uniformLocation.used())
2049 {
2050 context->handleError(InvalidOperation());
2051 return false;
2052 }
2053
2054 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2055
2056 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2057 if (!uniform.isArray() && count > 1)
2058 {
2059 context->handleError(InvalidOperation());
2060 return false;
2061 }
2062
2063 *uniformOut = &uniform;
2064 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002065}
2066
Jamie Madill5b772312018-03-08 20:28:32 -05002067bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002068 GLenum uniformType,
2069 GLsizei count,
2070 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002071{
Jiajia Qin5451d532017-11-16 17:16:34 +08002072 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2073 // It is compatible with INT or BOOL.
2074 // Do these cheap tests first, for a little extra speed.
2075 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002076 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002077 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002078 }
2079
Jiajia Qin5451d532017-11-16 17:16:34 +08002080 if (IsSamplerType(uniformType))
2081 {
2082 // Check that the values are in range.
2083 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2084 for (GLsizei i = 0; i < count; ++i)
2085 {
2086 if (value[i] < 0 || value[i] >= max)
2087 {
2088 context->handleError(InvalidValue() << "sampler uniform value out of range");
2089 return false;
2090 }
2091 }
2092 return true;
2093 }
2094
2095 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2096 return false;
2097}
2098
Jamie Madill5b772312018-03-08 20:28:32 -05002099bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002100{
2101 // Check that the value type is compatible with uniform type.
2102 // Do the cheaper test first, for a little extra speed.
2103 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2104 {
2105 return true;
2106 }
2107
2108 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2109 return false;
2110}
2111
Jamie Madill5b772312018-03-08 20:28:32 -05002112bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002113{
2114 // Check that the value type is compatible with uniform type.
2115 if (valueType == uniformType)
2116 {
2117 return true;
2118 }
2119
2120 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2121 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002122}
2123
Jamie Madill5b772312018-03-08 20:28:32 -05002124bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002125{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002126 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002127 gl::Program *programObject = context->getGLState().getProgram();
2128 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2129 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002130}
2131
Jamie Madill5b772312018-03-08 20:28:32 -05002132bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002133{
2134 const LinkedUniform *uniform = nullptr;
2135 gl::Program *programObject = context->getGLState().getProgram();
2136 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2137 ValidateUniform1ivValue(context, uniform->type, count, value);
2138}
2139
Jamie Madill5b772312018-03-08 20:28:32 -05002140bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002141 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002142 GLint location,
2143 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002144 GLboolean transpose)
2145{
Geoff Lang92019432017-11-20 13:09:34 -05002146 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002147 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002148 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002149 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002150 }
2151
Jamie Madill62d31cb2015-09-11 13:25:51 -04002152 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002153 gl::Program *programObject = context->getGLState().getProgram();
2154 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2155 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002156}
2157
Jamie Madill5b772312018-03-08 20:28:32 -05002158bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002159{
2160 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2161 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002162 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002163 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002164 }
2165
Jamie Madill0af26e12015-03-05 19:54:33 -05002166 const Caps &caps = context->getCaps();
2167
Jamie Madill893ab082014-05-16 16:56:10 -04002168 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2169 {
2170 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2171
Jamie Madill0af26e12015-03-05 19:54:33 -05002172 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002173 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002174 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002175 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002176 }
2177 }
2178
2179 switch (pname)
2180 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002181 case GL_TEXTURE_BINDING_2D:
2182 case GL_TEXTURE_BINDING_CUBE_MAP:
2183 case GL_TEXTURE_BINDING_3D:
2184 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002185 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002186 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002187 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2188 if (!context->getExtensions().textureRectangle)
2189 {
2190 context->handleError(InvalidEnum()
2191 << "ANGLE_texture_rectangle extension not present");
2192 return false;
2193 }
2194 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002195 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2196 if (!context->getExtensions().eglStreamConsumerExternal &&
2197 !context->getExtensions().eglImageExternal)
2198 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002199 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2200 "nor GL_OES_EGL_image_external "
2201 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002202 return false;
2203 }
2204 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002205
He Yunchaoced53ae2016-11-29 15:00:51 +08002206 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2207 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002208 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002209 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2210 ASSERT(readFramebuffer);
2211
2212 if (!ValidateFramebufferComplete(context, readFramebuffer, false))
Jamie Madill893ab082014-05-16 16:56:10 -04002213 {
Geoff Langb1196682014-07-23 13:47:29 -04002214 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002215 }
2216
Jamie Madille98b1b52018-03-08 09:47:23 -05002217 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002218 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002219 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002220 return false;
2221 }
2222
Jamie Madille98b1b52018-03-08 09:47:23 -05002223 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002224 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002225 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002226 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002227 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002228 }
2229 }
2230 break;
2231
He Yunchaoced53ae2016-11-29 15:00:51 +08002232 default:
2233 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002234 }
2235
2236 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002237 if (*numParams == 0)
2238 {
2239 return false;
2240 }
2241
2242 return true;
2243}
2244
Jamie Madill5b772312018-03-08 20:28:32 -05002245bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002246 GLenum pname,
2247 GLsizei bufSize,
2248 GLenum *nativeType,
2249 unsigned int *numParams)
2250{
2251 if (!ValidateRobustEntryPoint(context, bufSize))
2252 {
2253 return false;
2254 }
2255
2256 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2257 {
2258 return false;
2259 }
2260
2261 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002262 {
2263 return false;
2264 }
2265
2266 return true;
2267}
2268
Jamie Madill5b772312018-03-08 20:28:32 -05002269bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002270 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002271 GLint level,
2272 GLenum internalformat,
2273 bool isSubImage,
2274 GLint xoffset,
2275 GLint yoffset,
2276 GLint zoffset,
2277 GLint x,
2278 GLint y,
2279 GLsizei width,
2280 GLsizei height,
2281 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002282 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002283{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002284 TextureType texType = TextureTargetToType(target);
2285
Brandon Jones6cad5662017-06-14 13:25:13 -07002286 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002287 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002288 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2289 return false;
2290 }
2291
2292 if (width < 0 || height < 0)
2293 {
2294 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002295 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002296 }
2297
He Yunchaoced53ae2016-11-29 15:00:51 +08002298 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2299 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002300 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002301 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002302 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002303 }
2304
2305 if (border != 0)
2306 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002307 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002308 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002309 }
2310
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002311 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002312 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002313 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002314 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002315 }
2316
Jamie Madille98b1b52018-03-08 09:47:23 -05002317 const gl::State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002318 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madille98b1b52018-03-08 09:47:23 -05002319 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madill560a8d82014-05-21 13:06:20 -04002320 {
Geoff Langb1196682014-07-23 13:47:29 -04002321 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002322 }
2323
Jamie Madille98b1b52018-03-08 09:47:23 -05002324 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002325 {
Geoff Langb1196682014-07-23 13:47:29 -04002326 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002327 }
2328
Martin Radev138064f2016-07-15 12:03:41 +03002329 if (readFramebuffer->getReadBufferState() == GL_NONE)
2330 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002331 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002332 return false;
2333 }
2334
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002335 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2336 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002337 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002338 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002339 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2340 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002341 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002342 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002343 return false;
2344 }
2345
Martin Radev04e2c3b2017-07-27 16:54:35 +03002346 // ANGLE_multiview spec, Revision 1:
2347 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2348 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2349 // is not NONE.
2350 if (source->getMultiviewLayout() != GL_NONE)
2351 {
2352 context->handleError(InvalidFramebufferOperation()
2353 << "The active read framebuffer object has multiview attachments.");
2354 return false;
2355 }
2356
Geoff Langaae65a42014-05-26 12:43:44 -04002357 const gl::Caps &caps = context->getCaps();
2358
Geoff Langaae65a42014-05-26 12:43:44 -04002359 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002360 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002361 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002362 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002363 maxDimension = caps.max2DTextureSize;
2364 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002365
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002366 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002367 maxDimension = caps.maxCubeMapTextureSize;
2368 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002369
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002370 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002371 maxDimension = caps.maxRectangleTextureSize;
2372 break;
2373
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002374 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002375 maxDimension = caps.max2DTextureSize;
2376 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002377
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002378 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002379 maxDimension = caps.max3DTextureSize;
2380 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002381
He Yunchaoced53ae2016-11-29 15:00:51 +08002382 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002383 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002384 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002385 }
2386
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002387 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002388 if (!texture)
2389 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002390 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002391 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002392 }
2393
Geoff Lang69cce582015-09-17 13:20:36 -04002394 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002395 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002396 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002397 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002398 }
2399
Geoff Langca271392017-04-05 12:30:00 -04002400 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002401 isSubImage ? *texture->getFormat(target, level).info
2402 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002403
Geoff Lang966c9402017-04-18 12:38:27 -04002404 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002406 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002407 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002408 }
2409
2410 if (isSubImage)
2411 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002412 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2413 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2414 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002415 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002416 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002417 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002418 }
2419 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002420 else
2421 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002422 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002423 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002424 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002425 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002426 }
2427
Geoff Langeb66a6e2016-10-31 13:06:12 -04002428 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002429 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002430 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002431 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002432 }
2433
2434 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002435 if (static_cast<int>(width) > maxLevelDimension ||
2436 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002437 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002438 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002439 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002440 }
2441 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002442
Jamie Madill0c8abca2016-07-22 20:21:26 -04002443 if (textureFormatOut)
2444 {
2445 *textureFormatOut = texture->getFormat(target, level);
2446 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002447
2448 // Detect texture copying feedback loops for WebGL.
2449 if (context->getExtensions().webglCompatibility)
2450 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002451 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002452 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002453 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002454 return false;
2455 }
2456 }
2457
Jamie Madill560a8d82014-05-21 13:06:20 -04002458 return true;
2459}
2460
Jamie Madill5b772312018-03-08 20:28:32 -05002461bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002462{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002463 const Extensions &extensions = context->getExtensions();
2464
Jamie Madill1aeb1312014-06-20 13:21:25 -04002465 switch (mode)
2466 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002467 case GL_POINTS:
2468 case GL_LINES:
2469 case GL_LINE_LOOP:
2470 case GL_LINE_STRIP:
2471 case GL_TRIANGLES:
2472 case GL_TRIANGLE_STRIP:
2473 case GL_TRIANGLE_FAN:
2474 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002475
2476 case GL_LINES_ADJACENCY_EXT:
2477 case GL_LINE_STRIP_ADJACENCY_EXT:
2478 case GL_TRIANGLES_ADJACENCY_EXT:
2479 case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
2480 if (!extensions.geometryShader)
2481 {
2482 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2483 return false;
2484 }
2485 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002486 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002487 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002488 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002489 }
2490
Jamie Madill250d33f2014-06-06 17:09:03 -04002491 if (count < 0)
2492 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002493 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002494 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002495 }
2496
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002497 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002498
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002499 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2500 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2501 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2502 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002503 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002504 // Check for mapped buffers
2505 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002506 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002507 {
2508 context->handleError(InvalidOperation());
2509 return false;
2510 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002511 }
2512
Jamie Madillcbcde722017-01-06 14:50:00 -05002513 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2514 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002515 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002516 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002517 {
Ken Russellb9f92502018-01-27 19:00:26 -08002518 ASSERT(framebuffer);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002519 const FramebufferAttachment *dsAttachment =
2520 framebuffer->getStencilOrDepthStencilAttachment();
Ken Russellb9f92502018-01-27 19:00:26 -08002521 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2522 ASSERT(stencilBits <= 8);
2523
Jinyoung Hur85769f02015-10-20 17:08:44 -04002524 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Ken Russellb9f92502018-01-27 19:00:26 -08002525 if (depthStencilState.stencilTest && stencilBits > 0)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002526 {
Ken Russellb9f92502018-01-27 19:00:26 -08002527 GLuint maxStencilValue = (1 << stencilBits) - 1;
2528
2529 bool differentRefs =
2530 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2531 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2532 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2533 (depthStencilState.stencilBackWritemask & maxStencilValue);
2534 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2535 (depthStencilState.stencilBackMask & maxStencilValue);
2536
2537 if (differentRefs || differentWritemasks || differentMasks)
Jamie Madillcbcde722017-01-06 14:50:00 -05002538 {
Ken Russellb9f92502018-01-27 19:00:26 -08002539 if (!extensions.webglCompatibility)
2540 {
2541 ERR() << "This ANGLE implementation does not support separate front/back "
2542 "stencil writemasks, reference values, or stencil mask values.";
2543 }
2544 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
2545 return false;
Jamie Madillcbcde722017-01-06 14:50:00 -05002546 }
Geoff Lang3a86ad32015-09-01 11:47:05 -04002547 }
Jamie Madillac528012014-06-20 13:21:23 -04002548 }
2549
Jamie Madille98b1b52018-03-08 09:47:23 -05002550 if (!ValidateFramebufferComplete(context, framebuffer, true))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002551 {
Geoff Langb1196682014-07-23 13:47:29 -04002552 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002553 }
2554
Geoff Lang7dd2e102014-11-10 15:19:26 -05002555 gl::Program *program = state.getProgram();
2556 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002557 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002558 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002559 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002560 }
2561
Yunchao Hecddcb592017-11-13 15:27:35 +08002562 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2563 // vertex shader stage or fragment shader stage is a undefined behaviour.
2564 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2565 // produce undefined result.
Yunchao Heece12532017-11-21 15:50:21 +08002566 if (!program->hasLinkedVertexShader() || !program->hasLinkedFragmentShader())
Yunchao Hecddcb592017-11-13 15:27:35 +08002567 {
2568 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2569 "vertex shader stage or fragment shader stage.");
2570 return false;
2571 }
2572
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002573 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002574 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002575 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002576 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002577 }
2578
Martin Radevffe754b2017-07-31 10:38:07 +03002579 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002580 {
Martin Radevda8e2572017-09-12 17:21:16 +03002581 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002582 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002583 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002584 {
2585 context->handleError(InvalidOperation() << "The number of views in the active program "
2586 "and draw framebuffer does not match.");
2587 return false;
2588 }
Martin Radev7e69f762017-07-27 14:54:13 +03002589
2590 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2591 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2592 framebufferNumViews > 1)
2593 {
2594 context->handleError(InvalidOperation()
2595 << "There is an active transform feedback object "
2596 "when the number of views in the active draw "
2597 "framebuffer is greater than 1.");
2598 return false;
2599 }
Martin Radevffe754b2017-07-31 10:38:07 +03002600
2601 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2602 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2603 {
2604 context->handleError(InvalidOperation() << "There is an active query for target "
2605 "GL_TIME_ELAPSED_EXT when the number of "
2606 "views in the active draw framebuffer is "
2607 "greater than 1.");
2608 return false;
2609 }
Martin Radev7cf61662017-07-26 17:10:53 +03002610 }
2611
Jiawei Shaofccebff2018-03-08 13:51:02 +08002612 // Do geometry shader specific validations
2613 if (program->hasLinkedGeometryShader())
2614 {
2615 if (!IsCompatibleDrawModeWithGeometryShader(mode,
2616 program->getGeometryShaderInputPrimitiveType()))
2617 {
2618 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2619 IncompatibleDrawModeAgainstGeometryShader);
2620 return false;
2621 }
2622 }
2623
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002624 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002625 for (unsigned int uniformBlockIndex = 0;
2626 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002627 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002628 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002629 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002630 const OffsetBindingPointer<Buffer> &uniformBuffer =
2631 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002632
Geoff Lang5d124a62015-09-15 13:03:27 -04002633 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002634 {
2635 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002636 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002637 InvalidOperation()
2638 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002639 return false;
2640 }
2641
Geoff Lang5d124a62015-09-15 13:03:27 -04002642 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002643 if (uniformBufferSize == 0)
2644 {
2645 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002646 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002647 }
2648
Jamie Madill62d31cb2015-09-11 13:25:51 -04002649 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002650 {
2651 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002652 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002653 InvalidOperation()
2654 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002655 return false;
2656 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002657
2658 if (extensions.webglCompatibility &&
2659 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2660 {
2661 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2662 UniformBufferBoundForTransformFeedback);
2663 return false;
2664 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002665 }
2666
Geoff Lange0cff192017-05-30 13:04:56 -04002667 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002668 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002669 {
James Darpiniane8a93c62018-01-04 18:02:24 -08002670 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2671 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2672 transformFeedbackObject->buffersBoundForOtherUse())
2673 {
2674 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferDoubleBound);
2675 return false;
2676 }
Geoff Lange0cff192017-05-30 13:04:56 -04002677 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002678 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2679 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002680 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002681 return false;
2682 }
Geoff Lange0cff192017-05-30 13:04:56 -04002683
Geoff Lang9ab5b822017-05-30 16:19:23 -04002684 // Detect that the vertex shader input types match the attribute types
2685 if (!ValidateVertexShaderAttributeTypeMatch(context))
2686 {
2687 return false;
2688 }
2689
Geoff Lange0cff192017-05-30 13:04:56 -04002690 // Detect that the color buffer types match the fragment shader output types
2691 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2692 {
2693 return false;
2694 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002695 }
2696
Jamie Madill9fdaa492018-02-16 10:52:11 -05002697 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002698}
2699
Jamie Madill5b772312018-03-08 20:28:32 -05002700bool ValidateDrawArraysCommon(Context *context,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002701 GLenum mode,
2702 GLint first,
2703 GLsizei count,
2704 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002705{
Jamie Madillfd716582014-06-06 17:09:04 -04002706 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002707 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002708 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002709 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002710 }
2711
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002712 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002713 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002714 if (curTransformFeedback && curTransformFeedback->isActive() &&
2715 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002716 {
2717 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002718 // that does not match the current transform feedback object's draw mode (if transform
2719 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002720 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002721 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002722 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002723 }
2724
Jiajia Qind9671222016-11-29 16:30:31 +08002725 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002726 {
2727 return false;
2728 }
2729
Corentin Wallez71168a02016-12-19 15:11:18 -08002730 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002731 // - first < 0 has been checked as an error condition.
2732 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002733 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002734 ASSERT(first >= 0);
2735 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002736 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002737 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2738 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2739 {
2740 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2741 return false;
2742 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002743
Jamie Madill9fdaa492018-02-16 10:52:11 -05002744 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2745 {
2746 return false;
2747 }
Jamie Madillfd716582014-06-06 17:09:04 -04002748 }
2749
2750 return true;
2751}
2752
He Yunchaoced53ae2016-11-29 15:00:51 +08002753bool ValidateDrawArraysInstancedANGLE(Context *context,
2754 GLenum mode,
2755 GLint first,
2756 GLsizei count,
2757 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002758{
Geoff Lang63c5a592017-09-27 14:08:16 -04002759 if (!context->getExtensions().instancedArrays)
2760 {
2761 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2762 return false;
2763 }
2764
Corentin Wallez170efbf2017-05-02 13:45:01 -04002765 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002766 {
2767 return false;
2768 }
2769
Corentin Wallez0dc97812017-06-22 14:38:44 -04002770 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002771}
2772
Jamie Madill5b772312018-03-08 20:28:32 -05002773bool ValidateDrawElementsBase(Context *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002774{
Jamie Madill250d33f2014-06-06 17:09:03 -04002775 switch (type)
2776 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002777 case GL_UNSIGNED_BYTE:
2778 case GL_UNSIGNED_SHORT:
2779 break;
2780 case GL_UNSIGNED_INT:
2781 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2782 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002783 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002784 return false;
2785 }
2786 break;
2787 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002788 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002789 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002790 }
2791
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002792 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002793
2794 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002795 if (curTransformFeedback && curTransformFeedback->isActive() &&
2796 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002797 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002798 // It is an invalid operation to call DrawElements, DrawRangeElements or
2799 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002800 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002801 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002802 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002803 }
2804
Jiajia Qind9671222016-11-29 16:30:31 +08002805 return true;
2806}
2807
Jamie Madill5b772312018-03-08 20:28:32 -05002808bool ValidateDrawElementsCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002809 GLenum mode,
2810 GLsizei count,
2811 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002812 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002813 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002814{
2815 if (!ValidateDrawElementsBase(context, type))
2816 return false;
2817
2818 const State &state = context->getGLState();
2819
Corentin Wallez170efbf2017-05-02 13:45:01 -04002820 if (!ValidateDrawBase(context, mode, count))
2821 {
2822 return false;
2823 }
2824
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002825 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2826 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2827 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2828 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002829 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002830 // Check for mapped buffers
2831 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002832 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002833 {
2834 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2835 return false;
2836 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002837 }
2838
He Yunchaoced53ae2016-11-29 15:00:51 +08002839 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002840 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002841
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002842 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2843
2844 if (context->getExtensions().webglCompatibility)
2845 {
2846 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2847 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2848 {
2849 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2850 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2851 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002852 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002853 return false;
2854 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002855
2856 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2857 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2858 // error is generated.
2859 if (reinterpret_cast<intptr_t>(indices) < 0)
2860 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002861 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002862 return false;
2863 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002864 }
2865
2866 if (context->getExtensions().webglCompatibility ||
2867 !context->getGLState().areClientArraysEnabled())
2868 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002869 if (!elementArrayBuffer && count > 0)
2870 {
2871 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2872 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2873 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002874 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002875 return false;
2876 }
2877 }
2878
Jamie Madill9fdaa492018-02-16 10:52:11 -05002879 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04002880 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002881 // This is an application error that would normally result in a crash, but we catch it and
2882 // return an error
2883 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
2884 return false;
2885 }
2886
2887 if (count > 0 && elementArrayBuffer)
2888 {
2889 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2890 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2891 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2892 constexpr uint64_t kMaxTypeSize = 8;
2893 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2894 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2895 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
2896
2897 uint64_t typeSize = typeBytes;
2898 uint64_t elementCount = static_cast<uint64_t>(count);
2899 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2900
2901 // Doing the multiplication here is overflow-safe
2902 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2903
2904 // The offset can be any value, check for overflows
2905 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2906 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04002907 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002908 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2909 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002910 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05002911
2912 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2913 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002914 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002915 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
2916 return false;
2917 }
2918
2919 ASSERT(isPow2(typeSize) && typeSize > 0);
2920 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
2921 {
2922 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04002923 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002924 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002925
2926 if (context->getExtensions().webglCompatibility &&
2927 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
2928 {
2929 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2930 ElementArrayBufferBoundForTransformFeedback);
2931 return false;
2932 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002933 }
2934
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002935 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002936 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002937 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2938 // access is enabled.
2939 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2940 {
2941 return false;
2942 }
2943 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05002944 else if (count == 0)
2945 {
2946 // ValidateDrawAttribs also does some extra validation that is independent of the vertex
2947 // count.
2948 if (!ValidateDrawAttribs(context, 0, 0, 0))
2949 {
2950 return false;
2951 }
2952 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002953 else
2954 {
2955 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04002956 const DrawCallParams &params = context->getParams<DrawCallParams>();
2957 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
2958 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002959
2960 // If we use an index greater than our maximum supported index range, return an error.
2961 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2962 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04002963 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002964 {
2965 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2966 return false;
2967 }
2968
Jamie Madill6f5444d2018-03-14 10:08:11 -04002969 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end),
2970 static_cast<GLint>(indexRange.vertexCount())))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002971 {
2972 return false;
2973 }
2974
2975 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04002976 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002977 }
2978
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002979 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002980}
2981
Jamie Madill5b772312018-03-08 20:28:32 -05002982bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002983 GLenum mode,
2984 GLsizei count,
2985 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002986 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002987 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002988{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002989 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002990}
2991
Geoff Lang3edfe032015-09-04 16:38:24 -04002992bool ValidateDrawElementsInstancedANGLE(Context *context,
2993 GLenum mode,
2994 GLsizei count,
2995 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002996 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002997 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002998{
Geoff Lang63c5a592017-09-27 14:08:16 -04002999 if (!context->getExtensions().instancedArrays)
3000 {
3001 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3002 return false;
3003 }
3004
Corentin Wallez170efbf2017-05-02 13:45:01 -04003005 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003006 {
3007 return false;
3008 }
3009
Corentin Wallez0dc97812017-06-22 14:38:44 -04003010 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003011}
3012
He Yunchaoced53ae2016-11-29 15:00:51 +08003013bool ValidateFramebufferTextureBase(Context *context,
3014 GLenum target,
3015 GLenum attachment,
3016 GLuint texture,
3017 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003018{
Geoff Lange8afa902017-09-27 15:00:43 -04003019 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003020 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003021 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003022 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003023 }
3024
3025 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003026 {
3027 return false;
3028 }
3029
Jamie Madill55ec3b12014-07-03 10:38:57 -04003030 if (texture != 0)
3031 {
3032 gl::Texture *tex = context->getTexture(texture);
3033
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003034 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003035 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003036 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003037 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003038 }
3039
3040 if (level < 0)
3041 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003042 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003043 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003044 }
3045 }
3046
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003047 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003048 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003049
Jamie Madill84115c92015-04-23 15:00:07 -04003050 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003051 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003052 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003053 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003054 }
3055
3056 return true;
3057}
3058
Geoff Langb1196682014-07-23 13:47:29 -04003059bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003060{
3061 if (program == 0)
3062 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003063 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003064 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003065 }
3066
Dian Xiang769769a2015-09-09 15:20:08 -07003067 gl::Program *programObject = GetValidProgram(context, program);
3068 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003069 {
3070 return false;
3071 }
3072
Jamie Madill0063c512014-08-25 15:47:53 -04003073 if (!programObject || !programObject->isLinked())
3074 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003075 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003076 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003077 }
3078
Geoff Lang7dd2e102014-11-10 15:19:26 -05003079 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003080 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003081 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003082 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003083 }
3084
Jamie Madill0063c512014-08-25 15:47:53 -04003085 return true;
3086}
3087
Geoff Langf41d0ee2016-10-07 13:04:23 -04003088static bool ValidateSizedGetUniform(Context *context,
3089 GLuint program,
3090 GLint location,
3091 GLsizei bufSize,
3092 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003093{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003094 if (length)
3095 {
3096 *length = 0;
3097 }
3098
Jamie Madill78f41802014-08-25 15:47:55 -04003099 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003100 {
Jamie Madill78f41802014-08-25 15:47:55 -04003101 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003102 }
3103
Geoff Langf41d0ee2016-10-07 13:04:23 -04003104 if (bufSize < 0)
3105 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003106 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003107 return false;
3108 }
3109
Jamie Madilla502c742014-08-28 17:19:13 -04003110 gl::Program *programObject = context->getProgram(program);
3111 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003112
Jamie Madill78f41802014-08-25 15:47:55 -04003113 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003114 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003115 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003116 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003117 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003118 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003119 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003120 }
3121
Geoff Langf41d0ee2016-10-07 13:04:23 -04003122 if (length)
3123 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003124 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003125 }
3126
Jamie Madill0063c512014-08-25 15:47:53 -04003127 return true;
3128}
3129
He Yunchaoced53ae2016-11-29 15:00:51 +08003130bool ValidateGetnUniformfvEXT(Context *context,
3131 GLuint program,
3132 GLint location,
3133 GLsizei bufSize,
3134 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003135{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003136 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003137}
3138
He Yunchaoced53ae2016-11-29 15:00:51 +08003139bool ValidateGetnUniformivEXT(Context *context,
3140 GLuint program,
3141 GLint location,
3142 GLsizei bufSize,
3143 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003144{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003145 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3146}
3147
3148bool ValidateGetUniformfvRobustANGLE(Context *context,
3149 GLuint program,
3150 GLint location,
3151 GLsizei bufSize,
3152 GLsizei *length,
3153 GLfloat *params)
3154{
3155 if (!ValidateRobustEntryPoint(context, bufSize))
3156 {
3157 return false;
3158 }
3159
3160 // bufSize is validated in ValidateSizedGetUniform
3161 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3162}
3163
3164bool ValidateGetUniformivRobustANGLE(Context *context,
3165 GLuint program,
3166 GLint location,
3167 GLsizei bufSize,
3168 GLsizei *length,
3169 GLint *params)
3170{
3171 if (!ValidateRobustEntryPoint(context, bufSize))
3172 {
3173 return false;
3174 }
3175
3176 // bufSize is validated in ValidateSizedGetUniform
3177 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3178}
3179
3180bool ValidateGetUniformuivRobustANGLE(Context *context,
3181 GLuint program,
3182 GLint location,
3183 GLsizei bufSize,
3184 GLsizei *length,
3185 GLuint *params)
3186{
3187 if (!ValidateRobustEntryPoint(context, bufSize))
3188 {
3189 return false;
3190 }
3191
3192 if (context->getClientMajorVersion() < 3)
3193 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003194 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003195 return false;
3196 }
3197
3198 // bufSize is validated in ValidateSizedGetUniform
3199 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003200}
3201
He Yunchaoced53ae2016-11-29 15:00:51 +08003202bool ValidateDiscardFramebufferBase(Context *context,
3203 GLenum target,
3204 GLsizei numAttachments,
3205 const GLenum *attachments,
3206 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003207{
3208 if (numAttachments < 0)
3209 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003210 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003211 return false;
3212 }
3213
3214 for (GLsizei i = 0; i < numAttachments; ++i)
3215 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003216 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003217 {
3218 if (defaultFramebuffer)
3219 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003220 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003221 return false;
3222 }
3223
3224 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3225 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003226 context->handleError(InvalidOperation() << "Requested color attachment is "
3227 "greater than the maximum supported "
3228 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003229 return false;
3230 }
3231 }
3232 else
3233 {
3234 switch (attachments[i])
3235 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003236 case GL_DEPTH_ATTACHMENT:
3237 case GL_STENCIL_ATTACHMENT:
3238 case GL_DEPTH_STENCIL_ATTACHMENT:
3239 if (defaultFramebuffer)
3240 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003241 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3242 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003243 return false;
3244 }
3245 break;
3246 case GL_COLOR:
3247 case GL_DEPTH:
3248 case GL_STENCIL:
3249 if (!defaultFramebuffer)
3250 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003251 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3252 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003253 return false;
3254 }
3255 break;
3256 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003257 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003258 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003259 }
3260 }
3261 }
3262
3263 return true;
3264}
3265
Austin Kinross6ee1e782015-05-29 17:05:37 -07003266bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3267{
Jamie Madill007530e2017-12-28 14:27:04 -05003268 if (!context->getExtensions().debugMarker)
3269 {
3270 // The debug marker calls should not set error state
3271 // However, it seems reasonable to set an error state if the extension is not enabled
3272 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3273 return false;
3274 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003275
Jamie Madill007530e2017-12-28 14:27:04 -05003276 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003277 if (length < 0)
3278 {
3279 return false;
3280 }
3281
3282 if (marker == nullptr)
3283 {
3284 return false;
3285 }
3286
3287 return true;
3288}
3289
3290bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3291{
Jamie Madill007530e2017-12-28 14:27:04 -05003292 if (!context->getExtensions().debugMarker)
3293 {
3294 // The debug marker calls should not set error state
3295 // However, it seems reasonable to set an error state if the extension is not enabled
3296 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3297 return false;
3298 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003299
Jamie Madill007530e2017-12-28 14:27:04 -05003300 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003301 if (length < 0)
3302 {
3303 return false;
3304 }
3305
3306 if (length > 0 && marker == nullptr)
3307 {
3308 return false;
3309 }
3310
3311 return true;
3312}
3313
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003314bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003315{
Geoff Langa8406172015-07-21 16:53:39 -04003316 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003318 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003319 return false;
3320 }
3321
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003322 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003323 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003324 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003325 if (!context->getExtensions().eglImage)
3326 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003327 context->handleError(InvalidEnum()
3328 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003329 }
3330 break;
3331
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003332 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003333 if (!context->getExtensions().eglImageExternal)
3334 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003335 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3336 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003337 }
Geoff Langa8406172015-07-21 16:53:39 -04003338 break;
3339
3340 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003341 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003342 return false;
3343 }
3344
Jamie Madill007530e2017-12-28 14:27:04 -05003345 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3346
Jamie Madill61e16b42017-06-19 11:13:23 -04003347 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003348 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003349 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003350 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003351 return false;
3352 }
3353
Jamie Madill007530e2017-12-28 14:27:04 -05003354 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003355 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003356 context->handleError(InvalidOperation()
3357 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003358 return false;
3359 }
3360
Geoff Langca271392017-04-05 12:30:00 -04003361 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003362 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003363 if (!textureCaps.texturable)
3364 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003365 context->handleError(InvalidOperation()
3366 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003367 return false;
3368 }
3369
Geoff Langdcab33b2015-07-21 13:03:16 -04003370 return true;
3371}
3372
3373bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003374 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003375 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003376{
Geoff Langa8406172015-07-21 16:53:39 -04003377 if (!context->getExtensions().eglImage)
3378 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003379 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003380 return false;
3381 }
3382
3383 switch (target)
3384 {
3385 case GL_RENDERBUFFER:
3386 break;
3387
3388 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003389 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003390 return false;
3391 }
3392
Jamie Madill007530e2017-12-28 14:27:04 -05003393 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3394
Jamie Madill61e16b42017-06-19 11:13:23 -04003395 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003396 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003397 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003398 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003399 return false;
3400 }
3401
Geoff Langca271392017-04-05 12:30:00 -04003402 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003403 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003404 if (!textureCaps.renderable)
3405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003406 context->handleError(InvalidOperation()
3407 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003408 return false;
3409 }
3410
Geoff Langdcab33b2015-07-21 13:03:16 -04003411 return true;
3412}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003413
3414bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3415{
Geoff Lang36167ab2015-12-07 10:27:14 -05003416 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003417 {
3418 // The default VAO should always exist
3419 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003420 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003421 return false;
3422 }
3423
3424 return true;
3425}
3426
Geoff Langc5629752015-12-07 16:29:04 -05003427bool ValidateProgramBinaryBase(Context *context,
3428 GLuint program,
3429 GLenum binaryFormat,
3430 const void *binary,
3431 GLint length)
3432{
3433 Program *programObject = GetValidProgram(context, program);
3434 if (programObject == nullptr)
3435 {
3436 return false;
3437 }
3438
3439 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3440 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3441 programBinaryFormats.end())
3442 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003443 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003444 return false;
3445 }
3446
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003447 if (context->hasActiveTransformFeedback(program))
3448 {
3449 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003450 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3451 "is associated with an active transform "
3452 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003453 return false;
3454 }
3455
Geoff Langc5629752015-12-07 16:29:04 -05003456 return true;
3457}
3458
3459bool ValidateGetProgramBinaryBase(Context *context,
3460 GLuint program,
3461 GLsizei bufSize,
3462 GLsizei *length,
3463 GLenum *binaryFormat,
3464 void *binary)
3465{
3466 Program *programObject = GetValidProgram(context, program);
3467 if (programObject == nullptr)
3468 {
3469 return false;
3470 }
3471
3472 if (!programObject->isLinked())
3473 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003474 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003475 return false;
3476 }
3477
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003478 if (context->getCaps().programBinaryFormats.empty())
3479 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003480 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003481 return false;
3482 }
3483
Geoff Langc5629752015-12-07 16:29:04 -05003484 return true;
3485}
Jamie Madillc29968b2016-01-20 11:17:23 -05003486
Jamie Madill5b772312018-03-08 20:28:32 -05003487bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003488{
3489 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003490 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003491 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003492 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3493 return false;
3494 }
3495 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3496 {
3497 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003498 return false;
3499 }
3500
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003501 ASSERT(context->getGLState().getDrawFramebuffer());
3502 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003503 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3504
3505 // This should come first before the check for the default frame buffer
3506 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3507 // rather than INVALID_OPERATION
3508 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3509 {
3510 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3511
3512 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003513 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3514 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003515 {
3516 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003517 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3518 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3519 // 3.1 is still a bit ambiguous about the error, but future specs are
3520 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003521 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003522 return false;
3523 }
3524 else if (bufs[colorAttachment] >= maxColorAttachment)
3525 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003526 context->handleError(InvalidOperation()
3527 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003528 return false;
3529 }
3530 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3531 frameBufferId != 0)
3532 {
3533 // INVALID_OPERATION-GL is bound to buffer and ith argument
3534 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003535 context->handleError(InvalidOperation()
3536 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003537 return false;
3538 }
3539 }
3540
3541 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3542 // and n is not 1 or bufs is bound to value other than BACK and NONE
3543 if (frameBufferId == 0)
3544 {
3545 if (n != 1)
3546 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003547 context->handleError(InvalidOperation()
3548 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003549 return false;
3550 }
3551
3552 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3553 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003554 context->handleError(
3555 InvalidOperation()
3556 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003557 return false;
3558 }
3559 }
3560
3561 return true;
3562}
3563
Geoff Lang496c02d2016-10-20 11:38:11 -07003564bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003565 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003566 GLenum pname,
3567 GLsizei *length,
3568 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003569{
Geoff Lang496c02d2016-10-20 11:38:11 -07003570 if (length)
3571 {
3572 *length = 0;
3573 }
3574
3575 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3576 {
3577 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003578 InvalidOperation()
3579 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003580 return false;
3581 }
3582
Corentin Walleze4477002017-12-01 14:39:58 -05003583 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003584 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003585 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003586 return false;
3587 }
3588
Geoff Lang496c02d2016-10-20 11:38:11 -07003589 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003590 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003591 case GL_BUFFER_MAP_POINTER:
3592 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003593
Geoff Lang496c02d2016-10-20 11:38:11 -07003594 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003595 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003596 return false;
3597 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003598
3599 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3600 // target bound to zero generate an INVALID_OPERATION error."
3601 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003602 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003603 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003604 context->handleError(InvalidOperation()
3605 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003606 return false;
3607 }
3608
Geoff Lang496c02d2016-10-20 11:38:11 -07003609 if (length)
3610 {
3611 *length = 1;
3612 }
3613
Olli Etuaho4f667482016-03-30 15:56:35 +03003614 return true;
3615}
3616
Corentin Wallez336129f2017-10-17 15:55:40 -04003617bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003618{
Corentin Walleze4477002017-12-01 14:39:58 -05003619 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003620 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003621 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003622 return false;
3623 }
3624
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003625 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003626
3627 if (buffer == nullptr || !buffer->isMapped())
3628 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003629 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003630 return false;
3631 }
3632
3633 return true;
3634}
3635
3636bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003637 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003638 GLintptr offset,
3639 GLsizeiptr length,
3640 GLbitfield access)
3641{
Corentin Walleze4477002017-12-01 14:39:58 -05003642 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003643 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003644 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003645 return false;
3646 }
3647
Brandon Jones6cad5662017-06-14 13:25:13 -07003648 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003649 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003650 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3651 return false;
3652 }
3653
3654 if (length < 0)
3655 {
3656 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003657 return false;
3658 }
3659
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003660 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003661
3662 if (!buffer)
3663 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003664 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003665 return false;
3666 }
3667
3668 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003669 CheckedNumeric<size_t> checkedOffset(offset);
3670 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003671
Jamie Madille2e406c2016-06-02 13:04:10 -04003672 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003673 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003674 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003675 return false;
3676 }
3677
3678 // Check for invalid bits in the mask
3679 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3680 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3681 GL_MAP_UNSYNCHRONIZED_BIT;
3682
3683 if (access & ~(allAccessBits))
3684 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003685 context->handleError(InvalidValue()
3686 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003687 return false;
3688 }
3689
3690 if (length == 0)
3691 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003692 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003693 return false;
3694 }
3695
3696 if (buffer->isMapped())
3697 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003698 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003699 return false;
3700 }
3701
3702 // Check for invalid bit combinations
3703 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003705 context->handleError(InvalidOperation()
3706 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003707 return false;
3708 }
3709
3710 GLbitfield writeOnlyBits =
3711 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3712
3713 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3714 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003715 context->handleError(InvalidOperation()
3716 << "Invalid access bits when mapping buffer for reading: 0x"
3717 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003718 return false;
3719 }
3720
3721 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3722 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003723 context->handleError(
3724 InvalidOperation()
3725 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003726 return false;
3727 }
Geoff Lang79f71042017-08-14 16:43:43 -04003728
3729 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003730}
3731
3732bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003733 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003734 GLintptr offset,
3735 GLsizeiptr length)
3736{
Brandon Jones6cad5662017-06-14 13:25:13 -07003737 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003738 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003739 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3740 return false;
3741 }
3742
3743 if (length < 0)
3744 {
3745 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003746 return false;
3747 }
3748
Corentin Walleze4477002017-12-01 14:39:58 -05003749 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003750 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003751 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003752 return false;
3753 }
3754
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003755 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003756
3757 if (buffer == nullptr)
3758 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003759 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003760 return false;
3761 }
3762
3763 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003765 context->handleError(InvalidOperation()
3766 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003767 return false;
3768 }
3769
3770 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003771 CheckedNumeric<size_t> checkedOffset(offset);
3772 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003773
Jamie Madille2e406c2016-06-02 13:04:10 -04003774 if (!checkedSize.IsValid() ||
3775 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003776 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003777 context->handleError(InvalidValue()
3778 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003779 return false;
3780 }
3781
3782 return true;
3783}
3784
Olli Etuaho41997e72016-03-10 13:38:39 +02003785bool ValidateGenOrDelete(Context *context, GLint n)
3786{
3787 if (n < 0)
3788 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003789 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003790 return false;
3791 }
3792 return true;
3793}
3794
Jamie Madill5b772312018-03-08 20:28:32 -05003795bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003796{
3797 if (!context->getExtensions().robustClientMemory)
3798 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003799 context->handleError(InvalidOperation()
3800 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003801 return false;
3802 }
3803
3804 if (bufSize < 0)
3805 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003806 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003807 return false;
3808 }
3809
3810 return true;
3811}
3812
Jamie Madill5b772312018-03-08 20:28:32 -05003813bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003814{
3815 if (bufSize < numParams)
3816 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003817 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3818 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003819 return false;
3820 }
3821
3822 return true;
3823}
3824
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003825bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04003826 GLenum target,
3827 GLenum attachment,
3828 GLenum pname,
3829 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003830{
Geoff Lange8afa902017-09-27 15:00:43 -04003831 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003832 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003833 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003834 return false;
3835 }
3836
3837 int clientVersion = context->getClientMajorVersion();
3838
3839 switch (pname)
3840 {
3841 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3842 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3843 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3844 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3845 break;
3846
Martin Radeve5285d22017-07-14 16:23:53 +03003847 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3848 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3849 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3850 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3851 if (clientVersion < 3 || !context->getExtensions().multiview)
3852 {
3853 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3854 return false;
3855 }
3856 break;
3857
Geoff Langff5b2d52016-09-07 11:32:23 -04003858 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3859 if (clientVersion < 3 && !context->getExtensions().sRGB)
3860 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003861 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003862 return false;
3863 }
3864 break;
3865
3866 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3867 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3868 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3869 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3870 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3871 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3872 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3873 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3874 if (clientVersion < 3)
3875 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003876 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003877 return false;
3878 }
3879 break;
3880
3881 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003882 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003883 return false;
3884 }
3885
3886 // Determine if the attachment is a valid enum
3887 switch (attachment)
3888 {
3889 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04003890 case GL_DEPTH:
3891 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04003892 if (clientVersion < 3)
3893 {
Geoff Langfa125c92017-10-24 13:01:46 -04003894 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003895 return false;
3896 }
3897 break;
3898
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003899 case GL_DEPTH_STENCIL_ATTACHMENT:
3900 if (clientVersion < 3 && !context->isWebGL1())
3901 {
3902 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3903 return false;
3904 }
3905 break;
3906
Geoff Langfa125c92017-10-24 13:01:46 -04003907 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003908 case GL_DEPTH_ATTACHMENT:
3909 case GL_STENCIL_ATTACHMENT:
3910 break;
3911
3912 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003913 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3914 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003915 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3916 {
Geoff Langfa125c92017-10-24 13:01:46 -04003917 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003918 return false;
3919 }
3920 break;
3921 }
3922
3923 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3924 ASSERT(framebuffer);
3925
3926 if (framebuffer->id() == 0)
3927 {
3928 if (clientVersion < 3)
3929 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003930 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003931 return false;
3932 }
3933
3934 switch (attachment)
3935 {
3936 case GL_BACK:
3937 case GL_DEPTH:
3938 case GL_STENCIL:
3939 break;
3940
3941 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003942 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003943 return false;
3944 }
3945 }
3946 else
3947 {
3948 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3949 {
3950 // Valid attachment query
3951 }
3952 else
3953 {
3954 switch (attachment)
3955 {
3956 case GL_DEPTH_ATTACHMENT:
3957 case GL_STENCIL_ATTACHMENT:
3958 break;
3959
3960 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003961 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04003962 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003963 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003964 return false;
3965 }
3966 break;
3967
3968 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003969 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003970 return false;
3971 }
3972 }
3973 }
3974
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003975 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003976 if (attachmentObject)
3977 {
3978 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3979 attachmentObject->type() == GL_TEXTURE ||
3980 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3981
3982 switch (pname)
3983 {
3984 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3985 if (attachmentObject->type() != GL_RENDERBUFFER &&
3986 attachmentObject->type() != GL_TEXTURE)
3987 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003988 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003989 return false;
3990 }
3991 break;
3992
3993 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3994 if (attachmentObject->type() != GL_TEXTURE)
3995 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003996 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003997 return false;
3998 }
3999 break;
4000
4001 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4002 if (attachmentObject->type() != GL_TEXTURE)
4003 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004004 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004005 return false;
4006 }
4007 break;
4008
4009 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4010 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4011 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004012 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004013 return false;
4014 }
4015 break;
4016
4017 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4018 if (attachmentObject->type() != GL_TEXTURE)
4019 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004020 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004021 return false;
4022 }
4023 break;
4024
4025 default:
4026 break;
4027 }
4028 }
4029 else
4030 {
4031 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4032 // is NONE, then querying any other pname will generate INVALID_ENUM.
4033
4034 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4035 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4036 // INVALID_OPERATION for all other pnames
4037
4038 switch (pname)
4039 {
4040 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4041 break;
4042
4043 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4044 if (clientVersion < 3)
4045 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004046 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004047 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004048 return false;
4049 }
4050 break;
4051
4052 default:
4053 if (clientVersion < 3)
4054 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004055 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004056 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004057 return false;
4058 }
4059 else
4060 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004061 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004062 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004063 return false;
4064 }
4065 }
4066 }
4067
Martin Radeve5285d22017-07-14 16:23:53 +03004068 if (numParams)
4069 {
4070 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4071 {
4072 // Only when the viewport offsets are queried we can have a varying number of output
4073 // parameters.
4074 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4075 *numParams = numViews * 2;
4076 }
4077 else
4078 {
4079 // For all other queries we can have only one output parameter.
4080 *numParams = 1;
4081 }
4082 }
4083
Geoff Langff5b2d52016-09-07 11:32:23 -04004084 return true;
4085}
4086
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004087bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004088 GLenum target,
4089 GLenum attachment,
4090 GLenum pname,
4091 GLsizei bufSize,
4092 GLsizei *numParams)
4093{
4094 if (!ValidateRobustEntryPoint(context, bufSize))
4095 {
4096 return false;
4097 }
4098
Jamie Madillbe849e42017-05-02 15:49:00 -04004099 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4100 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004101 {
4102 return false;
4103 }
4104
4105 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4106 {
4107 return false;
4108 }
4109
4110 return true;
4111}
4112
Jamie Madill5b772312018-03-08 20:28:32 -05004113bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004114 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004115 GLenum pname,
4116 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004117 GLsizei *length,
4118 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004119{
4120 if (!ValidateRobustEntryPoint(context, bufSize))
4121 {
4122 return false;
4123 }
4124
Geoff Langebebe1c2016-10-14 12:01:31 -04004125 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004126 {
4127 return false;
4128 }
4129
Geoff Langebebe1c2016-10-14 12:01:31 -04004130 if (!ValidateRobustBufferSize(context, bufSize, *length))
4131 {
4132 return false;
4133 }
4134
4135 return true;
4136}
4137
Jamie Madill5b772312018-03-08 20:28:32 -05004138bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004139 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004140 GLenum pname,
4141 GLsizei bufSize,
4142 GLsizei *length,
4143 GLint64 *params)
4144{
4145 if (!ValidateRobustEntryPoint(context, bufSize))
4146 {
4147 return false;
4148 }
4149
4150 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4151 {
4152 return false;
4153 }
4154
4155 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004156 {
4157 return false;
4158 }
4159
4160 return true;
4161}
4162
Jamie Madill5b772312018-03-08 20:28:32 -05004163bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004164{
4165 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004166 if (numParams)
4167 {
4168 *numParams = 1;
4169 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004170
4171 Program *programObject = GetValidProgram(context, program);
4172 if (!programObject)
4173 {
4174 return false;
4175 }
4176
4177 switch (pname)
4178 {
4179 case GL_DELETE_STATUS:
4180 case GL_LINK_STATUS:
4181 case GL_VALIDATE_STATUS:
4182 case GL_INFO_LOG_LENGTH:
4183 case GL_ATTACHED_SHADERS:
4184 case GL_ACTIVE_ATTRIBUTES:
4185 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4186 case GL_ACTIVE_UNIFORMS:
4187 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4188 break;
4189
4190 case GL_PROGRAM_BINARY_LENGTH:
4191 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004193 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4194 "requires GL_OES_get_program_binary or "
4195 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004196 return false;
4197 }
4198 break;
4199
4200 case GL_ACTIVE_UNIFORM_BLOCKS:
4201 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4202 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4203 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4204 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4205 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4206 if (context->getClientMajorVersion() < 3)
4207 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004208 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004209 return false;
4210 }
4211 break;
4212
Yunchao He61afff12017-03-14 15:34:03 +08004213 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004214 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004215 if (context->getClientVersion() < Version(3, 1))
4216 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004217 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004218 return false;
4219 }
4220 break;
4221
Jiawei Shao6ae51612018-02-23 14:03:25 +08004222 case GL_COMPUTE_WORK_GROUP_SIZE:
4223 if (context->getClientVersion() < Version(3, 1))
4224 {
4225 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4226 return false;
4227 }
4228
4229 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4230 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4231 // program which has not been linked successfully, or which does not contain objects to
4232 // form a compute shader.
4233 if (!programObject->isLinked())
4234 {
4235 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4236 return false;
4237 }
4238 if (!programObject->hasLinkedComputeShader())
4239 {
4240 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4241 return false;
4242 }
4243 break;
4244
Jiawei Shao447bfac2018-03-14 14:23:40 +08004245 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4246 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4247 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4248 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4249 if (!context->getExtensions().geometryShader)
4250 {
4251 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4252 return false;
4253 }
4254
4255 // [EXT_geometry_shader] Chapter 7.12
4256 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4257 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4258 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4259 // successfully, or which does not contain objects to form a geometry shader.
4260 if (!programObject->isLinked())
4261 {
4262 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4263 return false;
4264 }
4265 if (!programObject->hasLinkedGeometryShader())
4266 {
4267 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4268 return false;
4269 }
4270 break;
4271
Geoff Langff5b2d52016-09-07 11:32:23 -04004272 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004273 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004274 return false;
4275 }
4276
4277 return true;
4278}
4279
4280bool ValidateGetProgramivRobustANGLE(Context *context,
4281 GLuint program,
4282 GLenum pname,
4283 GLsizei bufSize,
4284 GLsizei *numParams)
4285{
4286 if (!ValidateRobustEntryPoint(context, bufSize))
4287 {
4288 return false;
4289 }
4290
Jamie Madillbe849e42017-05-02 15:49:00 -04004291 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004292 {
4293 return false;
4294 }
4295
4296 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4297 {
4298 return false;
4299 }
4300
4301 return true;
4302}
4303
Geoff Lang740d9022016-10-07 11:20:52 -04004304bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4305 GLenum target,
4306 GLenum pname,
4307 GLsizei bufSize,
4308 GLsizei *length,
4309 GLint *params)
4310{
4311 if (!ValidateRobustEntryPoint(context, bufSize))
4312 {
4313 return false;
4314 }
4315
4316 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4317 {
4318 return false;
4319 }
4320
4321 if (!ValidateRobustBufferSize(context, bufSize, *length))
4322 {
4323 return false;
4324 }
4325
4326 return true;
4327}
4328
Geoff Langd7d0ed32016-10-07 11:33:51 -04004329bool ValidateGetShaderivRobustANGLE(Context *context,
4330 GLuint shader,
4331 GLenum pname,
4332 GLsizei bufSize,
4333 GLsizei *length,
4334 GLint *params)
4335{
4336 if (!ValidateRobustEntryPoint(context, bufSize))
4337 {
4338 return false;
4339 }
4340
4341 if (!ValidateGetShaderivBase(context, shader, pname, length))
4342 {
4343 return false;
4344 }
4345
4346 if (!ValidateRobustBufferSize(context, bufSize, *length))
4347 {
4348 return false;
4349 }
4350
4351 return true;
4352}
4353
Geoff Langc1984ed2016-10-07 12:41:00 -04004354bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004355 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004356 GLenum pname,
4357 GLsizei bufSize,
4358 GLsizei *length,
4359 GLfloat *params)
4360{
4361 if (!ValidateRobustEntryPoint(context, bufSize))
4362 {
4363 return false;
4364 }
4365
4366 if (!ValidateGetTexParameterBase(context, target, pname, length))
4367 {
4368 return false;
4369 }
4370
4371 if (!ValidateRobustBufferSize(context, bufSize, *length))
4372 {
4373 return false;
4374 }
4375
4376 return true;
4377}
4378
Geoff Langc1984ed2016-10-07 12:41:00 -04004379bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004380 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004381 GLenum pname,
4382 GLsizei bufSize,
4383 GLsizei *length,
4384 GLint *params)
4385{
4386 if (!ValidateRobustEntryPoint(context, bufSize))
4387 {
4388 return false;
4389 }
4390
4391 if (!ValidateGetTexParameterBase(context, target, pname, length))
4392 {
4393 return false;
4394 }
4395
4396 if (!ValidateRobustBufferSize(context, bufSize, *length))
4397 {
4398 return false;
4399 }
4400
4401 return true;
4402}
4403
Geoff Langc1984ed2016-10-07 12:41:00 -04004404bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004405 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004406 GLenum pname,
4407 GLsizei bufSize,
4408 const GLfloat *params)
4409{
4410 if (!ValidateRobustEntryPoint(context, bufSize))
4411 {
4412 return false;
4413 }
4414
4415 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4416}
4417
Geoff Langc1984ed2016-10-07 12:41:00 -04004418bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004419 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004420 GLenum pname,
4421 GLsizei bufSize,
4422 const GLint *params)
4423{
4424 if (!ValidateRobustEntryPoint(context, bufSize))
4425 {
4426 return false;
4427 }
4428
4429 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4430}
4431
Geoff Langc1984ed2016-10-07 12:41:00 -04004432bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4433 GLuint sampler,
4434 GLenum pname,
4435 GLuint bufSize,
4436 GLsizei *length,
4437 GLfloat *params)
4438{
4439 if (!ValidateRobustEntryPoint(context, bufSize))
4440 {
4441 return false;
4442 }
4443
4444 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4445 {
4446 return false;
4447 }
4448
4449 if (!ValidateRobustBufferSize(context, bufSize, *length))
4450 {
4451 return false;
4452 }
4453
4454 return true;
4455}
4456
Geoff Langc1984ed2016-10-07 12:41:00 -04004457bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4458 GLuint sampler,
4459 GLenum pname,
4460 GLuint bufSize,
4461 GLsizei *length,
4462 GLint *params)
4463{
4464 if (!ValidateRobustEntryPoint(context, bufSize))
4465 {
4466 return false;
4467 }
4468
4469 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4470 {
4471 return false;
4472 }
4473
4474 if (!ValidateRobustBufferSize(context, bufSize, *length))
4475 {
4476 return false;
4477 }
4478
4479 return true;
4480}
4481
Geoff Langc1984ed2016-10-07 12:41:00 -04004482bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4483 GLuint sampler,
4484 GLenum pname,
4485 GLsizei bufSize,
4486 const GLfloat *params)
4487{
4488 if (!ValidateRobustEntryPoint(context, bufSize))
4489 {
4490 return false;
4491 }
4492
4493 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4494}
4495
Geoff Langc1984ed2016-10-07 12:41:00 -04004496bool ValidateSamplerParameterivRobustANGLE(Context *context,
4497 GLuint sampler,
4498 GLenum pname,
4499 GLsizei bufSize,
4500 const GLint *params)
4501{
4502 if (!ValidateRobustEntryPoint(context, bufSize))
4503 {
4504 return false;
4505 }
4506
4507 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4508}
4509
Geoff Lang0b031062016-10-13 14:30:04 -04004510bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4511 GLuint index,
4512 GLenum pname,
4513 GLsizei bufSize,
4514 GLsizei *length,
4515 GLfloat *params)
4516{
4517 if (!ValidateRobustEntryPoint(context, bufSize))
4518 {
4519 return false;
4520 }
4521
4522 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4523 {
4524 return false;
4525 }
4526
4527 if (!ValidateRobustBufferSize(context, bufSize, *length))
4528 {
4529 return false;
4530 }
4531
4532 return true;
4533}
4534
Geoff Lang0b031062016-10-13 14:30:04 -04004535bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4536 GLuint index,
4537 GLenum pname,
4538 GLsizei bufSize,
4539 GLsizei *length,
4540 GLint *params)
4541{
4542 if (!ValidateRobustEntryPoint(context, bufSize))
4543 {
4544 return false;
4545 }
4546
4547 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4548 {
4549 return false;
4550 }
4551
4552 if (!ValidateRobustBufferSize(context, bufSize, *length))
4553 {
4554 return false;
4555 }
4556
4557 return true;
4558}
4559
Geoff Lang0b031062016-10-13 14:30:04 -04004560bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4561 GLuint index,
4562 GLenum pname,
4563 GLsizei bufSize,
4564 GLsizei *length,
4565 void **pointer)
4566{
4567 if (!ValidateRobustEntryPoint(context, bufSize))
4568 {
4569 return false;
4570 }
4571
4572 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4573 {
4574 return false;
4575 }
4576
4577 if (!ValidateRobustBufferSize(context, bufSize, *length))
4578 {
4579 return false;
4580 }
4581
4582 return true;
4583}
4584
Geoff Lang0b031062016-10-13 14:30:04 -04004585bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4586 GLuint index,
4587 GLenum pname,
4588 GLsizei bufSize,
4589 GLsizei *length,
4590 GLint *params)
4591{
4592 if (!ValidateRobustEntryPoint(context, bufSize))
4593 {
4594 return false;
4595 }
4596
4597 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4598 {
4599 return false;
4600 }
4601
4602 if (!ValidateRobustBufferSize(context, bufSize, *length))
4603 {
4604 return false;
4605 }
4606
4607 return true;
4608}
4609
Geoff Lang0b031062016-10-13 14:30:04 -04004610bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4611 GLuint index,
4612 GLenum pname,
4613 GLsizei bufSize,
4614 GLsizei *length,
4615 GLuint *params)
4616{
4617 if (!ValidateRobustEntryPoint(context, bufSize))
4618 {
4619 return false;
4620 }
4621
4622 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4623 {
4624 return false;
4625 }
4626
4627 if (!ValidateRobustBufferSize(context, bufSize, *length))
4628 {
4629 return false;
4630 }
4631
4632 return true;
4633}
4634
Geoff Lang6899b872016-10-14 11:30:13 -04004635bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4636 GLuint program,
4637 GLuint uniformBlockIndex,
4638 GLenum pname,
4639 GLsizei bufSize,
4640 GLsizei *length,
4641 GLint *params)
4642{
4643 if (!ValidateRobustEntryPoint(context, bufSize))
4644 {
4645 return false;
4646 }
4647
4648 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4649 {
4650 return false;
4651 }
4652
4653 if (!ValidateRobustBufferSize(context, bufSize, *length))
4654 {
4655 return false;
4656 }
4657
4658 return true;
4659}
4660
Geoff Lang0a9661f2016-10-20 10:59:20 -07004661bool ValidateGetInternalFormativRobustANGLE(Context *context,
4662 GLenum target,
4663 GLenum internalformat,
4664 GLenum pname,
4665 GLsizei bufSize,
4666 GLsizei *length,
4667 GLint *params)
4668{
4669 if (!ValidateRobustEntryPoint(context, bufSize))
4670 {
4671 return false;
4672 }
4673
4674 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4675 {
4676 return false;
4677 }
4678
4679 if (!ValidateRobustBufferSize(context, bufSize, *length))
4680 {
4681 return false;
4682 }
4683
4684 return true;
4685}
4686
Jamie Madill5b772312018-03-08 20:28:32 -05004687bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08004688 GLuint attribIndex,
4689 GLint size,
4690 GLenum type,
4691 GLboolean pureInteger)
4692{
4693 const Caps &caps = context->getCaps();
4694 if (attribIndex >= caps.maxVertexAttributes)
4695 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004696 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004697 return false;
4698 }
4699
4700 if (size < 1 || size > 4)
4701 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004702 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004703 return false;
Shao80957d92017-02-20 21:25:59 +08004704 }
4705
4706 switch (type)
4707 {
4708 case GL_BYTE:
4709 case GL_UNSIGNED_BYTE:
4710 case GL_SHORT:
4711 case GL_UNSIGNED_SHORT:
4712 break;
4713
4714 case GL_INT:
4715 case GL_UNSIGNED_INT:
4716 if (context->getClientMajorVersion() < 3)
4717 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004718 context->handleError(InvalidEnum()
4719 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004720 return false;
4721 }
4722 break;
4723
4724 case GL_FIXED:
4725 case GL_FLOAT:
4726 if (pureInteger)
4727 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004728 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004729 return false;
4730 }
4731 break;
4732
4733 case GL_HALF_FLOAT:
4734 if (context->getClientMajorVersion() < 3)
4735 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004736 context->handleError(InvalidEnum()
4737 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004738 return false;
4739 }
4740 if (pureInteger)
4741 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004742 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004743 return false;
4744 }
4745 break;
4746
4747 case GL_INT_2_10_10_10_REV:
4748 case GL_UNSIGNED_INT_2_10_10_10_REV:
4749 if (context->getClientMajorVersion() < 3)
4750 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004751 context->handleError(InvalidEnum()
4752 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004753 return false;
4754 }
4755 if (pureInteger)
4756 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004757 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004758 return false;
4759 }
4760 if (size != 4)
4761 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004762 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4763 "UNSIGNED_INT_2_10_10_10_REV and "
4764 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004765 return false;
4766 }
4767 break;
4768
4769 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004770 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004771 return false;
4772 }
4773
4774 return true;
4775}
4776
Geoff Lang76e65652017-03-27 14:58:02 -04004777// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4778// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4779// specified clear value and the type of a buffer that is being cleared generates an
4780// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05004781bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04004782 GLint drawbuffer,
4783 const GLenum *validComponentTypes,
4784 size_t validComponentTypeCount)
4785{
4786 const FramebufferAttachment *attachment =
4787 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4788 if (attachment)
4789 {
4790 GLenum componentType = attachment->getFormat().info->componentType;
4791 const GLenum *end = validComponentTypes + validComponentTypeCount;
4792 if (std::find(validComponentTypes, end, componentType) == end)
4793 {
4794 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004795 InvalidOperation()
4796 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004797 return false;
4798 }
4799 }
4800
4801 return true;
4802}
4803
Jamie Madill5b772312018-03-08 20:28:32 -05004804bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04004805{
4806 if (!ValidateRobustEntryPoint(context, dataSize))
4807 {
4808 return false;
4809 }
4810
Corentin Wallez336129f2017-10-17 15:55:40 -04004811 gl::Buffer *pixelUnpackBuffer =
4812 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004813 if (pixelUnpackBuffer == nullptr)
4814 {
4815 if (dataSize < imageSize)
4816 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004817 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004818 }
4819 }
4820 return true;
4821}
4822
Jamie Madill5b772312018-03-08 20:28:32 -05004823bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004824 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004825 GLenum pname,
4826 bool pointerVersion,
4827 GLsizei *numParams)
4828{
4829 if (numParams)
4830 {
4831 *numParams = 0;
4832 }
4833
Corentin Walleze4477002017-12-01 14:39:58 -05004834 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004835 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004836 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004837 return false;
4838 }
4839
4840 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4841 if (!buffer)
4842 {
4843 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004844 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004845 return false;
4846 }
4847
4848 const Extensions &extensions = context->getExtensions();
4849
4850 switch (pname)
4851 {
4852 case GL_BUFFER_USAGE:
4853 case GL_BUFFER_SIZE:
4854 break;
4855
4856 case GL_BUFFER_ACCESS_OES:
4857 if (!extensions.mapBuffer)
4858 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004859 context->handleError(InvalidEnum()
4860 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004861 return false;
4862 }
4863 break;
4864
4865 case GL_BUFFER_MAPPED:
4866 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4867 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4868 !extensions.mapBufferRange)
4869 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004870 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4871 "GL_OES_mapbuffer or "
4872 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004873 return false;
4874 }
4875 break;
4876
4877 case GL_BUFFER_MAP_POINTER:
4878 if (!pointerVersion)
4879 {
4880 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004881 InvalidEnum()
4882 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004883 return false;
4884 }
4885 break;
4886
4887 case GL_BUFFER_ACCESS_FLAGS:
4888 case GL_BUFFER_MAP_OFFSET:
4889 case GL_BUFFER_MAP_LENGTH:
4890 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4891 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004892 context->handleError(InvalidEnum()
4893 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004894 return false;
4895 }
4896 break;
4897
4898 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004899 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004900 return false;
4901 }
4902
4903 // All buffer parameter queries return one value.
4904 if (numParams)
4905 {
4906 *numParams = 1;
4907 }
4908
4909 return true;
4910}
4911
4912bool ValidateGetRenderbufferParameterivBase(Context *context,
4913 GLenum target,
4914 GLenum pname,
4915 GLsizei *length)
4916{
4917 if (length)
4918 {
4919 *length = 0;
4920 }
4921
4922 if (target != GL_RENDERBUFFER)
4923 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004924 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004925 return false;
4926 }
4927
4928 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4929 if (renderbuffer == nullptr)
4930 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004931 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004932 return false;
4933 }
4934
4935 switch (pname)
4936 {
4937 case GL_RENDERBUFFER_WIDTH:
4938 case GL_RENDERBUFFER_HEIGHT:
4939 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4940 case GL_RENDERBUFFER_RED_SIZE:
4941 case GL_RENDERBUFFER_GREEN_SIZE:
4942 case GL_RENDERBUFFER_BLUE_SIZE:
4943 case GL_RENDERBUFFER_ALPHA_SIZE:
4944 case GL_RENDERBUFFER_DEPTH_SIZE:
4945 case GL_RENDERBUFFER_STENCIL_SIZE:
4946 break;
4947
4948 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4949 if (!context->getExtensions().framebufferMultisample)
4950 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004951 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004952 return false;
4953 }
4954 break;
4955
4956 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004957 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004958 return false;
4959 }
4960
4961 if (length)
4962 {
4963 *length = 1;
4964 }
4965 return true;
4966}
4967
4968bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4969{
4970 if (length)
4971 {
4972 *length = 0;
4973 }
4974
4975 if (GetValidShader(context, shader) == nullptr)
4976 {
4977 return false;
4978 }
4979
4980 switch (pname)
4981 {
4982 case GL_SHADER_TYPE:
4983 case GL_DELETE_STATUS:
4984 case GL_COMPILE_STATUS:
4985 case GL_INFO_LOG_LENGTH:
4986 case GL_SHADER_SOURCE_LENGTH:
4987 break;
4988
4989 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4990 if (!context->getExtensions().translatedShaderSource)
4991 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004992 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004993 return false;
4994 }
4995 break;
4996
4997 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004998 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004999 return false;
5000 }
5001
5002 if (length)
5003 {
5004 *length = 1;
5005 }
5006 return true;
5007}
5008
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005009bool ValidateGetTexParameterBase(Context *context,
5010 TextureType target,
5011 GLenum pname,
5012 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005013{
5014 if (length)
5015 {
5016 *length = 0;
5017 }
5018
5019 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5020 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005021 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005022 return false;
5023 }
5024
5025 if (context->getTargetTexture(target) == nullptr)
5026 {
5027 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005028 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005029 return false;
5030 }
5031
5032 switch (pname)
5033 {
5034 case GL_TEXTURE_MAG_FILTER:
5035 case GL_TEXTURE_MIN_FILTER:
5036 case GL_TEXTURE_WRAP_S:
5037 case GL_TEXTURE_WRAP_T:
5038 break;
5039
5040 case GL_TEXTURE_USAGE_ANGLE:
5041 if (!context->getExtensions().textureUsage)
5042 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005043 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005044 return false;
5045 }
5046 break;
5047
5048 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005049 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005050 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005051 return false;
5052 }
5053 break;
5054
5055 case GL_TEXTURE_IMMUTABLE_FORMAT:
5056 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5057 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005058 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005059 return false;
5060 }
5061 break;
5062
5063 case GL_TEXTURE_WRAP_R:
5064 case GL_TEXTURE_IMMUTABLE_LEVELS:
5065 case GL_TEXTURE_SWIZZLE_R:
5066 case GL_TEXTURE_SWIZZLE_G:
5067 case GL_TEXTURE_SWIZZLE_B:
5068 case GL_TEXTURE_SWIZZLE_A:
5069 case GL_TEXTURE_BASE_LEVEL:
5070 case GL_TEXTURE_MAX_LEVEL:
5071 case GL_TEXTURE_MIN_LOD:
5072 case GL_TEXTURE_MAX_LOD:
5073 case GL_TEXTURE_COMPARE_MODE:
5074 case GL_TEXTURE_COMPARE_FUNC:
5075 if (context->getClientMajorVersion() < 3)
5076 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005077 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005078 return false;
5079 }
5080 break;
5081
5082 case GL_TEXTURE_SRGB_DECODE_EXT:
5083 if (!context->getExtensions().textureSRGBDecode)
5084 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005085 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005086 return false;
5087 }
5088 break;
5089
Yunchao Hebacaa712018-01-30 14:01:39 +08005090 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5091 if (context->getClientVersion() < Version(3, 1))
5092 {
5093 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5094 return false;
5095 }
5096 break;
5097
Jamie Madillbe849e42017-05-02 15:49:00 -04005098 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005099 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005100 return false;
5101 }
5102
5103 if (length)
5104 {
5105 *length = 1;
5106 }
5107 return true;
5108}
5109
5110bool ValidateGetVertexAttribBase(Context *context,
5111 GLuint index,
5112 GLenum pname,
5113 GLsizei *length,
5114 bool pointer,
5115 bool pureIntegerEntryPoint)
5116{
5117 if (length)
5118 {
5119 *length = 0;
5120 }
5121
5122 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5123 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005124 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005125 return false;
5126 }
5127
5128 if (index >= context->getCaps().maxVertexAttributes)
5129 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005130 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005131 return false;
5132 }
5133
5134 if (pointer)
5135 {
5136 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5137 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005138 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005139 return false;
5140 }
5141 }
5142 else
5143 {
5144 switch (pname)
5145 {
5146 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5147 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5148 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5149 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5150 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5151 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5152 case GL_CURRENT_VERTEX_ATTRIB:
5153 break;
5154
5155 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5156 static_assert(
5157 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5158 "ANGLE extension enums not equal to GL enums.");
5159 if (context->getClientMajorVersion() < 3 &&
5160 !context->getExtensions().instancedArrays)
5161 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005162 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5163 "requires OpenGL ES 3.0 or "
5164 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005165 return false;
5166 }
5167 break;
5168
5169 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5170 if (context->getClientMajorVersion() < 3)
5171 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005172 context->handleError(
5173 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005174 return false;
5175 }
5176 break;
5177
5178 case GL_VERTEX_ATTRIB_BINDING:
5179 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5180 if (context->getClientVersion() < ES_3_1)
5181 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005182 context->handleError(InvalidEnum()
5183 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005184 return false;
5185 }
5186 break;
5187
5188 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005189 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005190 return false;
5191 }
5192 }
5193
5194 if (length)
5195 {
5196 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5197 {
5198 *length = 4;
5199 }
5200 else
5201 {
5202 *length = 1;
5203 }
5204 }
5205
5206 return true;
5207}
5208
Jamie Madill4928b7c2017-06-20 12:57:39 -04005209bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005210 GLint x,
5211 GLint y,
5212 GLsizei width,
5213 GLsizei height,
5214 GLenum format,
5215 GLenum type,
5216 GLsizei bufSize,
5217 GLsizei *length,
5218 GLsizei *columns,
5219 GLsizei *rows,
5220 void *pixels)
5221{
5222 if (length != nullptr)
5223 {
5224 *length = 0;
5225 }
5226 if (rows != nullptr)
5227 {
5228 *rows = 0;
5229 }
5230 if (columns != nullptr)
5231 {
5232 *columns = 0;
5233 }
5234
5235 if (width < 0 || height < 0)
5236 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005237 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005238 return false;
5239 }
5240
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005241 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005242
Jamie Madille98b1b52018-03-08 09:47:23 -05005243 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madillbe849e42017-05-02 15:49:00 -04005244 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005245 return false;
5246 }
5247
Jamie Madille98b1b52018-03-08 09:47:23 -05005248 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005249 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005250 return false;
5251 }
5252
Jamie Madill690c8eb2018-03-12 15:20:03 -04005253 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005254 ASSERT(framebuffer);
5255
5256 if (framebuffer->getReadBufferState() == GL_NONE)
5257 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005258 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005259 return false;
5260 }
5261
5262 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5263 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5264 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5265 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5266 // situation is an application error that would lead to a crash in ANGLE.
5267 if (readBuffer == nullptr)
5268 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005269 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005270 return false;
5271 }
5272
Martin Radev28031682017-07-28 14:47:56 +03005273 // ANGLE_multiview, Revision 1:
5274 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5275 // current read framebuffer is not NONE.
5276 if (readBuffer->getMultiviewLayout() != GL_NONE)
5277 {
5278 context->handleError(InvalidFramebufferOperation()
5279 << "Attempting to read from a multi-view framebuffer.");
5280 return false;
5281 }
5282
Geoff Lang280ba992017-04-18 16:30:58 -04005283 if (context->getExtensions().webglCompatibility)
5284 {
5285 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5286 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5287 // and type before validating the combination of format and type. However, the
5288 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5289 // verifies that GL_INVALID_OPERATION is generated.
5290 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5291 // dEQP/WebGL.
5292 if (!ValidReadPixelsFormatEnum(context, format))
5293 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005294 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005295 return false;
5296 }
5297
5298 if (!ValidReadPixelsTypeEnum(context, type))
5299 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005300 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005301 return false;
5302 }
5303 }
5304
Jamie Madill690c8eb2018-03-12 15:20:03 -04005305 GLenum currentFormat = GL_NONE;
5306 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5307
5308 GLenum currentType = GL_NONE;
5309 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5310
Jamie Madillbe849e42017-05-02 15:49:00 -04005311 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5312
5313 bool validFormatTypeCombination =
5314 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5315
5316 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5317 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005318 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005319 return false;
5320 }
5321
5322 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005323 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005324 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5325 {
5326 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005327 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005328 return false;
5329 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005330 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5331 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5332 {
5333 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5334 return false;
5335 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005336
5337 // .. the data would be packed to the buffer object such that the memory writes required
5338 // would exceed the data store size.
5339 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5340 const gl::Extents size(width, height, 1);
5341 const auto &pack = context->getGLState().getPackState();
5342
5343 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5344 if (endByteOrErr.isError())
5345 {
5346 context->handleError(endByteOrErr.getError());
5347 return false;
5348 }
5349
5350 size_t endByte = endByteOrErr.getResult();
5351 if (bufSize >= 0)
5352 {
5353 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5354 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005355 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005356 return false;
5357 }
5358 }
5359
5360 if (pixelPackBuffer != nullptr)
5361 {
5362 CheckedNumeric<size_t> checkedEndByte(endByte);
5363 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5364 checkedEndByte += checkedOffset;
5365
5366 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5367 {
5368 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005369 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005370 return false;
5371 }
5372 }
5373
5374 if (pixelPackBuffer == nullptr && length != nullptr)
5375 {
5376 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5377 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005378 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005379 return false;
5380 }
5381
5382 *length = static_cast<GLsizei>(endByte);
5383 }
5384
Geoff Langa953b522018-02-21 16:56:23 -05005385 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005386 angle::CheckedNumeric<int> clippedExtent(length);
5387 if (start < 0)
5388 {
5389 // "subtract" the area that is less than 0
5390 clippedExtent += start;
5391 }
5392
Geoff Langa953b522018-02-21 16:56:23 -05005393 angle::CheckedNumeric<int> readExtent = start;
5394 readExtent += length;
5395 if (!readExtent.IsValid())
5396 {
5397 return false;
5398 }
5399
5400 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005401 {
5402 // Subtract the region to the right of the read buffer
5403 clippedExtent -= (readExtent - bufferSize);
5404 }
5405
5406 if (!clippedExtent.IsValid())
5407 {
Geoff Langa953b522018-02-21 16:56:23 -05005408 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005409 }
5410
Geoff Langa953b522018-02-21 16:56:23 -05005411 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5412 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005413 };
5414
Geoff Langa953b522018-02-21 16:56:23 -05005415 GLsizei writtenColumns = 0;
5416 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5417 {
5418 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5419 return false;
5420 }
5421
5422 GLsizei writtenRows = 0;
5423 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5424 {
5425 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5426 return false;
5427 }
5428
Jamie Madillbe849e42017-05-02 15:49:00 -04005429 if (columns != nullptr)
5430 {
Geoff Langa953b522018-02-21 16:56:23 -05005431 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005432 }
5433
5434 if (rows != nullptr)
5435 {
Geoff Langa953b522018-02-21 16:56:23 -05005436 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005437 }
5438
5439 return true;
5440}
5441
5442template <typename ParamType>
5443bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005444 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005445 GLenum pname,
5446 GLsizei bufSize,
5447 const ParamType *params)
5448{
5449 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5450 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005451 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005452 return false;
5453 }
5454
5455 if (context->getTargetTexture(target) == nullptr)
5456 {
5457 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005458 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005459 return false;
5460 }
5461
5462 const GLsizei minBufSize = 1;
5463 if (bufSize >= 0 && bufSize < minBufSize)
5464 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005465 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005466 return false;
5467 }
5468
5469 switch (pname)
5470 {
5471 case GL_TEXTURE_WRAP_R:
5472 case GL_TEXTURE_SWIZZLE_R:
5473 case GL_TEXTURE_SWIZZLE_G:
5474 case GL_TEXTURE_SWIZZLE_B:
5475 case GL_TEXTURE_SWIZZLE_A:
5476 case GL_TEXTURE_BASE_LEVEL:
5477 case GL_TEXTURE_MAX_LEVEL:
5478 case GL_TEXTURE_COMPARE_MODE:
5479 case GL_TEXTURE_COMPARE_FUNC:
5480 case GL_TEXTURE_MIN_LOD:
5481 case GL_TEXTURE_MAX_LOD:
5482 if (context->getClientMajorVersion() < 3)
5483 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005484 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005485 return false;
5486 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005487 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005488 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005489 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5490 "available without "
5491 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005492 return false;
5493 }
5494 break;
5495
5496 default:
5497 break;
5498 }
5499
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005500 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005501 {
5502 switch (pname)
5503 {
5504 case GL_TEXTURE_MIN_FILTER:
5505 case GL_TEXTURE_MAG_FILTER:
5506 case GL_TEXTURE_WRAP_S:
5507 case GL_TEXTURE_WRAP_T:
5508 case GL_TEXTURE_WRAP_R:
5509 case GL_TEXTURE_MIN_LOD:
5510 case GL_TEXTURE_MAX_LOD:
5511 case GL_TEXTURE_COMPARE_MODE:
5512 case GL_TEXTURE_COMPARE_FUNC:
5513 context->handleError(InvalidEnum()
5514 << "Invalid parameter for 2D multisampled textures.");
5515 return false;
5516 }
5517 }
5518
Jamie Madillbe849e42017-05-02 15:49:00 -04005519 switch (pname)
5520 {
5521 case GL_TEXTURE_WRAP_S:
5522 case GL_TEXTURE_WRAP_T:
5523 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005524 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005525 bool restrictedWrapModes =
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005526 target == TextureType::External || target == TextureType::Rectangle;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005527 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5528 {
5529 return false;
5530 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005531 }
5532 break;
5533
5534 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005535 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005536 bool restrictedMinFilter =
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005537 target == TextureType::External || target == TextureType::Rectangle;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005538 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5539 {
5540 return false;
5541 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005542 }
5543 break;
5544
5545 case GL_TEXTURE_MAG_FILTER:
5546 if (!ValidateTextureMagFilterValue(context, params))
5547 {
5548 return false;
5549 }
5550 break;
5551
5552 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005553 if (!context->getExtensions().textureUsage)
5554 {
5555 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5556 return false;
5557 }
5558
Jamie Madillbe849e42017-05-02 15:49:00 -04005559 switch (ConvertToGLenum(params[0]))
5560 {
5561 case GL_NONE:
5562 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5563 break;
5564
5565 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005566 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005567 return false;
5568 }
5569 break;
5570
5571 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Jamie Madillbe849e42017-05-02 15:49:00 -04005572 {
Luc Ferron1b1a8642018-01-23 15:12:01 -05005573 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5574 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5575 {
5576 return false;
5577 }
5578 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
Jamie Madillbe849e42017-05-02 15:49:00 -04005579 }
5580 break;
5581
5582 case GL_TEXTURE_MIN_LOD:
5583 case GL_TEXTURE_MAX_LOD:
5584 // any value is permissible
5585 break;
5586
5587 case GL_TEXTURE_COMPARE_MODE:
5588 if (!ValidateTextureCompareModeValue(context, params))
5589 {
5590 return false;
5591 }
5592 break;
5593
5594 case GL_TEXTURE_COMPARE_FUNC:
5595 if (!ValidateTextureCompareFuncValue(context, params))
5596 {
5597 return false;
5598 }
5599 break;
5600
5601 case GL_TEXTURE_SWIZZLE_R:
5602 case GL_TEXTURE_SWIZZLE_G:
5603 case GL_TEXTURE_SWIZZLE_B:
5604 case GL_TEXTURE_SWIZZLE_A:
5605 switch (ConvertToGLenum(params[0]))
5606 {
5607 case GL_RED:
5608 case GL_GREEN:
5609 case GL_BLUE:
5610 case GL_ALPHA:
5611 case GL_ZERO:
5612 case GL_ONE:
5613 break;
5614
5615 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005616 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005617 return false;
5618 }
5619 break;
5620
5621 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005622 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005623 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005624 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005625 return false;
5626 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005627 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005628 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005629 context->handleError(InvalidOperation()
5630 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005631 return false;
5632 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005633 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005634 {
5635 context->handleError(InvalidOperation()
5636 << "Base level must be 0 for multisampled textures.");
5637 return false;
5638 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005639 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005640 {
5641 context->handleError(InvalidOperation()
5642 << "Base level must be 0 for rectangle textures.");
5643 return false;
5644 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005645 break;
5646
5647 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005648 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005649 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005650 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005651 return false;
5652 }
5653 break;
5654
5655 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5656 if (context->getClientVersion() < Version(3, 1))
5657 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005658 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005659 return false;
5660 }
5661 switch (ConvertToGLenum(params[0]))
5662 {
5663 case GL_DEPTH_COMPONENT:
5664 case GL_STENCIL_INDEX:
5665 break;
5666
5667 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005668 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005669 return false;
5670 }
5671 break;
5672
5673 case GL_TEXTURE_SRGB_DECODE_EXT:
5674 if (!ValidateTextureSRGBDecodeValue(context, params))
5675 {
5676 return false;
5677 }
5678 break;
5679
5680 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005681 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005682 return false;
5683 }
5684
5685 return true;
5686}
5687
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005688template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
5689template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04005690
Jamie Madill5b772312018-03-08 20:28:32 -05005691bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04005692{
5693 if (index >= MAX_VERTEX_ATTRIBS)
5694 {
5695 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5696 return false;
5697 }
5698
5699 return true;
5700}
5701
5702bool ValidateGetActiveUniformBlockivBase(Context *context,
5703 GLuint program,
5704 GLuint uniformBlockIndex,
5705 GLenum pname,
5706 GLsizei *length)
5707{
5708 if (length)
5709 {
5710 *length = 0;
5711 }
5712
5713 if (context->getClientMajorVersion() < 3)
5714 {
5715 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5716 return false;
5717 }
5718
5719 Program *programObject = GetValidProgram(context, program);
5720 if (!programObject)
5721 {
5722 return false;
5723 }
5724
5725 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5726 {
5727 context->handleError(InvalidValue()
5728 << "uniformBlockIndex exceeds active uniform block count.");
5729 return false;
5730 }
5731
5732 switch (pname)
5733 {
5734 case GL_UNIFORM_BLOCK_BINDING:
5735 case GL_UNIFORM_BLOCK_DATA_SIZE:
5736 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5737 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5738 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5739 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5740 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5741 break;
5742
5743 default:
5744 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5745 return false;
5746 }
5747
5748 if (length)
5749 {
5750 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5751 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005752 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005753 programObject->getUniformBlockByIndex(uniformBlockIndex);
5754 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5755 }
5756 else
5757 {
5758 *length = 1;
5759 }
5760 }
5761
5762 return true;
5763}
5764
Jamie Madill9696d072017-08-26 23:19:57 -04005765template <typename ParamType>
5766bool ValidateSamplerParameterBase(Context *context,
5767 GLuint sampler,
5768 GLenum pname,
5769 GLsizei bufSize,
5770 ParamType *params)
5771{
5772 if (context->getClientMajorVersion() < 3)
5773 {
5774 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5775 return false;
5776 }
5777
5778 if (!context->isSampler(sampler))
5779 {
5780 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5781 return false;
5782 }
5783
5784 const GLsizei minBufSize = 1;
5785 if (bufSize >= 0 && bufSize < minBufSize)
5786 {
5787 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5788 return false;
5789 }
5790
5791 switch (pname)
5792 {
5793 case GL_TEXTURE_WRAP_S:
5794 case GL_TEXTURE_WRAP_T:
5795 case GL_TEXTURE_WRAP_R:
5796 if (!ValidateTextureWrapModeValue(context, params, false))
5797 {
5798 return false;
5799 }
5800 break;
5801
5802 case GL_TEXTURE_MIN_FILTER:
5803 if (!ValidateTextureMinFilterValue(context, params, false))
5804 {
5805 return false;
5806 }
5807 break;
5808
5809 case GL_TEXTURE_MAG_FILTER:
5810 if (!ValidateTextureMagFilterValue(context, params))
5811 {
5812 return false;
5813 }
5814 break;
5815
5816 case GL_TEXTURE_MIN_LOD:
5817 case GL_TEXTURE_MAX_LOD:
5818 // any value is permissible
5819 break;
5820
5821 case GL_TEXTURE_COMPARE_MODE:
5822 if (!ValidateTextureCompareModeValue(context, params))
5823 {
5824 return false;
5825 }
5826 break;
5827
5828 case GL_TEXTURE_COMPARE_FUNC:
5829 if (!ValidateTextureCompareFuncValue(context, params))
5830 {
5831 return false;
5832 }
5833 break;
5834
5835 case GL_TEXTURE_SRGB_DECODE_EXT:
5836 if (!ValidateTextureSRGBDecodeValue(context, params))
5837 {
5838 return false;
5839 }
5840 break;
5841
Luc Ferron1b1a8642018-01-23 15:12:01 -05005842 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5843 {
5844 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5845 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5846 {
5847 return false;
5848 }
5849 }
5850 break;
5851
Jamie Madill9696d072017-08-26 23:19:57 -04005852 default:
5853 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5854 return false;
5855 }
5856
5857 return true;
5858}
5859
5860template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5861template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5862
5863bool ValidateGetSamplerParameterBase(Context *context,
5864 GLuint sampler,
5865 GLenum pname,
5866 GLsizei *length)
5867{
5868 if (length)
5869 {
5870 *length = 0;
5871 }
5872
5873 if (context->getClientMajorVersion() < 3)
5874 {
5875 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5876 return false;
5877 }
5878
5879 if (!context->isSampler(sampler))
5880 {
5881 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5882 return false;
5883 }
5884
5885 switch (pname)
5886 {
5887 case GL_TEXTURE_WRAP_S:
5888 case GL_TEXTURE_WRAP_T:
5889 case GL_TEXTURE_WRAP_R:
5890 case GL_TEXTURE_MIN_FILTER:
5891 case GL_TEXTURE_MAG_FILTER:
5892 case GL_TEXTURE_MIN_LOD:
5893 case GL_TEXTURE_MAX_LOD:
5894 case GL_TEXTURE_COMPARE_MODE:
5895 case GL_TEXTURE_COMPARE_FUNC:
5896 break;
5897
Luc Ferron1b1a8642018-01-23 15:12:01 -05005898 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5899 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
5900 {
5901 return false;
5902 }
5903 break;
5904
Jamie Madill9696d072017-08-26 23:19:57 -04005905 case GL_TEXTURE_SRGB_DECODE_EXT:
5906 if (!context->getExtensions().textureSRGBDecode)
5907 {
5908 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5909 return false;
5910 }
5911 break;
5912
5913 default:
5914 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5915 return false;
5916 }
5917
5918 if (length)
5919 {
5920 *length = 1;
5921 }
5922 return true;
5923}
5924
5925bool ValidateGetInternalFormativBase(Context *context,
5926 GLenum target,
5927 GLenum internalformat,
5928 GLenum pname,
5929 GLsizei bufSize,
5930 GLsizei *numParams)
5931{
5932 if (numParams)
5933 {
5934 *numParams = 0;
5935 }
5936
5937 if (context->getClientMajorVersion() < 3)
5938 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005939 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005940 return false;
5941 }
5942
5943 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5944 if (!formatCaps.renderable)
5945 {
5946 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5947 return false;
5948 }
5949
5950 switch (target)
5951 {
5952 case GL_RENDERBUFFER:
5953 break;
5954
5955 case GL_TEXTURE_2D_MULTISAMPLE:
5956 if (context->getClientVersion() < ES_3_1)
5957 {
5958 context->handleError(InvalidOperation()
5959 << "Texture target requires at least OpenGL ES 3.1.");
5960 return false;
5961 }
5962 break;
5963
5964 default:
5965 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5966 return false;
5967 }
5968
5969 if (bufSize < 0)
5970 {
5971 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5972 return false;
5973 }
5974
5975 GLsizei maxWriteParams = 0;
5976 switch (pname)
5977 {
5978 case GL_NUM_SAMPLE_COUNTS:
5979 maxWriteParams = 1;
5980 break;
5981
5982 case GL_SAMPLES:
5983 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5984 break;
5985
5986 default:
5987 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5988 return false;
5989 }
5990
5991 if (numParams)
5992 {
5993 // glGetInternalFormativ will not overflow bufSize
5994 *numParams = std::min(bufSize, maxWriteParams);
5995 }
5996
5997 return true;
5998}
5999
Jamie Madille98b1b52018-03-08 09:47:23 -05006000// We should check with Khronos if returning INVALID_FRAMEBUFFER_OPERATION is OK when querying
6001// implementation format info for incomplete framebuffers. It seems like these queries are
6002// incongruent with the other errors.
6003bool ValidateFramebufferComplete(Context *context, Framebuffer *framebuffer, bool isFramebufferOp)
6004{
6005 bool complete = false;
6006 ANGLE_VALIDATION_TRY(framebuffer->isComplete(context, &complete));
6007 if (!complete)
6008 {
6009 if (isFramebufferOp)
6010 {
6011 context->handleError(InvalidFramebufferOperation());
6012 }
6013 else
6014 {
6015 context->handleError(InvalidOperation());
6016 }
6017 return false;
6018 }
6019 return true;
6020}
6021
6022bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6023{
6024 GLint samples = 0;
6025 ANGLE_VALIDATION_TRY(framebuffer->getSamples(context, &samples));
6026 if (samples != 0)
6027 {
6028 context->handleError(InvalidOperation());
6029 return false;
6030 }
6031 return true;
6032}
6033
Jamie Madillc29968b2016-01-20 11:17:23 -05006034} // namespace gl