blob: ea6add8c5c3803d39fe8111451ec7ab34b41d659 [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 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002518 const FramebufferAttachment *dsAttachment =
2519 framebuffer->getStencilOrDepthStencilAttachment();
2520 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002521 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002522 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002523
2524 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2525 bool differentWritemasks =
2526 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2527 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2528 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2529 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2530
2531 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002532 {
Martin Radevffe754b2017-07-31 10:38:07 +03002533 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002534 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002535 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2536 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002537 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002538 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002539 return false;
2540 }
Jamie Madillac528012014-06-20 13:21:23 -04002541 }
2542
Jamie Madille98b1b52018-03-08 09:47:23 -05002543 if (!ValidateFramebufferComplete(context, framebuffer, true))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002544 {
Geoff Langb1196682014-07-23 13:47:29 -04002545 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002546 }
2547
Geoff Lang7dd2e102014-11-10 15:19:26 -05002548 gl::Program *program = state.getProgram();
2549 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002550 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002551 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002552 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002553 }
2554
Yunchao Hecddcb592017-11-13 15:27:35 +08002555 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2556 // vertex shader stage or fragment shader stage is a undefined behaviour.
2557 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2558 // produce undefined result.
Yunchao Heece12532017-11-21 15:50:21 +08002559 if (!program->hasLinkedVertexShader() || !program->hasLinkedFragmentShader())
Yunchao Hecddcb592017-11-13 15:27:35 +08002560 {
2561 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2562 "vertex shader stage or fragment shader stage.");
2563 return false;
2564 }
2565
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002566 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002567 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002568 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002569 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002570 }
2571
Martin Radevffe754b2017-07-31 10:38:07 +03002572 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002573 {
Martin Radevda8e2572017-09-12 17:21:16 +03002574 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002575 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002576 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002577 {
2578 context->handleError(InvalidOperation() << "The number of views in the active program "
2579 "and draw framebuffer does not match.");
2580 return false;
2581 }
Martin Radev7e69f762017-07-27 14:54:13 +03002582
2583 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2584 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2585 framebufferNumViews > 1)
2586 {
2587 context->handleError(InvalidOperation()
2588 << "There is an active transform feedback object "
2589 "when the number of views in the active draw "
2590 "framebuffer is greater than 1.");
2591 return false;
2592 }
Martin Radevffe754b2017-07-31 10:38:07 +03002593
2594 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2595 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2596 {
2597 context->handleError(InvalidOperation() << "There is an active query for target "
2598 "GL_TIME_ELAPSED_EXT when the number of "
2599 "views in the active draw framebuffer is "
2600 "greater than 1.");
2601 return false;
2602 }
Martin Radev7cf61662017-07-26 17:10:53 +03002603 }
2604
Jiawei Shaofccebff2018-03-08 13:51:02 +08002605 // Do geometry shader specific validations
2606 if (program->hasLinkedGeometryShader())
2607 {
2608 if (!IsCompatibleDrawModeWithGeometryShader(mode,
2609 program->getGeometryShaderInputPrimitiveType()))
2610 {
2611 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2612 IncompatibleDrawModeAgainstGeometryShader);
2613 return false;
2614 }
2615 }
2616
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002617 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002618 for (unsigned int uniformBlockIndex = 0;
2619 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002620 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002621 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002622 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002623 const OffsetBindingPointer<Buffer> &uniformBuffer =
2624 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002625
Geoff Lang5d124a62015-09-15 13:03:27 -04002626 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002627 {
2628 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002629 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002630 InvalidOperation()
2631 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002632 return false;
2633 }
2634
Geoff Lang5d124a62015-09-15 13:03:27 -04002635 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002636 if (uniformBufferSize == 0)
2637 {
2638 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002639 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002640 }
2641
Jamie Madill62d31cb2015-09-11 13:25:51 -04002642 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002643 {
2644 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002645 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002646 InvalidOperation()
2647 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002648 return false;
2649 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002650
2651 if (extensions.webglCompatibility &&
2652 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2653 {
2654 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2655 UniformBufferBoundForTransformFeedback);
2656 return false;
2657 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002658 }
2659
Geoff Lange0cff192017-05-30 13:04:56 -04002660 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002661 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002662 {
James Darpiniane8a93c62018-01-04 18:02:24 -08002663 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2664 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2665 transformFeedbackObject->buffersBoundForOtherUse())
2666 {
2667 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferDoubleBound);
2668 return false;
2669 }
Geoff Lange0cff192017-05-30 13:04:56 -04002670 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002671 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2672 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002673 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002674 return false;
2675 }
Geoff Lange0cff192017-05-30 13:04:56 -04002676
Geoff Lang9ab5b822017-05-30 16:19:23 -04002677 // Detect that the vertex shader input types match the attribute types
2678 if (!ValidateVertexShaderAttributeTypeMatch(context))
2679 {
2680 return false;
2681 }
2682
Geoff Lange0cff192017-05-30 13:04:56 -04002683 // Detect that the color buffer types match the fragment shader output types
2684 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2685 {
2686 return false;
2687 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002688 }
2689
Jamie Madill9fdaa492018-02-16 10:52:11 -05002690 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002691}
2692
Jamie Madill5b772312018-03-08 20:28:32 -05002693bool ValidateDrawArraysCommon(Context *context,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002694 GLenum mode,
2695 GLint first,
2696 GLsizei count,
2697 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002698{
Jamie Madillfd716582014-06-06 17:09:04 -04002699 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002700 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002701 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002702 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002703 }
2704
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002705 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002706 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002707 if (curTransformFeedback && curTransformFeedback->isActive() &&
2708 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002709 {
2710 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002711 // that does not match the current transform feedback object's draw mode (if transform
2712 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002713 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002714 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002715 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002716 }
2717
Jiajia Qind9671222016-11-29 16:30:31 +08002718 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002719 {
2720 return false;
2721 }
2722
Corentin Wallez71168a02016-12-19 15:11:18 -08002723 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002724 // - first < 0 has been checked as an error condition.
2725 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002726 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002727 ASSERT(first >= 0);
2728 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002729 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002730 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2731 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2732 {
2733 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2734 return false;
2735 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002736
Jamie Madill9fdaa492018-02-16 10:52:11 -05002737 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2738 {
2739 return false;
2740 }
Jamie Madillfd716582014-06-06 17:09:04 -04002741 }
2742
2743 return true;
2744}
2745
He Yunchaoced53ae2016-11-29 15:00:51 +08002746bool ValidateDrawArraysInstancedANGLE(Context *context,
2747 GLenum mode,
2748 GLint first,
2749 GLsizei count,
2750 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002751{
Geoff Lang63c5a592017-09-27 14:08:16 -04002752 if (!context->getExtensions().instancedArrays)
2753 {
2754 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2755 return false;
2756 }
2757
Corentin Wallez170efbf2017-05-02 13:45:01 -04002758 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002759 {
2760 return false;
2761 }
2762
Corentin Wallez0dc97812017-06-22 14:38:44 -04002763 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002764}
2765
Jamie Madill5b772312018-03-08 20:28:32 -05002766bool ValidateDrawElementsBase(Context *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002767{
Jamie Madill250d33f2014-06-06 17:09:03 -04002768 switch (type)
2769 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002770 case GL_UNSIGNED_BYTE:
2771 case GL_UNSIGNED_SHORT:
2772 break;
2773 case GL_UNSIGNED_INT:
2774 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2775 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002776 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002777 return false;
2778 }
2779 break;
2780 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002781 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002782 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002783 }
2784
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002785 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002786
2787 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002788 if (curTransformFeedback && curTransformFeedback->isActive() &&
2789 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002790 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002791 // It is an invalid operation to call DrawElements, DrawRangeElements or
2792 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002793 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002794 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002795 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002796 }
2797
Jiajia Qind9671222016-11-29 16:30:31 +08002798 return true;
2799}
2800
Jamie Madill5b772312018-03-08 20:28:32 -05002801bool ValidateDrawElementsCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002802 GLenum mode,
2803 GLsizei count,
2804 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002805 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002806 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002807{
2808 if (!ValidateDrawElementsBase(context, type))
2809 return false;
2810
2811 const State &state = context->getGLState();
2812
Corentin Wallez170efbf2017-05-02 13:45:01 -04002813 if (!ValidateDrawBase(context, mode, count))
2814 {
2815 return false;
2816 }
2817
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002818 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2819 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2820 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2821 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002822 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002823 // Check for mapped buffers
2824 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002825 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002826 {
2827 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2828 return false;
2829 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002830 }
2831
He Yunchaoced53ae2016-11-29 15:00:51 +08002832 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002833 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002834
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002835 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2836
2837 if (context->getExtensions().webglCompatibility)
2838 {
2839 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2840 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2841 {
2842 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2843 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2844 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002845 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002846 return false;
2847 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002848
2849 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2850 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2851 // error is generated.
2852 if (reinterpret_cast<intptr_t>(indices) < 0)
2853 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002854 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002855 return false;
2856 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002857 }
2858
2859 if (context->getExtensions().webglCompatibility ||
2860 !context->getGLState().areClientArraysEnabled())
2861 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002862 if (!elementArrayBuffer && count > 0)
2863 {
2864 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2865 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2866 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002867 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002868 return false;
2869 }
2870 }
2871
Jamie Madill9fdaa492018-02-16 10:52:11 -05002872 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04002873 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002874 // This is an application error that would normally result in a crash, but we catch it and
2875 // return an error
2876 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
2877 return false;
2878 }
2879
2880 if (count > 0 && elementArrayBuffer)
2881 {
2882 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2883 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2884 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2885 constexpr uint64_t kMaxTypeSize = 8;
2886 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2887 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2888 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
2889
2890 uint64_t typeSize = typeBytes;
2891 uint64_t elementCount = static_cast<uint64_t>(count);
2892 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2893
2894 // Doing the multiplication here is overflow-safe
2895 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2896
2897 // The offset can be any value, check for overflows
2898 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2899 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04002900 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002901 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2902 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002903 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05002904
2905 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2906 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002907 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002908 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
2909 return false;
2910 }
2911
2912 ASSERT(isPow2(typeSize) && typeSize > 0);
2913 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
2914 {
2915 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04002916 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002917 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002918
2919 if (context->getExtensions().webglCompatibility &&
2920 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
2921 {
2922 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2923 ElementArrayBufferBoundForTransformFeedback);
2924 return false;
2925 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002926 }
2927
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002928 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002929 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002930 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2931 // access is enabled.
2932 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2933 {
2934 return false;
2935 }
2936 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05002937 else if (count == 0)
2938 {
2939 // ValidateDrawAttribs also does some extra validation that is independent of the vertex
2940 // count.
2941 if (!ValidateDrawAttribs(context, 0, 0, 0))
2942 {
2943 return false;
2944 }
2945 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002946 else
2947 {
2948 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04002949 const DrawCallParams &params = context->getParams<DrawCallParams>();
2950 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
2951 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002952
2953 // If we use an index greater than our maximum supported index range, return an error.
2954 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2955 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04002956 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002957 {
2958 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2959 return false;
2960 }
2961
Jamie Madill6f5444d2018-03-14 10:08:11 -04002962 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end),
2963 static_cast<GLint>(indexRange.vertexCount())))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002964 {
2965 return false;
2966 }
2967
2968 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04002969 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002970 }
2971
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002972 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002973}
2974
Jamie Madill5b772312018-03-08 20:28:32 -05002975bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002976 GLenum mode,
2977 GLsizei count,
2978 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002979 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002980 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002981{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002982 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002983}
2984
Geoff Lang3edfe032015-09-04 16:38:24 -04002985bool ValidateDrawElementsInstancedANGLE(Context *context,
2986 GLenum mode,
2987 GLsizei count,
2988 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002989 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002990 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002991{
Geoff Lang63c5a592017-09-27 14:08:16 -04002992 if (!context->getExtensions().instancedArrays)
2993 {
2994 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2995 return false;
2996 }
2997
Corentin Wallez170efbf2017-05-02 13:45:01 -04002998 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002999 {
3000 return false;
3001 }
3002
Corentin Wallez0dc97812017-06-22 14:38:44 -04003003 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003004}
3005
He Yunchaoced53ae2016-11-29 15:00:51 +08003006bool ValidateFramebufferTextureBase(Context *context,
3007 GLenum target,
3008 GLenum attachment,
3009 GLuint texture,
3010 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003011{
Geoff Lange8afa902017-09-27 15:00:43 -04003012 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003013 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003014 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003015 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003016 }
3017
3018 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003019 {
3020 return false;
3021 }
3022
Jamie Madill55ec3b12014-07-03 10:38:57 -04003023 if (texture != 0)
3024 {
3025 gl::Texture *tex = context->getTexture(texture);
3026
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003027 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003028 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003029 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003030 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003031 }
3032
3033 if (level < 0)
3034 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003035 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003036 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003037 }
3038 }
3039
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003040 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003041 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003042
Jamie Madill84115c92015-04-23 15:00:07 -04003043 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003044 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003045 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003046 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003047 }
3048
3049 return true;
3050}
3051
Geoff Langb1196682014-07-23 13:47:29 -04003052bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003053{
3054 if (program == 0)
3055 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003056 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003057 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003058 }
3059
Dian Xiang769769a2015-09-09 15:20:08 -07003060 gl::Program *programObject = GetValidProgram(context, program);
3061 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003062 {
3063 return false;
3064 }
3065
Jamie Madill0063c512014-08-25 15:47:53 -04003066 if (!programObject || !programObject->isLinked())
3067 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003068 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003069 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003070 }
3071
Geoff Lang7dd2e102014-11-10 15:19:26 -05003072 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003073 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003074 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003075 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003076 }
3077
Jamie Madill0063c512014-08-25 15:47:53 -04003078 return true;
3079}
3080
Geoff Langf41d0ee2016-10-07 13:04:23 -04003081static bool ValidateSizedGetUniform(Context *context,
3082 GLuint program,
3083 GLint location,
3084 GLsizei bufSize,
3085 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003086{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003087 if (length)
3088 {
3089 *length = 0;
3090 }
3091
Jamie Madill78f41802014-08-25 15:47:55 -04003092 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003093 {
Jamie Madill78f41802014-08-25 15:47:55 -04003094 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003095 }
3096
Geoff Langf41d0ee2016-10-07 13:04:23 -04003097 if (bufSize < 0)
3098 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003099 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003100 return false;
3101 }
3102
Jamie Madilla502c742014-08-28 17:19:13 -04003103 gl::Program *programObject = context->getProgram(program);
3104 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003105
Jamie Madill78f41802014-08-25 15:47:55 -04003106 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003107 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003108 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003109 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003110 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003111 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003112 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003113 }
3114
Geoff Langf41d0ee2016-10-07 13:04:23 -04003115 if (length)
3116 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003117 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003118 }
3119
Jamie Madill0063c512014-08-25 15:47:53 -04003120 return true;
3121}
3122
He Yunchaoced53ae2016-11-29 15:00:51 +08003123bool ValidateGetnUniformfvEXT(Context *context,
3124 GLuint program,
3125 GLint location,
3126 GLsizei bufSize,
3127 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003128{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003129 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003130}
3131
He Yunchaoced53ae2016-11-29 15:00:51 +08003132bool ValidateGetnUniformivEXT(Context *context,
3133 GLuint program,
3134 GLint location,
3135 GLsizei bufSize,
3136 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003137{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003138 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3139}
3140
3141bool ValidateGetUniformfvRobustANGLE(Context *context,
3142 GLuint program,
3143 GLint location,
3144 GLsizei bufSize,
3145 GLsizei *length,
3146 GLfloat *params)
3147{
3148 if (!ValidateRobustEntryPoint(context, bufSize))
3149 {
3150 return false;
3151 }
3152
3153 // bufSize is validated in ValidateSizedGetUniform
3154 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3155}
3156
3157bool ValidateGetUniformivRobustANGLE(Context *context,
3158 GLuint program,
3159 GLint location,
3160 GLsizei bufSize,
3161 GLsizei *length,
3162 GLint *params)
3163{
3164 if (!ValidateRobustEntryPoint(context, bufSize))
3165 {
3166 return false;
3167 }
3168
3169 // bufSize is validated in ValidateSizedGetUniform
3170 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3171}
3172
3173bool ValidateGetUniformuivRobustANGLE(Context *context,
3174 GLuint program,
3175 GLint location,
3176 GLsizei bufSize,
3177 GLsizei *length,
3178 GLuint *params)
3179{
3180 if (!ValidateRobustEntryPoint(context, bufSize))
3181 {
3182 return false;
3183 }
3184
3185 if (context->getClientMajorVersion() < 3)
3186 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003187 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003188 return false;
3189 }
3190
3191 // bufSize is validated in ValidateSizedGetUniform
3192 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003193}
3194
He Yunchaoced53ae2016-11-29 15:00:51 +08003195bool ValidateDiscardFramebufferBase(Context *context,
3196 GLenum target,
3197 GLsizei numAttachments,
3198 const GLenum *attachments,
3199 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003200{
3201 if (numAttachments < 0)
3202 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003203 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003204 return false;
3205 }
3206
3207 for (GLsizei i = 0; i < numAttachments; ++i)
3208 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003209 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003210 {
3211 if (defaultFramebuffer)
3212 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003213 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003214 return false;
3215 }
3216
3217 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3218 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003219 context->handleError(InvalidOperation() << "Requested color attachment is "
3220 "greater than the maximum supported "
3221 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003222 return false;
3223 }
3224 }
3225 else
3226 {
3227 switch (attachments[i])
3228 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003229 case GL_DEPTH_ATTACHMENT:
3230 case GL_STENCIL_ATTACHMENT:
3231 case GL_DEPTH_STENCIL_ATTACHMENT:
3232 if (defaultFramebuffer)
3233 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003234 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3235 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003236 return false;
3237 }
3238 break;
3239 case GL_COLOR:
3240 case GL_DEPTH:
3241 case GL_STENCIL:
3242 if (!defaultFramebuffer)
3243 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003244 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3245 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003246 return false;
3247 }
3248 break;
3249 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003250 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003251 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003252 }
3253 }
3254 }
3255
3256 return true;
3257}
3258
Austin Kinross6ee1e782015-05-29 17:05:37 -07003259bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3260{
Jamie Madill007530e2017-12-28 14:27:04 -05003261 if (!context->getExtensions().debugMarker)
3262 {
3263 // The debug marker calls should not set error state
3264 // However, it seems reasonable to set an error state if the extension is not enabled
3265 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3266 return false;
3267 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003268
Jamie Madill007530e2017-12-28 14:27:04 -05003269 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003270 if (length < 0)
3271 {
3272 return false;
3273 }
3274
3275 if (marker == nullptr)
3276 {
3277 return false;
3278 }
3279
3280 return true;
3281}
3282
3283bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3284{
Jamie Madill007530e2017-12-28 14:27:04 -05003285 if (!context->getExtensions().debugMarker)
3286 {
3287 // The debug marker calls should not set error state
3288 // However, it seems reasonable to set an error state if the extension is not enabled
3289 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3290 return false;
3291 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003292
Jamie Madill007530e2017-12-28 14:27:04 -05003293 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003294 if (length < 0)
3295 {
3296 return false;
3297 }
3298
3299 if (length > 0 && marker == nullptr)
3300 {
3301 return false;
3302 }
3303
3304 return true;
3305}
3306
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003307bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003308{
Geoff Langa8406172015-07-21 16:53:39 -04003309 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3310 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003311 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003312 return false;
3313 }
3314
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003315 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003316 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003317 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003318 if (!context->getExtensions().eglImage)
3319 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003320 context->handleError(InvalidEnum()
3321 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003322 }
3323 break;
3324
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003325 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003326 if (!context->getExtensions().eglImageExternal)
3327 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003328 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3329 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003330 }
Geoff Langa8406172015-07-21 16:53:39 -04003331 break;
3332
3333 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003334 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003335 return false;
3336 }
3337
Jamie Madill007530e2017-12-28 14:27:04 -05003338 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3339
Jamie Madill61e16b42017-06-19 11:13:23 -04003340 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003341 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003342 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003343 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003344 return false;
3345 }
3346
Jamie Madill007530e2017-12-28 14:27:04 -05003347 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003348 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003349 context->handleError(InvalidOperation()
3350 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003351 return false;
3352 }
3353
Geoff Langca271392017-04-05 12:30:00 -04003354 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003355 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003356 if (!textureCaps.texturable)
3357 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003358 context->handleError(InvalidOperation()
3359 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003360 return false;
3361 }
3362
Geoff Langdcab33b2015-07-21 13:03:16 -04003363 return true;
3364}
3365
3366bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003367 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003368 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003369{
Geoff Langa8406172015-07-21 16:53:39 -04003370 if (!context->getExtensions().eglImage)
3371 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003372 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003373 return false;
3374 }
3375
3376 switch (target)
3377 {
3378 case GL_RENDERBUFFER:
3379 break;
3380
3381 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003382 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003383 return false;
3384 }
3385
Jamie Madill007530e2017-12-28 14:27:04 -05003386 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3387
Jamie Madill61e16b42017-06-19 11:13:23 -04003388 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003389 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003390 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003391 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003392 return false;
3393 }
3394
Geoff Langca271392017-04-05 12:30:00 -04003395 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003396 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003397 if (!textureCaps.renderable)
3398 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003399 context->handleError(InvalidOperation()
3400 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003401 return false;
3402 }
3403
Geoff Langdcab33b2015-07-21 13:03:16 -04003404 return true;
3405}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003406
3407bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3408{
Geoff Lang36167ab2015-12-07 10:27:14 -05003409 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003410 {
3411 // The default VAO should always exist
3412 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003413 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003414 return false;
3415 }
3416
3417 return true;
3418}
3419
Geoff Langc5629752015-12-07 16:29:04 -05003420bool ValidateProgramBinaryBase(Context *context,
3421 GLuint program,
3422 GLenum binaryFormat,
3423 const void *binary,
3424 GLint length)
3425{
3426 Program *programObject = GetValidProgram(context, program);
3427 if (programObject == nullptr)
3428 {
3429 return false;
3430 }
3431
3432 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3433 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3434 programBinaryFormats.end())
3435 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003436 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003437 return false;
3438 }
3439
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003440 if (context->hasActiveTransformFeedback(program))
3441 {
3442 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003443 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3444 "is associated with an active transform "
3445 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003446 return false;
3447 }
3448
Geoff Langc5629752015-12-07 16:29:04 -05003449 return true;
3450}
3451
3452bool ValidateGetProgramBinaryBase(Context *context,
3453 GLuint program,
3454 GLsizei bufSize,
3455 GLsizei *length,
3456 GLenum *binaryFormat,
3457 void *binary)
3458{
3459 Program *programObject = GetValidProgram(context, program);
3460 if (programObject == nullptr)
3461 {
3462 return false;
3463 }
3464
3465 if (!programObject->isLinked())
3466 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003467 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003468 return false;
3469 }
3470
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003471 if (context->getCaps().programBinaryFormats.empty())
3472 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003473 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003474 return false;
3475 }
3476
Geoff Langc5629752015-12-07 16:29:04 -05003477 return true;
3478}
Jamie Madillc29968b2016-01-20 11:17:23 -05003479
Jamie Madill5b772312018-03-08 20:28:32 -05003480bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003481{
3482 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003483 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003484 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003485 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3486 return false;
3487 }
3488 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3489 {
3490 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003491 return false;
3492 }
3493
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003494 ASSERT(context->getGLState().getDrawFramebuffer());
3495 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003496 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3497
3498 // This should come first before the check for the default frame buffer
3499 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3500 // rather than INVALID_OPERATION
3501 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3502 {
3503 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3504
3505 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003506 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3507 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003508 {
3509 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003510 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3511 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3512 // 3.1 is still a bit ambiguous about the error, but future specs are
3513 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003514 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003515 return false;
3516 }
3517 else if (bufs[colorAttachment] >= maxColorAttachment)
3518 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003519 context->handleError(InvalidOperation()
3520 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003521 return false;
3522 }
3523 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3524 frameBufferId != 0)
3525 {
3526 // INVALID_OPERATION-GL is bound to buffer and ith argument
3527 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003528 context->handleError(InvalidOperation()
3529 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003530 return false;
3531 }
3532 }
3533
3534 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3535 // and n is not 1 or bufs is bound to value other than BACK and NONE
3536 if (frameBufferId == 0)
3537 {
3538 if (n != 1)
3539 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003540 context->handleError(InvalidOperation()
3541 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003542 return false;
3543 }
3544
3545 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3546 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003547 context->handleError(
3548 InvalidOperation()
3549 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003550 return false;
3551 }
3552 }
3553
3554 return true;
3555}
3556
Geoff Lang496c02d2016-10-20 11:38:11 -07003557bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003558 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003559 GLenum pname,
3560 GLsizei *length,
3561 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003562{
Geoff Lang496c02d2016-10-20 11:38:11 -07003563 if (length)
3564 {
3565 *length = 0;
3566 }
3567
3568 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3569 {
3570 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003571 InvalidOperation()
3572 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003573 return false;
3574 }
3575
Corentin Walleze4477002017-12-01 14:39:58 -05003576 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003577 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003578 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003579 return false;
3580 }
3581
Geoff Lang496c02d2016-10-20 11:38:11 -07003582 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003583 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003584 case GL_BUFFER_MAP_POINTER:
3585 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003586
Geoff Lang496c02d2016-10-20 11:38:11 -07003587 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003588 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003589 return false;
3590 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003591
3592 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3593 // target bound to zero generate an INVALID_OPERATION error."
3594 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003595 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003596 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003597 context->handleError(InvalidOperation()
3598 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003599 return false;
3600 }
3601
Geoff Lang496c02d2016-10-20 11:38:11 -07003602 if (length)
3603 {
3604 *length = 1;
3605 }
3606
Olli Etuaho4f667482016-03-30 15:56:35 +03003607 return true;
3608}
3609
Corentin Wallez336129f2017-10-17 15:55:40 -04003610bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003611{
Corentin Walleze4477002017-12-01 14:39:58 -05003612 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003613 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003614 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003615 return false;
3616 }
3617
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003618 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003619
3620 if (buffer == nullptr || !buffer->isMapped())
3621 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003622 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003623 return false;
3624 }
3625
3626 return true;
3627}
3628
3629bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003630 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003631 GLintptr offset,
3632 GLsizeiptr length,
3633 GLbitfield access)
3634{
Corentin Walleze4477002017-12-01 14:39:58 -05003635 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003636 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003637 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003638 return false;
3639 }
3640
Brandon Jones6cad5662017-06-14 13:25:13 -07003641 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003642 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003643 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3644 return false;
3645 }
3646
3647 if (length < 0)
3648 {
3649 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003650 return false;
3651 }
3652
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003653 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003654
3655 if (!buffer)
3656 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003657 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003658 return false;
3659 }
3660
3661 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003662 CheckedNumeric<size_t> checkedOffset(offset);
3663 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003664
Jamie Madille2e406c2016-06-02 13:04:10 -04003665 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003666 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003667 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003668 return false;
3669 }
3670
3671 // Check for invalid bits in the mask
3672 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3673 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3674 GL_MAP_UNSYNCHRONIZED_BIT;
3675
3676 if (access & ~(allAccessBits))
3677 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003678 context->handleError(InvalidValue()
3679 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003680 return false;
3681 }
3682
3683 if (length == 0)
3684 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003685 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003686 return false;
3687 }
3688
3689 if (buffer->isMapped())
3690 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003691 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003692 return false;
3693 }
3694
3695 // Check for invalid bit combinations
3696 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3697 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003698 context->handleError(InvalidOperation()
3699 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003700 return false;
3701 }
3702
3703 GLbitfield writeOnlyBits =
3704 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3705
3706 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3707 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003708 context->handleError(InvalidOperation()
3709 << "Invalid access bits when mapping buffer for reading: 0x"
3710 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003711 return false;
3712 }
3713
3714 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3715 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003716 context->handleError(
3717 InvalidOperation()
3718 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003719 return false;
3720 }
Geoff Lang79f71042017-08-14 16:43:43 -04003721
3722 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003723}
3724
3725bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003726 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003727 GLintptr offset,
3728 GLsizeiptr length)
3729{
Brandon Jones6cad5662017-06-14 13:25:13 -07003730 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003731 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003732 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3733 return false;
3734 }
3735
3736 if (length < 0)
3737 {
3738 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003739 return false;
3740 }
3741
Corentin Walleze4477002017-12-01 14:39:58 -05003742 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003743 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003744 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003745 return false;
3746 }
3747
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003748 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003749
3750 if (buffer == nullptr)
3751 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003752 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003753 return false;
3754 }
3755
3756 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3757 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003758 context->handleError(InvalidOperation()
3759 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003760 return false;
3761 }
3762
3763 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003764 CheckedNumeric<size_t> checkedOffset(offset);
3765 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003766
Jamie Madille2e406c2016-06-02 13:04:10 -04003767 if (!checkedSize.IsValid() ||
3768 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003769 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003770 context->handleError(InvalidValue()
3771 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003772 return false;
3773 }
3774
3775 return true;
3776}
3777
Olli Etuaho41997e72016-03-10 13:38:39 +02003778bool ValidateGenOrDelete(Context *context, GLint n)
3779{
3780 if (n < 0)
3781 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003782 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003783 return false;
3784 }
3785 return true;
3786}
3787
Jamie Madill5b772312018-03-08 20:28:32 -05003788bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003789{
3790 if (!context->getExtensions().robustClientMemory)
3791 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003792 context->handleError(InvalidOperation()
3793 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003794 return false;
3795 }
3796
3797 if (bufSize < 0)
3798 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003799 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003800 return false;
3801 }
3802
3803 return true;
3804}
3805
Jamie Madill5b772312018-03-08 20:28:32 -05003806bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003807{
3808 if (bufSize < numParams)
3809 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003810 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3811 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003812 return false;
3813 }
3814
3815 return true;
3816}
3817
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003818bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04003819 GLenum target,
3820 GLenum attachment,
3821 GLenum pname,
3822 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003823{
Geoff Lange8afa902017-09-27 15:00:43 -04003824 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003825 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003826 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003827 return false;
3828 }
3829
3830 int clientVersion = context->getClientMajorVersion();
3831
3832 switch (pname)
3833 {
3834 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3835 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3836 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3837 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3838 break;
3839
Martin Radeve5285d22017-07-14 16:23:53 +03003840 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3841 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3842 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3843 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3844 if (clientVersion < 3 || !context->getExtensions().multiview)
3845 {
3846 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3847 return false;
3848 }
3849 break;
3850
Geoff Langff5b2d52016-09-07 11:32:23 -04003851 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3852 if (clientVersion < 3 && !context->getExtensions().sRGB)
3853 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003854 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003855 return false;
3856 }
3857 break;
3858
3859 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3860 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3861 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3862 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3863 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3864 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3865 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3866 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3867 if (clientVersion < 3)
3868 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003869 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003870 return false;
3871 }
3872 break;
3873
3874 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003875 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003876 return false;
3877 }
3878
3879 // Determine if the attachment is a valid enum
3880 switch (attachment)
3881 {
3882 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04003883 case GL_DEPTH:
3884 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04003885 if (clientVersion < 3)
3886 {
Geoff Langfa125c92017-10-24 13:01:46 -04003887 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003888 return false;
3889 }
3890 break;
3891
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003892 case GL_DEPTH_STENCIL_ATTACHMENT:
3893 if (clientVersion < 3 && !context->isWebGL1())
3894 {
3895 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3896 return false;
3897 }
3898 break;
3899
Geoff Langfa125c92017-10-24 13:01:46 -04003900 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003901 case GL_DEPTH_ATTACHMENT:
3902 case GL_STENCIL_ATTACHMENT:
3903 break;
3904
3905 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003906 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3907 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003908 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3909 {
Geoff Langfa125c92017-10-24 13:01:46 -04003910 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003911 return false;
3912 }
3913 break;
3914 }
3915
3916 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3917 ASSERT(framebuffer);
3918
3919 if (framebuffer->id() == 0)
3920 {
3921 if (clientVersion < 3)
3922 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003923 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003924 return false;
3925 }
3926
3927 switch (attachment)
3928 {
3929 case GL_BACK:
3930 case GL_DEPTH:
3931 case GL_STENCIL:
3932 break;
3933
3934 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003935 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003936 return false;
3937 }
3938 }
3939 else
3940 {
3941 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3942 {
3943 // Valid attachment query
3944 }
3945 else
3946 {
3947 switch (attachment)
3948 {
3949 case GL_DEPTH_ATTACHMENT:
3950 case GL_STENCIL_ATTACHMENT:
3951 break;
3952
3953 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003954 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04003955 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003956 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003957 return false;
3958 }
3959 break;
3960
3961 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003962 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003963 return false;
3964 }
3965 }
3966 }
3967
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003968 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003969 if (attachmentObject)
3970 {
3971 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3972 attachmentObject->type() == GL_TEXTURE ||
3973 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3974
3975 switch (pname)
3976 {
3977 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3978 if (attachmentObject->type() != GL_RENDERBUFFER &&
3979 attachmentObject->type() != GL_TEXTURE)
3980 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003981 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003982 return false;
3983 }
3984 break;
3985
3986 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3987 if (attachmentObject->type() != GL_TEXTURE)
3988 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003989 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003990 return false;
3991 }
3992 break;
3993
3994 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3995 if (attachmentObject->type() != GL_TEXTURE)
3996 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003997 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003998 return false;
3999 }
4000 break;
4001
4002 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4003 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4004 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004005 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004006 return false;
4007 }
4008 break;
4009
4010 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4011 if (attachmentObject->type() != GL_TEXTURE)
4012 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004013 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004014 return false;
4015 }
4016 break;
4017
4018 default:
4019 break;
4020 }
4021 }
4022 else
4023 {
4024 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4025 // is NONE, then querying any other pname will generate INVALID_ENUM.
4026
4027 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4028 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4029 // INVALID_OPERATION for all other pnames
4030
4031 switch (pname)
4032 {
4033 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4034 break;
4035
4036 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4037 if (clientVersion < 3)
4038 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004039 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004040 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004041 return false;
4042 }
4043 break;
4044
4045 default:
4046 if (clientVersion < 3)
4047 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004048 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004049 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004050 return false;
4051 }
4052 else
4053 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004054 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004055 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004056 return false;
4057 }
4058 }
4059 }
4060
Martin Radeve5285d22017-07-14 16:23:53 +03004061 if (numParams)
4062 {
4063 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4064 {
4065 // Only when the viewport offsets are queried we can have a varying number of output
4066 // parameters.
4067 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4068 *numParams = numViews * 2;
4069 }
4070 else
4071 {
4072 // For all other queries we can have only one output parameter.
4073 *numParams = 1;
4074 }
4075 }
4076
Geoff Langff5b2d52016-09-07 11:32:23 -04004077 return true;
4078}
4079
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004080bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004081 GLenum target,
4082 GLenum attachment,
4083 GLenum pname,
4084 GLsizei bufSize,
4085 GLsizei *numParams)
4086{
4087 if (!ValidateRobustEntryPoint(context, bufSize))
4088 {
4089 return false;
4090 }
4091
Jamie Madillbe849e42017-05-02 15:49:00 -04004092 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4093 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004094 {
4095 return false;
4096 }
4097
4098 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4099 {
4100 return false;
4101 }
4102
4103 return true;
4104}
4105
Jamie Madill5b772312018-03-08 20:28:32 -05004106bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004107 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004108 GLenum pname,
4109 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004110 GLsizei *length,
4111 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004112{
4113 if (!ValidateRobustEntryPoint(context, bufSize))
4114 {
4115 return false;
4116 }
4117
Geoff Langebebe1c2016-10-14 12:01:31 -04004118 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004119 {
4120 return false;
4121 }
4122
Geoff Langebebe1c2016-10-14 12:01:31 -04004123 if (!ValidateRobustBufferSize(context, bufSize, *length))
4124 {
4125 return false;
4126 }
4127
4128 return true;
4129}
4130
Jamie Madill5b772312018-03-08 20:28:32 -05004131bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004132 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004133 GLenum pname,
4134 GLsizei bufSize,
4135 GLsizei *length,
4136 GLint64 *params)
4137{
4138 if (!ValidateRobustEntryPoint(context, bufSize))
4139 {
4140 return false;
4141 }
4142
4143 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4144 {
4145 return false;
4146 }
4147
4148 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004149 {
4150 return false;
4151 }
4152
4153 return true;
4154}
4155
Jamie Madill5b772312018-03-08 20:28:32 -05004156bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004157{
4158 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004159 if (numParams)
4160 {
4161 *numParams = 1;
4162 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004163
4164 Program *programObject = GetValidProgram(context, program);
4165 if (!programObject)
4166 {
4167 return false;
4168 }
4169
4170 switch (pname)
4171 {
4172 case GL_DELETE_STATUS:
4173 case GL_LINK_STATUS:
4174 case GL_VALIDATE_STATUS:
4175 case GL_INFO_LOG_LENGTH:
4176 case GL_ATTACHED_SHADERS:
4177 case GL_ACTIVE_ATTRIBUTES:
4178 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4179 case GL_ACTIVE_UNIFORMS:
4180 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4181 break;
4182
4183 case GL_PROGRAM_BINARY_LENGTH:
4184 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4185 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004186 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4187 "requires GL_OES_get_program_binary or "
4188 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004189 return false;
4190 }
4191 break;
4192
4193 case GL_ACTIVE_UNIFORM_BLOCKS:
4194 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4195 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4196 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4197 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4198 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4199 if (context->getClientMajorVersion() < 3)
4200 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004201 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004202 return false;
4203 }
4204 break;
4205
Yunchao He61afff12017-03-14 15:34:03 +08004206 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004207 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004208 if (context->getClientVersion() < Version(3, 1))
4209 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004210 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004211 return false;
4212 }
4213 break;
4214
Jiawei Shao6ae51612018-02-23 14:03:25 +08004215 case GL_COMPUTE_WORK_GROUP_SIZE:
4216 if (context->getClientVersion() < Version(3, 1))
4217 {
4218 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4219 return false;
4220 }
4221
4222 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4223 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4224 // program which has not been linked successfully, or which does not contain objects to
4225 // form a compute shader.
4226 if (!programObject->isLinked())
4227 {
4228 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4229 return false;
4230 }
4231 if (!programObject->hasLinkedComputeShader())
4232 {
4233 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4234 return false;
4235 }
4236 break;
4237
Jiawei Shao447bfac2018-03-14 14:23:40 +08004238 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4239 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4240 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4241 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4242 if (!context->getExtensions().geometryShader)
4243 {
4244 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4245 return false;
4246 }
4247
4248 // [EXT_geometry_shader] Chapter 7.12
4249 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4250 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4251 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4252 // successfully, or which does not contain objects to form a geometry shader.
4253 if (!programObject->isLinked())
4254 {
4255 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4256 return false;
4257 }
4258 if (!programObject->hasLinkedGeometryShader())
4259 {
4260 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4261 return false;
4262 }
4263 break;
4264
Geoff Langff5b2d52016-09-07 11:32:23 -04004265 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004266 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004267 return false;
4268 }
4269
4270 return true;
4271}
4272
4273bool ValidateGetProgramivRobustANGLE(Context *context,
4274 GLuint program,
4275 GLenum pname,
4276 GLsizei bufSize,
4277 GLsizei *numParams)
4278{
4279 if (!ValidateRobustEntryPoint(context, bufSize))
4280 {
4281 return false;
4282 }
4283
Jamie Madillbe849e42017-05-02 15:49:00 -04004284 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004285 {
4286 return false;
4287 }
4288
4289 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4290 {
4291 return false;
4292 }
4293
4294 return true;
4295}
4296
Geoff Lang740d9022016-10-07 11:20:52 -04004297bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4298 GLenum target,
4299 GLenum pname,
4300 GLsizei bufSize,
4301 GLsizei *length,
4302 GLint *params)
4303{
4304 if (!ValidateRobustEntryPoint(context, bufSize))
4305 {
4306 return false;
4307 }
4308
4309 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4310 {
4311 return false;
4312 }
4313
4314 if (!ValidateRobustBufferSize(context, bufSize, *length))
4315 {
4316 return false;
4317 }
4318
4319 return true;
4320}
4321
Geoff Langd7d0ed32016-10-07 11:33:51 -04004322bool ValidateGetShaderivRobustANGLE(Context *context,
4323 GLuint shader,
4324 GLenum pname,
4325 GLsizei bufSize,
4326 GLsizei *length,
4327 GLint *params)
4328{
4329 if (!ValidateRobustEntryPoint(context, bufSize))
4330 {
4331 return false;
4332 }
4333
4334 if (!ValidateGetShaderivBase(context, shader, pname, length))
4335 {
4336 return false;
4337 }
4338
4339 if (!ValidateRobustBufferSize(context, bufSize, *length))
4340 {
4341 return false;
4342 }
4343
4344 return true;
4345}
4346
Geoff Langc1984ed2016-10-07 12:41:00 -04004347bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004348 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004349 GLenum pname,
4350 GLsizei bufSize,
4351 GLsizei *length,
4352 GLfloat *params)
4353{
4354 if (!ValidateRobustEntryPoint(context, bufSize))
4355 {
4356 return false;
4357 }
4358
4359 if (!ValidateGetTexParameterBase(context, target, pname, length))
4360 {
4361 return false;
4362 }
4363
4364 if (!ValidateRobustBufferSize(context, bufSize, *length))
4365 {
4366 return false;
4367 }
4368
4369 return true;
4370}
4371
Geoff Langc1984ed2016-10-07 12:41:00 -04004372bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004373 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004374 GLenum pname,
4375 GLsizei bufSize,
4376 GLsizei *length,
4377 GLint *params)
4378{
4379 if (!ValidateRobustEntryPoint(context, bufSize))
4380 {
4381 return false;
4382 }
4383
4384 if (!ValidateGetTexParameterBase(context, target, pname, length))
4385 {
4386 return false;
4387 }
4388
4389 if (!ValidateRobustBufferSize(context, bufSize, *length))
4390 {
4391 return false;
4392 }
4393
4394 return true;
4395}
4396
Geoff Langc1984ed2016-10-07 12:41:00 -04004397bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004398 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004399 GLenum pname,
4400 GLsizei bufSize,
4401 const GLfloat *params)
4402{
4403 if (!ValidateRobustEntryPoint(context, bufSize))
4404 {
4405 return false;
4406 }
4407
4408 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4409}
4410
Geoff Langc1984ed2016-10-07 12:41:00 -04004411bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004412 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004413 GLenum pname,
4414 GLsizei bufSize,
4415 const GLint *params)
4416{
4417 if (!ValidateRobustEntryPoint(context, bufSize))
4418 {
4419 return false;
4420 }
4421
4422 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4423}
4424
Geoff Langc1984ed2016-10-07 12:41:00 -04004425bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4426 GLuint sampler,
4427 GLenum pname,
4428 GLuint bufSize,
4429 GLsizei *length,
4430 GLfloat *params)
4431{
4432 if (!ValidateRobustEntryPoint(context, bufSize))
4433 {
4434 return false;
4435 }
4436
4437 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4438 {
4439 return false;
4440 }
4441
4442 if (!ValidateRobustBufferSize(context, bufSize, *length))
4443 {
4444 return false;
4445 }
4446
4447 return true;
4448}
4449
Geoff Langc1984ed2016-10-07 12:41:00 -04004450bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4451 GLuint sampler,
4452 GLenum pname,
4453 GLuint bufSize,
4454 GLsizei *length,
4455 GLint *params)
4456{
4457 if (!ValidateRobustEntryPoint(context, bufSize))
4458 {
4459 return false;
4460 }
4461
4462 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4463 {
4464 return false;
4465 }
4466
4467 if (!ValidateRobustBufferSize(context, bufSize, *length))
4468 {
4469 return false;
4470 }
4471
4472 return true;
4473}
4474
Geoff Langc1984ed2016-10-07 12:41:00 -04004475bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4476 GLuint sampler,
4477 GLenum pname,
4478 GLsizei bufSize,
4479 const GLfloat *params)
4480{
4481 if (!ValidateRobustEntryPoint(context, bufSize))
4482 {
4483 return false;
4484 }
4485
4486 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4487}
4488
Geoff Langc1984ed2016-10-07 12:41:00 -04004489bool ValidateSamplerParameterivRobustANGLE(Context *context,
4490 GLuint sampler,
4491 GLenum pname,
4492 GLsizei bufSize,
4493 const GLint *params)
4494{
4495 if (!ValidateRobustEntryPoint(context, bufSize))
4496 {
4497 return false;
4498 }
4499
4500 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4501}
4502
Geoff Lang0b031062016-10-13 14:30:04 -04004503bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4504 GLuint index,
4505 GLenum pname,
4506 GLsizei bufSize,
4507 GLsizei *length,
4508 GLfloat *params)
4509{
4510 if (!ValidateRobustEntryPoint(context, bufSize))
4511 {
4512 return false;
4513 }
4514
4515 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4516 {
4517 return false;
4518 }
4519
4520 if (!ValidateRobustBufferSize(context, bufSize, *length))
4521 {
4522 return false;
4523 }
4524
4525 return true;
4526}
4527
Geoff Lang0b031062016-10-13 14:30:04 -04004528bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4529 GLuint index,
4530 GLenum pname,
4531 GLsizei bufSize,
4532 GLsizei *length,
4533 GLint *params)
4534{
4535 if (!ValidateRobustEntryPoint(context, bufSize))
4536 {
4537 return false;
4538 }
4539
4540 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4541 {
4542 return false;
4543 }
4544
4545 if (!ValidateRobustBufferSize(context, bufSize, *length))
4546 {
4547 return false;
4548 }
4549
4550 return true;
4551}
4552
Geoff Lang0b031062016-10-13 14:30:04 -04004553bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4554 GLuint index,
4555 GLenum pname,
4556 GLsizei bufSize,
4557 GLsizei *length,
4558 void **pointer)
4559{
4560 if (!ValidateRobustEntryPoint(context, bufSize))
4561 {
4562 return false;
4563 }
4564
4565 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4566 {
4567 return false;
4568 }
4569
4570 if (!ValidateRobustBufferSize(context, bufSize, *length))
4571 {
4572 return false;
4573 }
4574
4575 return true;
4576}
4577
Geoff Lang0b031062016-10-13 14:30:04 -04004578bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4579 GLuint index,
4580 GLenum pname,
4581 GLsizei bufSize,
4582 GLsizei *length,
4583 GLint *params)
4584{
4585 if (!ValidateRobustEntryPoint(context, bufSize))
4586 {
4587 return false;
4588 }
4589
4590 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4591 {
4592 return false;
4593 }
4594
4595 if (!ValidateRobustBufferSize(context, bufSize, *length))
4596 {
4597 return false;
4598 }
4599
4600 return true;
4601}
4602
Geoff Lang0b031062016-10-13 14:30:04 -04004603bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4604 GLuint index,
4605 GLenum pname,
4606 GLsizei bufSize,
4607 GLsizei *length,
4608 GLuint *params)
4609{
4610 if (!ValidateRobustEntryPoint(context, bufSize))
4611 {
4612 return false;
4613 }
4614
4615 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4616 {
4617 return false;
4618 }
4619
4620 if (!ValidateRobustBufferSize(context, bufSize, *length))
4621 {
4622 return false;
4623 }
4624
4625 return true;
4626}
4627
Geoff Lang6899b872016-10-14 11:30:13 -04004628bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4629 GLuint program,
4630 GLuint uniformBlockIndex,
4631 GLenum pname,
4632 GLsizei bufSize,
4633 GLsizei *length,
4634 GLint *params)
4635{
4636 if (!ValidateRobustEntryPoint(context, bufSize))
4637 {
4638 return false;
4639 }
4640
4641 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4642 {
4643 return false;
4644 }
4645
4646 if (!ValidateRobustBufferSize(context, bufSize, *length))
4647 {
4648 return false;
4649 }
4650
4651 return true;
4652}
4653
Geoff Lang0a9661f2016-10-20 10:59:20 -07004654bool ValidateGetInternalFormativRobustANGLE(Context *context,
4655 GLenum target,
4656 GLenum internalformat,
4657 GLenum pname,
4658 GLsizei bufSize,
4659 GLsizei *length,
4660 GLint *params)
4661{
4662 if (!ValidateRobustEntryPoint(context, bufSize))
4663 {
4664 return false;
4665 }
4666
4667 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4668 {
4669 return false;
4670 }
4671
4672 if (!ValidateRobustBufferSize(context, bufSize, *length))
4673 {
4674 return false;
4675 }
4676
4677 return true;
4678}
4679
Jamie Madill5b772312018-03-08 20:28:32 -05004680bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08004681 GLuint attribIndex,
4682 GLint size,
4683 GLenum type,
4684 GLboolean pureInteger)
4685{
4686 const Caps &caps = context->getCaps();
4687 if (attribIndex >= caps.maxVertexAttributes)
4688 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004689 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004690 return false;
4691 }
4692
4693 if (size < 1 || size > 4)
4694 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004695 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004696 return false;
Shao80957d92017-02-20 21:25:59 +08004697 }
4698
4699 switch (type)
4700 {
4701 case GL_BYTE:
4702 case GL_UNSIGNED_BYTE:
4703 case GL_SHORT:
4704 case GL_UNSIGNED_SHORT:
4705 break;
4706
4707 case GL_INT:
4708 case GL_UNSIGNED_INT:
4709 if (context->getClientMajorVersion() < 3)
4710 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004711 context->handleError(InvalidEnum()
4712 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004713 return false;
4714 }
4715 break;
4716
4717 case GL_FIXED:
4718 case GL_FLOAT:
4719 if (pureInteger)
4720 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004721 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004722 return false;
4723 }
4724 break;
4725
4726 case GL_HALF_FLOAT:
4727 if (context->getClientMajorVersion() < 3)
4728 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004729 context->handleError(InvalidEnum()
4730 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004731 return false;
4732 }
4733 if (pureInteger)
4734 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004735 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004736 return false;
4737 }
4738 break;
4739
4740 case GL_INT_2_10_10_10_REV:
4741 case GL_UNSIGNED_INT_2_10_10_10_REV:
4742 if (context->getClientMajorVersion() < 3)
4743 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004744 context->handleError(InvalidEnum()
4745 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004746 return false;
4747 }
4748 if (pureInteger)
4749 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004750 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004751 return false;
4752 }
4753 if (size != 4)
4754 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004755 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4756 "UNSIGNED_INT_2_10_10_10_REV and "
4757 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004758 return false;
4759 }
4760 break;
4761
4762 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004763 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004764 return false;
4765 }
4766
4767 return true;
4768}
4769
Geoff Lang76e65652017-03-27 14:58:02 -04004770// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4771// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4772// specified clear value and the type of a buffer that is being cleared generates an
4773// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05004774bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04004775 GLint drawbuffer,
4776 const GLenum *validComponentTypes,
4777 size_t validComponentTypeCount)
4778{
4779 const FramebufferAttachment *attachment =
4780 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4781 if (attachment)
4782 {
4783 GLenum componentType = attachment->getFormat().info->componentType;
4784 const GLenum *end = validComponentTypes + validComponentTypeCount;
4785 if (std::find(validComponentTypes, end, componentType) == end)
4786 {
4787 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004788 InvalidOperation()
4789 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004790 return false;
4791 }
4792 }
4793
4794 return true;
4795}
4796
Jamie Madill5b772312018-03-08 20:28:32 -05004797bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04004798{
4799 if (!ValidateRobustEntryPoint(context, dataSize))
4800 {
4801 return false;
4802 }
4803
Corentin Wallez336129f2017-10-17 15:55:40 -04004804 gl::Buffer *pixelUnpackBuffer =
4805 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004806 if (pixelUnpackBuffer == nullptr)
4807 {
4808 if (dataSize < imageSize)
4809 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004810 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004811 }
4812 }
4813 return true;
4814}
4815
Jamie Madill5b772312018-03-08 20:28:32 -05004816bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004817 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004818 GLenum pname,
4819 bool pointerVersion,
4820 GLsizei *numParams)
4821{
4822 if (numParams)
4823 {
4824 *numParams = 0;
4825 }
4826
Corentin Walleze4477002017-12-01 14:39:58 -05004827 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004828 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004829 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004830 return false;
4831 }
4832
4833 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4834 if (!buffer)
4835 {
4836 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004837 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004838 return false;
4839 }
4840
4841 const Extensions &extensions = context->getExtensions();
4842
4843 switch (pname)
4844 {
4845 case GL_BUFFER_USAGE:
4846 case GL_BUFFER_SIZE:
4847 break;
4848
4849 case GL_BUFFER_ACCESS_OES:
4850 if (!extensions.mapBuffer)
4851 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004852 context->handleError(InvalidEnum()
4853 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004854 return false;
4855 }
4856 break;
4857
4858 case GL_BUFFER_MAPPED:
4859 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4860 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4861 !extensions.mapBufferRange)
4862 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004863 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4864 "GL_OES_mapbuffer or "
4865 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004866 return false;
4867 }
4868 break;
4869
4870 case GL_BUFFER_MAP_POINTER:
4871 if (!pointerVersion)
4872 {
4873 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004874 InvalidEnum()
4875 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004876 return false;
4877 }
4878 break;
4879
4880 case GL_BUFFER_ACCESS_FLAGS:
4881 case GL_BUFFER_MAP_OFFSET:
4882 case GL_BUFFER_MAP_LENGTH:
4883 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4884 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004885 context->handleError(InvalidEnum()
4886 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004887 return false;
4888 }
4889 break;
4890
4891 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004892 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004893 return false;
4894 }
4895
4896 // All buffer parameter queries return one value.
4897 if (numParams)
4898 {
4899 *numParams = 1;
4900 }
4901
4902 return true;
4903}
4904
4905bool ValidateGetRenderbufferParameterivBase(Context *context,
4906 GLenum target,
4907 GLenum pname,
4908 GLsizei *length)
4909{
4910 if (length)
4911 {
4912 *length = 0;
4913 }
4914
4915 if (target != GL_RENDERBUFFER)
4916 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004917 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004918 return false;
4919 }
4920
4921 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4922 if (renderbuffer == nullptr)
4923 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004924 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004925 return false;
4926 }
4927
4928 switch (pname)
4929 {
4930 case GL_RENDERBUFFER_WIDTH:
4931 case GL_RENDERBUFFER_HEIGHT:
4932 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4933 case GL_RENDERBUFFER_RED_SIZE:
4934 case GL_RENDERBUFFER_GREEN_SIZE:
4935 case GL_RENDERBUFFER_BLUE_SIZE:
4936 case GL_RENDERBUFFER_ALPHA_SIZE:
4937 case GL_RENDERBUFFER_DEPTH_SIZE:
4938 case GL_RENDERBUFFER_STENCIL_SIZE:
4939 break;
4940
4941 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4942 if (!context->getExtensions().framebufferMultisample)
4943 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004944 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004945 return false;
4946 }
4947 break;
4948
4949 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004950 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004951 return false;
4952 }
4953
4954 if (length)
4955 {
4956 *length = 1;
4957 }
4958 return true;
4959}
4960
4961bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4962{
4963 if (length)
4964 {
4965 *length = 0;
4966 }
4967
4968 if (GetValidShader(context, shader) == nullptr)
4969 {
4970 return false;
4971 }
4972
4973 switch (pname)
4974 {
4975 case GL_SHADER_TYPE:
4976 case GL_DELETE_STATUS:
4977 case GL_COMPILE_STATUS:
4978 case GL_INFO_LOG_LENGTH:
4979 case GL_SHADER_SOURCE_LENGTH:
4980 break;
4981
4982 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4983 if (!context->getExtensions().translatedShaderSource)
4984 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004985 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004986 return false;
4987 }
4988 break;
4989
4990 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004991 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004992 return false;
4993 }
4994
4995 if (length)
4996 {
4997 *length = 1;
4998 }
4999 return true;
5000}
5001
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005002bool ValidateGetTexParameterBase(Context *context,
5003 TextureType target,
5004 GLenum pname,
5005 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005006{
5007 if (length)
5008 {
5009 *length = 0;
5010 }
5011
5012 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5013 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005014 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005015 return false;
5016 }
5017
5018 if (context->getTargetTexture(target) == nullptr)
5019 {
5020 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005021 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005022 return false;
5023 }
5024
5025 switch (pname)
5026 {
5027 case GL_TEXTURE_MAG_FILTER:
5028 case GL_TEXTURE_MIN_FILTER:
5029 case GL_TEXTURE_WRAP_S:
5030 case GL_TEXTURE_WRAP_T:
5031 break;
5032
5033 case GL_TEXTURE_USAGE_ANGLE:
5034 if (!context->getExtensions().textureUsage)
5035 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005036 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005037 return false;
5038 }
5039 break;
5040
5041 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005042 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005043 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005044 return false;
5045 }
5046 break;
5047
5048 case GL_TEXTURE_IMMUTABLE_FORMAT:
5049 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5050 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005051 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005052 return false;
5053 }
5054 break;
5055
5056 case GL_TEXTURE_WRAP_R:
5057 case GL_TEXTURE_IMMUTABLE_LEVELS:
5058 case GL_TEXTURE_SWIZZLE_R:
5059 case GL_TEXTURE_SWIZZLE_G:
5060 case GL_TEXTURE_SWIZZLE_B:
5061 case GL_TEXTURE_SWIZZLE_A:
5062 case GL_TEXTURE_BASE_LEVEL:
5063 case GL_TEXTURE_MAX_LEVEL:
5064 case GL_TEXTURE_MIN_LOD:
5065 case GL_TEXTURE_MAX_LOD:
5066 case GL_TEXTURE_COMPARE_MODE:
5067 case GL_TEXTURE_COMPARE_FUNC:
5068 if (context->getClientMajorVersion() < 3)
5069 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005070 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005071 return false;
5072 }
5073 break;
5074
5075 case GL_TEXTURE_SRGB_DECODE_EXT:
5076 if (!context->getExtensions().textureSRGBDecode)
5077 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005078 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005079 return false;
5080 }
5081 break;
5082
Yunchao Hebacaa712018-01-30 14:01:39 +08005083 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5084 if (context->getClientVersion() < Version(3, 1))
5085 {
5086 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5087 return false;
5088 }
5089 break;
5090
Jamie Madillbe849e42017-05-02 15:49:00 -04005091 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005092 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005093 return false;
5094 }
5095
5096 if (length)
5097 {
5098 *length = 1;
5099 }
5100 return true;
5101}
5102
5103bool ValidateGetVertexAttribBase(Context *context,
5104 GLuint index,
5105 GLenum pname,
5106 GLsizei *length,
5107 bool pointer,
5108 bool pureIntegerEntryPoint)
5109{
5110 if (length)
5111 {
5112 *length = 0;
5113 }
5114
5115 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5116 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005117 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005118 return false;
5119 }
5120
5121 if (index >= context->getCaps().maxVertexAttributes)
5122 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005123 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005124 return false;
5125 }
5126
5127 if (pointer)
5128 {
5129 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5130 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005131 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005132 return false;
5133 }
5134 }
5135 else
5136 {
5137 switch (pname)
5138 {
5139 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5140 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5141 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5142 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5143 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5144 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5145 case GL_CURRENT_VERTEX_ATTRIB:
5146 break;
5147
5148 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5149 static_assert(
5150 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5151 "ANGLE extension enums not equal to GL enums.");
5152 if (context->getClientMajorVersion() < 3 &&
5153 !context->getExtensions().instancedArrays)
5154 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005155 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5156 "requires OpenGL ES 3.0 or "
5157 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005158 return false;
5159 }
5160 break;
5161
5162 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5163 if (context->getClientMajorVersion() < 3)
5164 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005165 context->handleError(
5166 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005167 return false;
5168 }
5169 break;
5170
5171 case GL_VERTEX_ATTRIB_BINDING:
5172 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5173 if (context->getClientVersion() < ES_3_1)
5174 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005175 context->handleError(InvalidEnum()
5176 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005177 return false;
5178 }
5179 break;
5180
5181 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005182 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005183 return false;
5184 }
5185 }
5186
5187 if (length)
5188 {
5189 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5190 {
5191 *length = 4;
5192 }
5193 else
5194 {
5195 *length = 1;
5196 }
5197 }
5198
5199 return true;
5200}
5201
Jamie Madill4928b7c2017-06-20 12:57:39 -04005202bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005203 GLint x,
5204 GLint y,
5205 GLsizei width,
5206 GLsizei height,
5207 GLenum format,
5208 GLenum type,
5209 GLsizei bufSize,
5210 GLsizei *length,
5211 GLsizei *columns,
5212 GLsizei *rows,
5213 void *pixels)
5214{
5215 if (length != nullptr)
5216 {
5217 *length = 0;
5218 }
5219 if (rows != nullptr)
5220 {
5221 *rows = 0;
5222 }
5223 if (columns != nullptr)
5224 {
5225 *columns = 0;
5226 }
5227
5228 if (width < 0 || height < 0)
5229 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005230 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005231 return false;
5232 }
5233
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005234 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005235
Jamie Madille98b1b52018-03-08 09:47:23 -05005236 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madillbe849e42017-05-02 15:49:00 -04005237 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005238 return false;
5239 }
5240
Jamie Madille98b1b52018-03-08 09:47:23 -05005241 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005242 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005243 return false;
5244 }
5245
Jamie Madill690c8eb2018-03-12 15:20:03 -04005246 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005247 ASSERT(framebuffer);
5248
5249 if (framebuffer->getReadBufferState() == GL_NONE)
5250 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005251 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005252 return false;
5253 }
5254
5255 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5256 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5257 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5258 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5259 // situation is an application error that would lead to a crash in ANGLE.
5260 if (readBuffer == nullptr)
5261 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005262 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005263 return false;
5264 }
5265
Martin Radev28031682017-07-28 14:47:56 +03005266 // ANGLE_multiview, Revision 1:
5267 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5268 // current read framebuffer is not NONE.
5269 if (readBuffer->getMultiviewLayout() != GL_NONE)
5270 {
5271 context->handleError(InvalidFramebufferOperation()
5272 << "Attempting to read from a multi-view framebuffer.");
5273 return false;
5274 }
5275
Geoff Lang280ba992017-04-18 16:30:58 -04005276 if (context->getExtensions().webglCompatibility)
5277 {
5278 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5279 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5280 // and type before validating the combination of format and type. However, the
5281 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5282 // verifies that GL_INVALID_OPERATION is generated.
5283 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5284 // dEQP/WebGL.
5285 if (!ValidReadPixelsFormatEnum(context, format))
5286 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005287 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005288 return false;
5289 }
5290
5291 if (!ValidReadPixelsTypeEnum(context, type))
5292 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005293 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005294 return false;
5295 }
5296 }
5297
Jamie Madill690c8eb2018-03-12 15:20:03 -04005298 GLenum currentFormat = GL_NONE;
5299 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5300
5301 GLenum currentType = GL_NONE;
5302 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5303
Jamie Madillbe849e42017-05-02 15:49:00 -04005304 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5305
5306 bool validFormatTypeCombination =
5307 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5308
5309 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5310 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005311 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005312 return false;
5313 }
5314
5315 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005316 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005317 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5318 {
5319 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005320 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005321 return false;
5322 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005323 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5324 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5325 {
5326 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5327 return false;
5328 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005329
5330 // .. the data would be packed to the buffer object such that the memory writes required
5331 // would exceed the data store size.
5332 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5333 const gl::Extents size(width, height, 1);
5334 const auto &pack = context->getGLState().getPackState();
5335
5336 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5337 if (endByteOrErr.isError())
5338 {
5339 context->handleError(endByteOrErr.getError());
5340 return false;
5341 }
5342
5343 size_t endByte = endByteOrErr.getResult();
5344 if (bufSize >= 0)
5345 {
5346 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5347 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005348 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005349 return false;
5350 }
5351 }
5352
5353 if (pixelPackBuffer != nullptr)
5354 {
5355 CheckedNumeric<size_t> checkedEndByte(endByte);
5356 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5357 checkedEndByte += checkedOffset;
5358
5359 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5360 {
5361 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005362 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005363 return false;
5364 }
5365 }
5366
5367 if (pixelPackBuffer == nullptr && length != nullptr)
5368 {
5369 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5370 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005371 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005372 return false;
5373 }
5374
5375 *length = static_cast<GLsizei>(endByte);
5376 }
5377
Geoff Langa953b522018-02-21 16:56:23 -05005378 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005379 angle::CheckedNumeric<int> clippedExtent(length);
5380 if (start < 0)
5381 {
5382 // "subtract" the area that is less than 0
5383 clippedExtent += start;
5384 }
5385
Geoff Langa953b522018-02-21 16:56:23 -05005386 angle::CheckedNumeric<int> readExtent = start;
5387 readExtent += length;
5388 if (!readExtent.IsValid())
5389 {
5390 return false;
5391 }
5392
5393 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005394 {
5395 // Subtract the region to the right of the read buffer
5396 clippedExtent -= (readExtent - bufferSize);
5397 }
5398
5399 if (!clippedExtent.IsValid())
5400 {
Geoff Langa953b522018-02-21 16:56:23 -05005401 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005402 }
5403
Geoff Langa953b522018-02-21 16:56:23 -05005404 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5405 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005406 };
5407
Geoff Langa953b522018-02-21 16:56:23 -05005408 GLsizei writtenColumns = 0;
5409 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5410 {
5411 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5412 return false;
5413 }
5414
5415 GLsizei writtenRows = 0;
5416 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5417 {
5418 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5419 return false;
5420 }
5421
Jamie Madillbe849e42017-05-02 15:49:00 -04005422 if (columns != nullptr)
5423 {
Geoff Langa953b522018-02-21 16:56:23 -05005424 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005425 }
5426
5427 if (rows != nullptr)
5428 {
Geoff Langa953b522018-02-21 16:56:23 -05005429 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005430 }
5431
5432 return true;
5433}
5434
5435template <typename ParamType>
5436bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005437 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005438 GLenum pname,
5439 GLsizei bufSize,
5440 const ParamType *params)
5441{
5442 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5443 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005444 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005445 return false;
5446 }
5447
5448 if (context->getTargetTexture(target) == nullptr)
5449 {
5450 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005451 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005452 return false;
5453 }
5454
5455 const GLsizei minBufSize = 1;
5456 if (bufSize >= 0 && bufSize < minBufSize)
5457 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005458 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005459 return false;
5460 }
5461
5462 switch (pname)
5463 {
5464 case GL_TEXTURE_WRAP_R:
5465 case GL_TEXTURE_SWIZZLE_R:
5466 case GL_TEXTURE_SWIZZLE_G:
5467 case GL_TEXTURE_SWIZZLE_B:
5468 case GL_TEXTURE_SWIZZLE_A:
5469 case GL_TEXTURE_BASE_LEVEL:
5470 case GL_TEXTURE_MAX_LEVEL:
5471 case GL_TEXTURE_COMPARE_MODE:
5472 case GL_TEXTURE_COMPARE_FUNC:
5473 case GL_TEXTURE_MIN_LOD:
5474 case GL_TEXTURE_MAX_LOD:
5475 if (context->getClientMajorVersion() < 3)
5476 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005477 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005478 return false;
5479 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005480 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005481 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005482 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5483 "available without "
5484 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005485 return false;
5486 }
5487 break;
5488
5489 default:
5490 break;
5491 }
5492
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005493 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005494 {
5495 switch (pname)
5496 {
5497 case GL_TEXTURE_MIN_FILTER:
5498 case GL_TEXTURE_MAG_FILTER:
5499 case GL_TEXTURE_WRAP_S:
5500 case GL_TEXTURE_WRAP_T:
5501 case GL_TEXTURE_WRAP_R:
5502 case GL_TEXTURE_MIN_LOD:
5503 case GL_TEXTURE_MAX_LOD:
5504 case GL_TEXTURE_COMPARE_MODE:
5505 case GL_TEXTURE_COMPARE_FUNC:
5506 context->handleError(InvalidEnum()
5507 << "Invalid parameter for 2D multisampled textures.");
5508 return false;
5509 }
5510 }
5511
Jamie Madillbe849e42017-05-02 15:49:00 -04005512 switch (pname)
5513 {
5514 case GL_TEXTURE_WRAP_S:
5515 case GL_TEXTURE_WRAP_T:
5516 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005517 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005518 bool restrictedWrapModes =
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005519 target == TextureType::External || target == TextureType::Rectangle;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005520 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5521 {
5522 return false;
5523 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005524 }
5525 break;
5526
5527 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005528 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005529 bool restrictedMinFilter =
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005530 target == TextureType::External || target == TextureType::Rectangle;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005531 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5532 {
5533 return false;
5534 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005535 }
5536 break;
5537
5538 case GL_TEXTURE_MAG_FILTER:
5539 if (!ValidateTextureMagFilterValue(context, params))
5540 {
5541 return false;
5542 }
5543 break;
5544
5545 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005546 if (!context->getExtensions().textureUsage)
5547 {
5548 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5549 return false;
5550 }
5551
Jamie Madillbe849e42017-05-02 15:49:00 -04005552 switch (ConvertToGLenum(params[0]))
5553 {
5554 case GL_NONE:
5555 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5556 break;
5557
5558 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005559 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005560 return false;
5561 }
5562 break;
5563
5564 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Jamie Madillbe849e42017-05-02 15:49:00 -04005565 {
Luc Ferron1b1a8642018-01-23 15:12:01 -05005566 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5567 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5568 {
5569 return false;
5570 }
5571 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
Jamie Madillbe849e42017-05-02 15:49:00 -04005572 }
5573 break;
5574
5575 case GL_TEXTURE_MIN_LOD:
5576 case GL_TEXTURE_MAX_LOD:
5577 // any value is permissible
5578 break;
5579
5580 case GL_TEXTURE_COMPARE_MODE:
5581 if (!ValidateTextureCompareModeValue(context, params))
5582 {
5583 return false;
5584 }
5585 break;
5586
5587 case GL_TEXTURE_COMPARE_FUNC:
5588 if (!ValidateTextureCompareFuncValue(context, params))
5589 {
5590 return false;
5591 }
5592 break;
5593
5594 case GL_TEXTURE_SWIZZLE_R:
5595 case GL_TEXTURE_SWIZZLE_G:
5596 case GL_TEXTURE_SWIZZLE_B:
5597 case GL_TEXTURE_SWIZZLE_A:
5598 switch (ConvertToGLenum(params[0]))
5599 {
5600 case GL_RED:
5601 case GL_GREEN:
5602 case GL_BLUE:
5603 case GL_ALPHA:
5604 case GL_ZERO:
5605 case GL_ONE:
5606 break;
5607
5608 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005609 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005610 return false;
5611 }
5612 break;
5613
5614 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005615 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005616 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005617 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005618 return false;
5619 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005620 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005621 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005622 context->handleError(InvalidOperation()
5623 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005624 return false;
5625 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005626 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005627 {
5628 context->handleError(InvalidOperation()
5629 << "Base level must be 0 for multisampled textures.");
5630 return false;
5631 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005632 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005633 {
5634 context->handleError(InvalidOperation()
5635 << "Base level must be 0 for rectangle textures.");
5636 return false;
5637 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005638 break;
5639
5640 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005641 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005642 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005643 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005644 return false;
5645 }
5646 break;
5647
5648 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5649 if (context->getClientVersion() < Version(3, 1))
5650 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005651 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005652 return false;
5653 }
5654 switch (ConvertToGLenum(params[0]))
5655 {
5656 case GL_DEPTH_COMPONENT:
5657 case GL_STENCIL_INDEX:
5658 break;
5659
5660 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005661 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005662 return false;
5663 }
5664 break;
5665
5666 case GL_TEXTURE_SRGB_DECODE_EXT:
5667 if (!ValidateTextureSRGBDecodeValue(context, params))
5668 {
5669 return false;
5670 }
5671 break;
5672
5673 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005674 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005675 return false;
5676 }
5677
5678 return true;
5679}
5680
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005681template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
5682template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04005683
Jamie Madill5b772312018-03-08 20:28:32 -05005684bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04005685{
5686 if (index >= MAX_VERTEX_ATTRIBS)
5687 {
5688 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5689 return false;
5690 }
5691
5692 return true;
5693}
5694
5695bool ValidateGetActiveUniformBlockivBase(Context *context,
5696 GLuint program,
5697 GLuint uniformBlockIndex,
5698 GLenum pname,
5699 GLsizei *length)
5700{
5701 if (length)
5702 {
5703 *length = 0;
5704 }
5705
5706 if (context->getClientMajorVersion() < 3)
5707 {
5708 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5709 return false;
5710 }
5711
5712 Program *programObject = GetValidProgram(context, program);
5713 if (!programObject)
5714 {
5715 return false;
5716 }
5717
5718 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5719 {
5720 context->handleError(InvalidValue()
5721 << "uniformBlockIndex exceeds active uniform block count.");
5722 return false;
5723 }
5724
5725 switch (pname)
5726 {
5727 case GL_UNIFORM_BLOCK_BINDING:
5728 case GL_UNIFORM_BLOCK_DATA_SIZE:
5729 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5730 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5731 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5732 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5733 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5734 break;
5735
5736 default:
5737 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5738 return false;
5739 }
5740
5741 if (length)
5742 {
5743 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5744 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005745 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005746 programObject->getUniformBlockByIndex(uniformBlockIndex);
5747 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5748 }
5749 else
5750 {
5751 *length = 1;
5752 }
5753 }
5754
5755 return true;
5756}
5757
Jamie Madill9696d072017-08-26 23:19:57 -04005758template <typename ParamType>
5759bool ValidateSamplerParameterBase(Context *context,
5760 GLuint sampler,
5761 GLenum pname,
5762 GLsizei bufSize,
5763 ParamType *params)
5764{
5765 if (context->getClientMajorVersion() < 3)
5766 {
5767 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5768 return false;
5769 }
5770
5771 if (!context->isSampler(sampler))
5772 {
5773 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5774 return false;
5775 }
5776
5777 const GLsizei minBufSize = 1;
5778 if (bufSize >= 0 && bufSize < minBufSize)
5779 {
5780 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5781 return false;
5782 }
5783
5784 switch (pname)
5785 {
5786 case GL_TEXTURE_WRAP_S:
5787 case GL_TEXTURE_WRAP_T:
5788 case GL_TEXTURE_WRAP_R:
5789 if (!ValidateTextureWrapModeValue(context, params, false))
5790 {
5791 return false;
5792 }
5793 break;
5794
5795 case GL_TEXTURE_MIN_FILTER:
5796 if (!ValidateTextureMinFilterValue(context, params, false))
5797 {
5798 return false;
5799 }
5800 break;
5801
5802 case GL_TEXTURE_MAG_FILTER:
5803 if (!ValidateTextureMagFilterValue(context, params))
5804 {
5805 return false;
5806 }
5807 break;
5808
5809 case GL_TEXTURE_MIN_LOD:
5810 case GL_TEXTURE_MAX_LOD:
5811 // any value is permissible
5812 break;
5813
5814 case GL_TEXTURE_COMPARE_MODE:
5815 if (!ValidateTextureCompareModeValue(context, params))
5816 {
5817 return false;
5818 }
5819 break;
5820
5821 case GL_TEXTURE_COMPARE_FUNC:
5822 if (!ValidateTextureCompareFuncValue(context, params))
5823 {
5824 return false;
5825 }
5826 break;
5827
5828 case GL_TEXTURE_SRGB_DECODE_EXT:
5829 if (!ValidateTextureSRGBDecodeValue(context, params))
5830 {
5831 return false;
5832 }
5833 break;
5834
Luc Ferron1b1a8642018-01-23 15:12:01 -05005835 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5836 {
5837 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5838 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5839 {
5840 return false;
5841 }
5842 }
5843 break;
5844
Jamie Madill9696d072017-08-26 23:19:57 -04005845 default:
5846 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5847 return false;
5848 }
5849
5850 return true;
5851}
5852
5853template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5854template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5855
5856bool ValidateGetSamplerParameterBase(Context *context,
5857 GLuint sampler,
5858 GLenum pname,
5859 GLsizei *length)
5860{
5861 if (length)
5862 {
5863 *length = 0;
5864 }
5865
5866 if (context->getClientMajorVersion() < 3)
5867 {
5868 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5869 return false;
5870 }
5871
5872 if (!context->isSampler(sampler))
5873 {
5874 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5875 return false;
5876 }
5877
5878 switch (pname)
5879 {
5880 case GL_TEXTURE_WRAP_S:
5881 case GL_TEXTURE_WRAP_T:
5882 case GL_TEXTURE_WRAP_R:
5883 case GL_TEXTURE_MIN_FILTER:
5884 case GL_TEXTURE_MAG_FILTER:
5885 case GL_TEXTURE_MIN_LOD:
5886 case GL_TEXTURE_MAX_LOD:
5887 case GL_TEXTURE_COMPARE_MODE:
5888 case GL_TEXTURE_COMPARE_FUNC:
5889 break;
5890
Luc Ferron1b1a8642018-01-23 15:12:01 -05005891 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5892 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
5893 {
5894 return false;
5895 }
5896 break;
5897
Jamie Madill9696d072017-08-26 23:19:57 -04005898 case GL_TEXTURE_SRGB_DECODE_EXT:
5899 if (!context->getExtensions().textureSRGBDecode)
5900 {
5901 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5902 return false;
5903 }
5904 break;
5905
5906 default:
5907 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5908 return false;
5909 }
5910
5911 if (length)
5912 {
5913 *length = 1;
5914 }
5915 return true;
5916}
5917
5918bool ValidateGetInternalFormativBase(Context *context,
5919 GLenum target,
5920 GLenum internalformat,
5921 GLenum pname,
5922 GLsizei bufSize,
5923 GLsizei *numParams)
5924{
5925 if (numParams)
5926 {
5927 *numParams = 0;
5928 }
5929
5930 if (context->getClientMajorVersion() < 3)
5931 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005932 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005933 return false;
5934 }
5935
5936 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5937 if (!formatCaps.renderable)
5938 {
5939 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5940 return false;
5941 }
5942
5943 switch (target)
5944 {
5945 case GL_RENDERBUFFER:
5946 break;
5947
5948 case GL_TEXTURE_2D_MULTISAMPLE:
5949 if (context->getClientVersion() < ES_3_1)
5950 {
5951 context->handleError(InvalidOperation()
5952 << "Texture target requires at least OpenGL ES 3.1.");
5953 return false;
5954 }
5955 break;
5956
5957 default:
5958 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5959 return false;
5960 }
5961
5962 if (bufSize < 0)
5963 {
5964 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5965 return false;
5966 }
5967
5968 GLsizei maxWriteParams = 0;
5969 switch (pname)
5970 {
5971 case GL_NUM_SAMPLE_COUNTS:
5972 maxWriteParams = 1;
5973 break;
5974
5975 case GL_SAMPLES:
5976 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5977 break;
5978
5979 default:
5980 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5981 return false;
5982 }
5983
5984 if (numParams)
5985 {
5986 // glGetInternalFormativ will not overflow bufSize
5987 *numParams = std::min(bufSize, maxWriteParams);
5988 }
5989
5990 return true;
5991}
5992
Jamie Madille98b1b52018-03-08 09:47:23 -05005993// We should check with Khronos if returning INVALID_FRAMEBUFFER_OPERATION is OK when querying
5994// implementation format info for incomplete framebuffers. It seems like these queries are
5995// incongruent with the other errors.
5996bool ValidateFramebufferComplete(Context *context, Framebuffer *framebuffer, bool isFramebufferOp)
5997{
5998 bool complete = false;
5999 ANGLE_VALIDATION_TRY(framebuffer->isComplete(context, &complete));
6000 if (!complete)
6001 {
6002 if (isFramebufferOp)
6003 {
6004 context->handleError(InvalidFramebufferOperation());
6005 }
6006 else
6007 {
6008 context->handleError(InvalidOperation());
6009 }
6010 return false;
6011 }
6012 return true;
6013}
6014
6015bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6016{
6017 GLint samples = 0;
6018 ANGLE_VALIDATION_TRY(framebuffer->getSamples(context, &samples));
6019 if (samples != 0)
6020 {
6021 context->handleError(InvalidOperation());
6022 return false;
6023 }
6024 return true;
6025}
6026
Jamie Madillc29968b2016-01-20 11:17:23 -05006027} // namespace gl