blob: 43ca249129b3c515eb7a5869bd3cc3da209c09ab [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;
986 default:
987 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500988 }
989}
990
Jamie Madill5b772312018-03-08 20:28:32 -0500991bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400992 GLenum type,
993 GLboolean normalized,
994 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400995 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400996 bool pureInteger)
997{
998 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400999 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1000 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1001 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1002 // parameter exceeds 255.
1003 constexpr GLsizei kMaxWebGLStride = 255;
1004 if (stride > kMaxWebGLStride)
1005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001006 context->handleError(InvalidValue()
1007 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001008 return false;
1009 }
1010
1011 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1012 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1013 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1014 // or an INVALID_OPERATION error is generated.
1015 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1016 size_t typeSize = GetVertexFormatTypeSize(internalType);
1017
1018 ASSERT(isPow2(typeSize) && typeSize > 0);
1019 size_t sizeMask = (typeSize - 1);
1020 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1021 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001022 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001023 return false;
1024 }
1025
1026 if ((stride & sizeMask) != 0)
1027 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001028 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001029 return false;
1030 }
1031
1032 return true;
1033}
1034
Jamie Madill5b772312018-03-08 20:28:32 -05001035Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001036{
He Yunchaoced53ae2016-11-29 15:00:51 +08001037 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1038 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1039 // or program object and INVALID_OPERATION if the provided name identifies an object
1040 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001041
Dian Xiang769769a2015-09-09 15:20:08 -07001042 Program *validProgram = context->getProgram(id);
1043
1044 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001045 {
Dian Xiang769769a2015-09-09 15:20:08 -07001046 if (context->getShader(id))
1047 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001048 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001049 }
1050 else
1051 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001052 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001053 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001054 }
Dian Xiang769769a2015-09-09 15:20:08 -07001055
1056 return validProgram;
1057}
1058
Jamie Madill5b772312018-03-08 20:28:32 -05001059Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001060{
1061 // See ValidProgram for spec details.
1062
1063 Shader *validShader = context->getShader(id);
1064
1065 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001066 {
Dian Xiang769769a2015-09-09 15:20:08 -07001067 if (context->getProgram(id))
1068 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001069 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001070 }
1071 else
1072 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001073 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001074 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001075 }
Dian Xiang769769a2015-09-09 15:20:08 -07001076
1077 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001078}
1079
Geoff Langb1196682014-07-23 13:47:29 -04001080bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001081{
Geoff Langfa125c92017-10-24 13:01:46 -04001082 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001083 {
Geoff Langfa125c92017-10-24 13:01:46 -04001084 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1085 {
1086 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1087 return false;
1088 }
Jamie Madillb4472272014-07-03 10:38:55 -04001089
Geoff Langfa125c92017-10-24 13:01:46 -04001090 // Color attachment 0 is validated below because it is always valid
1091 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001092 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001093 {
Geoff Langfa125c92017-10-24 13:01:46 -04001094 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001095 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001096 }
1097 }
1098 else
1099 {
1100 switch (attachment)
1101 {
Geoff Langfa125c92017-10-24 13:01:46 -04001102 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001103 case GL_DEPTH_ATTACHMENT:
1104 case GL_STENCIL_ATTACHMENT:
1105 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001106
He Yunchaoced53ae2016-11-29 15:00:51 +08001107 case GL_DEPTH_STENCIL_ATTACHMENT:
1108 if (!context->getExtensions().webglCompatibility &&
1109 context->getClientMajorVersion() < 3)
1110 {
Geoff Langfa125c92017-10-24 13:01:46 -04001111 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001112 return false;
1113 }
1114 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001115
He Yunchaoced53ae2016-11-29 15:00:51 +08001116 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001117 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001118 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001119 }
1120 }
1121
1122 return true;
1123}
1124
Jamie Madill5b772312018-03-08 20:28:32 -05001125bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001126 GLenum target,
1127 GLsizei samples,
1128 GLenum internalformat,
1129 GLsizei width,
1130 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001131{
1132 switch (target)
1133 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001134 case GL_RENDERBUFFER:
1135 break;
1136 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001137 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001138 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001139 }
1140
1141 if (width < 0 || height < 0 || samples < 0)
1142 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001143 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001144 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001145 }
1146
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001147 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1148 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1149
1150 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001151 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001152 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001153 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001154 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001155 }
1156
1157 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1158 // 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 -08001159 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001160 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1161 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001162 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001163 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001164 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001165 }
1166
Geoff Langaae65a42014-05-26 12:43:44 -04001167 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001168 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001169 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001170 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001171 }
1172
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001173 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001174 if (handle == 0)
1175 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001176 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001177 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001178 }
1179
1180 return true;
1181}
1182
He Yunchaoced53ae2016-11-29 15:00:51 +08001183bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1184 GLenum target,
1185 GLenum attachment,
1186 GLenum renderbuffertarget,
1187 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001188{
Geoff Lange8afa902017-09-27 15:00:43 -04001189 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001190 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001191 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001192 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001193 }
1194
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001195 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001196
Jamie Madill84115c92015-04-23 15:00:07 -04001197 ASSERT(framebuffer);
1198 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001199 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001200 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001201 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001202 }
1203
Jamie Madillb4472272014-07-03 10:38:55 -04001204 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001205 {
Jamie Madillb4472272014-07-03 10:38:55 -04001206 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001207 }
1208
Jamie Madillab9d82c2014-01-21 16:38:14 -05001209 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1210 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1211 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1212 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1213 if (renderbuffer != 0)
1214 {
1215 if (!context->getRenderbuffer(renderbuffer))
1216 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001217 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001218 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001219 }
1220 }
1221
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001222 return true;
1223}
1224
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001225bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001226 GLint srcX0,
1227 GLint srcY0,
1228 GLint srcX1,
1229 GLint srcY1,
1230 GLint dstX0,
1231 GLint dstY0,
1232 GLint dstX1,
1233 GLint dstY1,
1234 GLbitfield mask,
1235 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001236{
1237 switch (filter)
1238 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001239 case GL_NEAREST:
1240 break;
1241 case GL_LINEAR:
1242 break;
1243 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001244 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001245 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001246 }
1247
1248 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1249 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001250 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001251 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001252 }
1253
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001254 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1255 // color buffer, leaving only nearest being unfiltered from above
1256 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1257 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001258 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001259 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001260 }
1261
Jamie Madill51f40ec2016-06-15 14:06:00 -04001262 const auto &glState = context->getGLState();
1263 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1264 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001265
1266 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001267 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001268 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001269 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001270 }
1271
Jamie Madille98b1b52018-03-08 09:47:23 -05001272 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madill48faf802014-11-06 15:27:22 -05001273 {
Jamie Madill48faf802014-11-06 15:27:22 -05001274 return false;
1275 }
1276
Jamie Madille98b1b52018-03-08 09:47:23 -05001277 if (!ValidateFramebufferComplete(context, drawFramebuffer, true))
Jamie Madill48faf802014-11-06 15:27:22 -05001278 {
Jamie Madill48faf802014-11-06 15:27:22 -05001279 return false;
1280 }
1281
Qin Jiajiaaef92162018-02-27 13:51:44 +08001282 if (readFramebuffer->id() == drawFramebuffer->id())
1283 {
1284 context->handleError(InvalidOperation());
1285 return false;
1286 }
1287
Jamie Madille98b1b52018-03-08 09:47:23 -05001288 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001289 {
Geoff Langb1196682014-07-23 13:47:29 -04001290 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001291 }
1292
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001293 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1294
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001295 if (mask & GL_COLOR_BUFFER_BIT)
1296 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001297 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001298 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001299
He Yunchao66a41a22016-12-15 16:45:05 +08001300 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001301 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001302 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001303
Geoff Langa15472a2015-08-11 11:48:03 -04001304 for (size_t drawbufferIdx = 0;
1305 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001306 {
Geoff Langa15472a2015-08-11 11:48:03 -04001307 const FramebufferAttachment *attachment =
1308 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1309 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001310 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001311 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001312
Geoff Langb2f3d052013-08-13 12:49:27 -04001313 // The GL ES 3.0.2 spec (pg 193) states that:
1314 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001315 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1316 // as well
1317 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1318 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001319 // Changes with EXT_color_buffer_float:
1320 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001321 GLenum readComponentType = readFormat.info->componentType;
1322 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001323 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001324 readComponentType == GL_SIGNED_NORMALIZED);
1325 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1326 drawComponentType == GL_SIGNED_NORMALIZED);
1327
1328 if (extensions.colorBufferFloat)
1329 {
1330 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1331 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1332
1333 if (readFixedOrFloat != drawFixedOrFloat)
1334 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001335 context->handleError(InvalidOperation()
1336 << "If the read buffer contains fixed-point or "
1337 "floating-point values, the draw buffer must "
1338 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001339 return false;
1340 }
1341 }
1342 else if (readFixedPoint != drawFixedPoint)
1343 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001344 context->handleError(InvalidOperation()
1345 << "If the read buffer contains fixed-point values, "
1346 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001347 return false;
1348 }
1349
1350 if (readComponentType == GL_UNSIGNED_INT &&
1351 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001352 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001353 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001354 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001355 }
1356
Jamie Madill6163c752015-12-07 16:32:59 -05001357 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001358 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001359 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001360 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001361 }
1362
Jamie Madilla3944d42016-07-22 22:13:26 -04001363 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001364 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001365 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001366 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001367 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001368 }
Geoff Lange4915782017-04-12 15:19:07 -04001369
1370 if (context->getExtensions().webglCompatibility &&
1371 *readColorBuffer == *attachment)
1372 {
1373 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001374 InvalidOperation()
1375 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001376 return false;
1377 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001378 }
1379 }
1380
Jamie Madilla3944d42016-07-22 22:13:26 -04001381 if ((readFormat.info->componentType == GL_INT ||
1382 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1383 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001385 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001386 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001387 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001388 }
He Yunchao66a41a22016-12-15 16:45:05 +08001389 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1390 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1391 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1392 // situation is an application error that would lead to a crash in ANGLE.
1393 else if (drawFramebuffer->hasEnabledDrawBuffer())
1394 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001395 context->handleError(
1396 InvalidOperation()
1397 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001398 return false;
1399 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001400 }
1401
He Yunchaoced53ae2016-11-29 15:00:51 +08001402 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001403 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1404 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001405 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001406 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001407 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001408 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001409 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001410 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001411 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001412
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001413 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001414 {
Kenneth Russell69382852017-07-21 16:38:44 -04001415 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001416 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001417 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001418 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001419 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001420
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001421 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001422 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001423 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001424 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001425 }
Geoff Lange4915782017-04-12 15:19:07 -04001426
1427 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1428 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001429 context->handleError(
1430 InvalidOperation()
1431 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001432 return false;
1433 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001434 }
He Yunchao66a41a22016-12-15 16:45:05 +08001435 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1436 else if (drawBuffer)
1437 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001438 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1439 "depth/stencil attachment of a "
1440 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001441 return false;
1442 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001443 }
1444 }
1445
Martin Radeva3ed4572017-07-27 18:29:37 +03001446 // ANGLE_multiview, Revision 1:
1447 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1448 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1449 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1450 {
1451 context->handleError(InvalidFramebufferOperation()
1452 << "Attempt to read from a multi-view framebuffer.");
1453 return false;
1454 }
1455 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1456 {
1457 context->handleError(InvalidFramebufferOperation()
1458 << "Attempt to write to a multi-view framebuffer.");
1459 return false;
1460 }
1461
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001462 return true;
1463}
1464
Jamie Madill4928b7c2017-06-20 12:57:39 -04001465bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001466 GLint x,
1467 GLint y,
1468 GLsizei width,
1469 GLsizei height,
1470 GLenum format,
1471 GLenum type,
1472 GLsizei bufSize,
1473 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001474 GLsizei *columns,
1475 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001476 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001477{
1478 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001479 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001480 return false;
1481 }
1482
Geoff Lang62fce5b2016-09-30 10:46:35 -04001483 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001484 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001485 {
Geoff Langb1196682014-07-23 13:47:29 -04001486 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001487 }
1488
Geoff Lang62fce5b2016-09-30 10:46:35 -04001489 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001490 {
Geoff Langb1196682014-07-23 13:47:29 -04001491 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001492 }
1493
Jamie Madillc29968b2016-01-20 11:17:23 -05001494 return true;
1495}
1496
1497bool ValidateReadnPixelsEXT(Context *context,
1498 GLint x,
1499 GLint y,
1500 GLsizei width,
1501 GLsizei height,
1502 GLenum format,
1503 GLenum type,
1504 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001505 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001506{
1507 if (bufSize < 0)
1508 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001509 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001510 return false;
1511 }
1512
Geoff Lang62fce5b2016-09-30 10:46:35 -04001513 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001514 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001515}
Jamie Madill26e91952014-03-05 15:01:27 -05001516
Jamie Madill4928b7c2017-06-20 12:57:39 -04001517bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001518 GLint x,
1519 GLint y,
1520 GLsizei width,
1521 GLsizei height,
1522 GLenum format,
1523 GLenum type,
1524 GLsizei bufSize,
1525 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001526 GLsizei *columns,
1527 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001528 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001529{
1530 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001531 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001532 return false;
1533 }
1534
Geoff Lange93daba2017-03-30 13:54:40 -04001535 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1536 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001537 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001538 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001539 }
1540
Geoff Lang62fce5b2016-09-30 10:46:35 -04001541 if (!ValidateRobustBufferSize(context, bufSize, *length))
1542 {
1543 return false;
1544 }
1545
1546 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001547}
1548
Jamie Madillf0e04492017-08-26 15:28:42 -04001549bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001550{
1551 if (!context->getExtensions().occlusionQueryBoolean &&
1552 !context->getExtensions().disjointTimerQuery)
1553 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001554 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001555 return false;
1556 }
1557
Olli Etuaho41997e72016-03-10 13:38:39 +02001558 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001559}
1560
Jamie Madillf0e04492017-08-26 15:28:42 -04001561bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001562{
1563 if (!context->getExtensions().occlusionQueryBoolean &&
1564 !context->getExtensions().disjointTimerQuery)
1565 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001566 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001567 return false;
1568 }
1569
Olli Etuaho41997e72016-03-10 13:38:39 +02001570 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001571}
1572
Jamie Madillf0e04492017-08-26 15:28:42 -04001573bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1574{
1575 if (!context->getExtensions().occlusionQueryBoolean &&
1576 !context->getExtensions().disjointTimerQuery)
1577 {
1578 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1579 return false;
1580 }
1581
1582 return true;
1583}
1584
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001585bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001586{
1587 if (!ValidQueryType(context, target))
1588 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001589 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001590 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001591 }
1592
1593 if (id == 0)
1594 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001595 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001596 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001597 }
1598
1599 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1600 // of zero, if the active query object name for <target> is non-zero (for the
1601 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1602 // the active query for either target is non-zero), if <id> is the name of an
1603 // existing query object whose type does not match <target>, or if <id> is the
1604 // active query object name for any query type, the error INVALID_OPERATION is
1605 // generated.
1606
1607 // Ensure no other queries are active
1608 // NOTE: If other queries than occlusion are supported, we will need to check
1609 // separately that:
1610 // a) The query ID passed is not the current active query for any target/type
1611 // b) There are no active queries for the requested target (and in the case
1612 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1613 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001614
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001615 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001616 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001617 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001618 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001619 }
1620
1621 Query *queryObject = context->getQuery(id, true, target);
1622
1623 // check that name was obtained with glGenQueries
1624 if (!queryObject)
1625 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001626 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001627 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001628 }
1629
1630 // check for type mismatch
1631 if (queryObject->getType() != target)
1632 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001633 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001634 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001635 }
1636
1637 return true;
1638}
1639
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001640bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1641{
1642 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001643 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001644 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001645 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001646 return false;
1647 }
1648
1649 return ValidateBeginQueryBase(context, target, id);
1650}
1651
1652bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001653{
1654 if (!ValidQueryType(context, target))
1655 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001656 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001657 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001658 }
1659
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001660 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001661
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001662 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001663 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001664 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001665 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001666 }
1667
Jamie Madill45c785d2014-05-13 14:09:34 -04001668 return true;
1669}
1670
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001671bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1672{
1673 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001674 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001675 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001676 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001677 return false;
1678 }
1679
1680 return ValidateEndQueryBase(context, target);
1681}
1682
1683bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1684{
1685 if (!context->getExtensions().disjointTimerQuery)
1686 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001687 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001688 return false;
1689 }
1690
1691 if (target != GL_TIMESTAMP_EXT)
1692 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001693 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001694 return false;
1695 }
1696
1697 Query *queryObject = context->getQuery(id, true, target);
1698 if (queryObject == nullptr)
1699 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001700 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001701 return false;
1702 }
1703
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001704 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001705 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001706 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001707 return false;
1708 }
1709
1710 return true;
1711}
1712
Geoff Lang2186c382016-10-14 10:54:54 -04001713bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001714{
Geoff Lang2186c382016-10-14 10:54:54 -04001715 if (numParams)
1716 {
1717 *numParams = 0;
1718 }
1719
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001720 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1721 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001722 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001723 return false;
1724 }
1725
1726 switch (pname)
1727 {
1728 case GL_CURRENT_QUERY_EXT:
1729 if (target == GL_TIMESTAMP_EXT)
1730 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001731 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001732 return false;
1733 }
1734 break;
1735 case GL_QUERY_COUNTER_BITS_EXT:
1736 if (!context->getExtensions().disjointTimerQuery ||
1737 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1738 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001739 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001740 return false;
1741 }
1742 break;
1743 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001744 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001745 return false;
1746 }
1747
Geoff Lang2186c382016-10-14 10:54:54 -04001748 if (numParams)
1749 {
1750 // All queries return only one value
1751 *numParams = 1;
1752 }
1753
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001754 return true;
1755}
1756
1757bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1758{
1759 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001760 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001761 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001762 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001763 return false;
1764 }
1765
Geoff Lang2186c382016-10-14 10:54:54 -04001766 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001767}
1768
Geoff Lang2186c382016-10-14 10:54:54 -04001769bool ValidateGetQueryivRobustANGLE(Context *context,
1770 GLenum target,
1771 GLenum pname,
1772 GLsizei bufSize,
1773 GLsizei *length,
1774 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001775{
Geoff Lang2186c382016-10-14 10:54:54 -04001776 if (!ValidateRobustEntryPoint(context, bufSize))
1777 {
1778 return false;
1779 }
1780
1781 if (!ValidateGetQueryivBase(context, target, pname, length))
1782 {
1783 return false;
1784 }
1785
1786 if (!ValidateRobustBufferSize(context, bufSize, *length))
1787 {
1788 return false;
1789 }
1790
1791 return true;
1792}
1793
1794bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1795{
1796 if (numParams)
1797 {
1798 *numParams = 0;
1799 }
1800
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001801 Query *queryObject = context->getQuery(id, false, GL_NONE);
1802
1803 if (!queryObject)
1804 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001805 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001806 return false;
1807 }
1808
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001809 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001810 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001811 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001812 return false;
1813 }
1814
1815 switch (pname)
1816 {
1817 case GL_QUERY_RESULT_EXT:
1818 case GL_QUERY_RESULT_AVAILABLE_EXT:
1819 break;
1820
1821 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001822 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001823 return false;
1824 }
1825
Geoff Lang2186c382016-10-14 10:54:54 -04001826 if (numParams)
1827 {
1828 *numParams = 1;
1829 }
1830
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001831 return true;
1832}
1833
1834bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1835{
1836 if (!context->getExtensions().disjointTimerQuery)
1837 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001838 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001839 return false;
1840 }
Geoff Lang2186c382016-10-14 10:54:54 -04001841 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1842}
1843
1844bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1845 GLuint id,
1846 GLenum pname,
1847 GLsizei bufSize,
1848 GLsizei *length,
1849 GLint *params)
1850{
1851 if (!context->getExtensions().disjointTimerQuery)
1852 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001853 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001854 return false;
1855 }
1856
1857 if (!ValidateRobustEntryPoint(context, bufSize))
1858 {
1859 return false;
1860 }
1861
1862 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1863 {
1864 return false;
1865 }
1866
1867 if (!ValidateRobustBufferSize(context, bufSize, *length))
1868 {
1869 return false;
1870 }
1871
1872 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001873}
1874
1875bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1876{
1877 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001878 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001879 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001880 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001881 return false;
1882 }
Geoff Lang2186c382016-10-14 10:54:54 -04001883 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1884}
1885
1886bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1887 GLuint id,
1888 GLenum pname,
1889 GLsizei bufSize,
1890 GLsizei *length,
1891 GLuint *params)
1892{
1893 if (!context->getExtensions().disjointTimerQuery &&
1894 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1895 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001896 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001897 return false;
1898 }
1899
1900 if (!ValidateRobustEntryPoint(context, bufSize))
1901 {
1902 return false;
1903 }
1904
1905 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1906 {
1907 return false;
1908 }
1909
1910 if (!ValidateRobustBufferSize(context, bufSize, *length))
1911 {
1912 return false;
1913 }
1914
1915 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001916}
1917
1918bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1919{
1920 if (!context->getExtensions().disjointTimerQuery)
1921 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001922 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001923 return false;
1924 }
Geoff Lang2186c382016-10-14 10:54:54 -04001925 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1926}
1927
1928bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1929 GLuint id,
1930 GLenum pname,
1931 GLsizei bufSize,
1932 GLsizei *length,
1933 GLint64 *params)
1934{
1935 if (!context->getExtensions().disjointTimerQuery)
1936 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001937 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001938 return false;
1939 }
1940
1941 if (!ValidateRobustEntryPoint(context, bufSize))
1942 {
1943 return false;
1944 }
1945
1946 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1947 {
1948 return false;
1949 }
1950
1951 if (!ValidateRobustBufferSize(context, bufSize, *length))
1952 {
1953 return false;
1954 }
1955
1956 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001957}
1958
1959bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1960{
1961 if (!context->getExtensions().disjointTimerQuery)
1962 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001963 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001964 return false;
1965 }
Geoff Lang2186c382016-10-14 10:54:54 -04001966 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1967}
1968
1969bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1970 GLuint id,
1971 GLenum pname,
1972 GLsizei bufSize,
1973 GLsizei *length,
1974 GLuint64 *params)
1975{
1976 if (!context->getExtensions().disjointTimerQuery)
1977 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001978 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001979 return false;
1980 }
1981
1982 if (!ValidateRobustEntryPoint(context, bufSize))
1983 {
1984 return false;
1985 }
1986
1987 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1988 {
1989 return false;
1990 }
1991
1992 if (!ValidateRobustBufferSize(context, bufSize, *length))
1993 {
1994 return false;
1995 }
1996
1997 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001998}
1999
Jamie Madill5b772312018-03-08 20:28:32 -05002000bool ValidateUniformCommonBase(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002001 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002002 GLint location,
2003 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002004 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002005{
Jiajia Qin5451d532017-11-16 17:16:34 +08002006 // TODO(Jiajia): Add image uniform check in future.
2007 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002008 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002009 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002010 return false;
2011 }
2012
Jiajia Qin5451d532017-11-16 17:16:34 +08002013 if (!program)
2014 {
2015 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2016 return false;
2017 }
2018
2019 if (!program->isLinked())
2020 {
2021 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2022 return false;
2023 }
2024
2025 if (location == -1)
2026 {
2027 // Silently ignore the uniform command
2028 return false;
2029 }
2030
2031 const auto &uniformLocations = program->getUniformLocations();
2032 size_t castedLocation = static_cast<size_t>(location);
2033 if (castedLocation >= uniformLocations.size())
2034 {
2035 context->handleError(InvalidOperation() << "Invalid uniform location");
2036 return false;
2037 }
2038
2039 const auto &uniformLocation = uniformLocations[castedLocation];
2040 if (uniformLocation.ignored)
2041 {
2042 // Silently ignore the uniform command
2043 return false;
2044 }
2045
2046 if (!uniformLocation.used())
2047 {
2048 context->handleError(InvalidOperation());
2049 return false;
2050 }
2051
2052 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2053
2054 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2055 if (!uniform.isArray() && count > 1)
2056 {
2057 context->handleError(InvalidOperation());
2058 return false;
2059 }
2060
2061 *uniformOut = &uniform;
2062 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002063}
2064
Jamie Madill5b772312018-03-08 20:28:32 -05002065bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002066 GLenum uniformType,
2067 GLsizei count,
2068 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002069{
Jiajia Qin5451d532017-11-16 17:16:34 +08002070 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2071 // It is compatible with INT or BOOL.
2072 // Do these cheap tests first, for a little extra speed.
2073 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002074 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002075 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002076 }
2077
Jiajia Qin5451d532017-11-16 17:16:34 +08002078 if (IsSamplerType(uniformType))
2079 {
2080 // Check that the values are in range.
2081 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2082 for (GLsizei i = 0; i < count; ++i)
2083 {
2084 if (value[i] < 0 || value[i] >= max)
2085 {
2086 context->handleError(InvalidValue() << "sampler uniform value out of range");
2087 return false;
2088 }
2089 }
2090 return true;
2091 }
2092
2093 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2094 return false;
2095}
2096
Jamie Madill5b772312018-03-08 20:28:32 -05002097bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002098{
2099 // Check that the value type is compatible with uniform type.
2100 // Do the cheaper test first, for a little extra speed.
2101 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2102 {
2103 return true;
2104 }
2105
2106 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2107 return false;
2108}
2109
Jamie Madill5b772312018-03-08 20:28:32 -05002110bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002111{
2112 // Check that the value type is compatible with uniform type.
2113 if (valueType == uniformType)
2114 {
2115 return true;
2116 }
2117
2118 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2119 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002120}
2121
Jamie Madill5b772312018-03-08 20:28:32 -05002122bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002123{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002124 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002125 gl::Program *programObject = context->getGLState().getProgram();
2126 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2127 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002128}
2129
Jamie Madill5b772312018-03-08 20:28:32 -05002130bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002131{
2132 const LinkedUniform *uniform = nullptr;
2133 gl::Program *programObject = context->getGLState().getProgram();
2134 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2135 ValidateUniform1ivValue(context, uniform->type, count, value);
2136}
2137
Jamie Madill5b772312018-03-08 20:28:32 -05002138bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002139 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002140 GLint location,
2141 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002142 GLboolean transpose)
2143{
Geoff Lang92019432017-11-20 13:09:34 -05002144 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002145 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002146 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002147 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002148 }
2149
Jamie Madill62d31cb2015-09-11 13:25:51 -04002150 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002151 gl::Program *programObject = context->getGLState().getProgram();
2152 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2153 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002154}
2155
Jamie Madill5b772312018-03-08 20:28:32 -05002156bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002157{
2158 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2159 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002160 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002161 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002162 }
2163
Jamie Madill0af26e12015-03-05 19:54:33 -05002164 const Caps &caps = context->getCaps();
2165
Jamie Madill893ab082014-05-16 16:56:10 -04002166 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2167 {
2168 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2169
Jamie Madill0af26e12015-03-05 19:54:33 -05002170 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002171 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002172 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002173 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002174 }
2175 }
2176
2177 switch (pname)
2178 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002179 case GL_TEXTURE_BINDING_2D:
2180 case GL_TEXTURE_BINDING_CUBE_MAP:
2181 case GL_TEXTURE_BINDING_3D:
2182 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002183 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002184 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002185 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2186 if (!context->getExtensions().textureRectangle)
2187 {
2188 context->handleError(InvalidEnum()
2189 << "ANGLE_texture_rectangle extension not present");
2190 return false;
2191 }
2192 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002193 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2194 if (!context->getExtensions().eglStreamConsumerExternal &&
2195 !context->getExtensions().eglImageExternal)
2196 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002197 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2198 "nor GL_OES_EGL_image_external "
2199 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002200 return false;
2201 }
2202 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002203
He Yunchaoced53ae2016-11-29 15:00:51 +08002204 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2205 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002206 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002207 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2208 ASSERT(readFramebuffer);
2209
2210 if (!ValidateFramebufferComplete(context, readFramebuffer, false))
Jamie Madill893ab082014-05-16 16:56:10 -04002211 {
Geoff Langb1196682014-07-23 13:47:29 -04002212 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002213 }
2214
Jamie Madille98b1b52018-03-08 09:47:23 -05002215 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002216 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002217 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002218 return false;
2219 }
2220
Jamie Madille98b1b52018-03-08 09:47:23 -05002221 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002222 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002223 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002224 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002225 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002226 }
2227 }
2228 break;
2229
He Yunchaoced53ae2016-11-29 15:00:51 +08002230 default:
2231 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002232 }
2233
2234 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002235 if (*numParams == 0)
2236 {
2237 return false;
2238 }
2239
2240 return true;
2241}
2242
Jamie Madill5b772312018-03-08 20:28:32 -05002243bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002244 GLenum pname,
2245 GLsizei bufSize,
2246 GLenum *nativeType,
2247 unsigned int *numParams)
2248{
2249 if (!ValidateRobustEntryPoint(context, bufSize))
2250 {
2251 return false;
2252 }
2253
2254 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2255 {
2256 return false;
2257 }
2258
2259 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002260 {
2261 return false;
2262 }
2263
2264 return true;
2265}
2266
Jamie Madill5b772312018-03-08 20:28:32 -05002267bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002268 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002269 GLint level,
2270 GLenum internalformat,
2271 bool isSubImage,
2272 GLint xoffset,
2273 GLint yoffset,
2274 GLint zoffset,
2275 GLint x,
2276 GLint y,
2277 GLsizei width,
2278 GLsizei height,
2279 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002280 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002281{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002282 TextureType texType = TextureTargetToType(target);
2283
Brandon Jones6cad5662017-06-14 13:25:13 -07002284 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002285 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002286 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2287 return false;
2288 }
2289
2290 if (width < 0 || height < 0)
2291 {
2292 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002293 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002294 }
2295
He Yunchaoced53ae2016-11-29 15:00:51 +08002296 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2297 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002298 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002299 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002300 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002301 }
2302
2303 if (border != 0)
2304 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002305 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002306 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002307 }
2308
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002309 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002310 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002311 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002312 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002313 }
2314
Jamie Madille98b1b52018-03-08 09:47:23 -05002315 const gl::State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002316 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madille98b1b52018-03-08 09:47:23 -05002317 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madill560a8d82014-05-21 13:06:20 -04002318 {
Geoff Langb1196682014-07-23 13:47:29 -04002319 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002320 }
2321
Jamie Madille98b1b52018-03-08 09:47:23 -05002322 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002323 {
Geoff Langb1196682014-07-23 13:47:29 -04002324 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002325 }
2326
Martin Radev138064f2016-07-15 12:03:41 +03002327 if (readFramebuffer->getReadBufferState() == GL_NONE)
2328 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002329 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002330 return false;
2331 }
2332
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002333 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2334 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002335 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002336 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002337 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2338 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002339 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002340 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002341 return false;
2342 }
2343
Martin Radev04e2c3b2017-07-27 16:54:35 +03002344 // ANGLE_multiview spec, Revision 1:
2345 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2346 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2347 // is not NONE.
2348 if (source->getMultiviewLayout() != GL_NONE)
2349 {
2350 context->handleError(InvalidFramebufferOperation()
2351 << "The active read framebuffer object has multiview attachments.");
2352 return false;
2353 }
2354
Geoff Langaae65a42014-05-26 12:43:44 -04002355 const gl::Caps &caps = context->getCaps();
2356
Geoff Langaae65a42014-05-26 12:43:44 -04002357 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002358 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002359 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002360 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002361 maxDimension = caps.max2DTextureSize;
2362 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002363
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002364 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002365 maxDimension = caps.maxCubeMapTextureSize;
2366 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002367
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002368 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002369 maxDimension = caps.maxRectangleTextureSize;
2370 break;
2371
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002372 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002373 maxDimension = caps.max2DTextureSize;
2374 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002375
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002376 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002377 maxDimension = caps.max3DTextureSize;
2378 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002379
He Yunchaoced53ae2016-11-29 15:00:51 +08002380 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002381 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002382 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002383 }
2384
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002385 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002386 if (!texture)
2387 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002388 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002389 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002390 }
2391
Geoff Lang69cce582015-09-17 13:20:36 -04002392 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002393 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002394 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002395 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002396 }
2397
Geoff Langca271392017-04-05 12:30:00 -04002398 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002399 isSubImage ? *texture->getFormat(target, level).info
2400 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002401
Geoff Lang966c9402017-04-18 12:38:27 -04002402 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002404 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002405 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002406 }
2407
2408 if (isSubImage)
2409 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002410 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2411 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2412 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002413 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002414 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002415 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002416 }
2417 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002418 else
2419 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002420 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002421 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002422 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002423 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002424 }
2425
Geoff Langeb66a6e2016-10-31 13:06:12 -04002426 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002427 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002428 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002429 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002430 }
2431
2432 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002433 if (static_cast<int>(width) > maxLevelDimension ||
2434 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002435 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002436 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002437 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002438 }
2439 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002440
Jamie Madill0c8abca2016-07-22 20:21:26 -04002441 if (textureFormatOut)
2442 {
2443 *textureFormatOut = texture->getFormat(target, level);
2444 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002445
2446 // Detect texture copying feedback loops for WebGL.
2447 if (context->getExtensions().webglCompatibility)
2448 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002449 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002450 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002451 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002452 return false;
2453 }
2454 }
2455
Jamie Madill560a8d82014-05-21 13:06:20 -04002456 return true;
2457}
2458
Jamie Madill5b772312018-03-08 20:28:32 -05002459bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002460{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002461 const Extensions &extensions = context->getExtensions();
2462
Jamie Madill1aeb1312014-06-20 13:21:25 -04002463 switch (mode)
2464 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002465 case GL_POINTS:
2466 case GL_LINES:
2467 case GL_LINE_LOOP:
2468 case GL_LINE_STRIP:
2469 case GL_TRIANGLES:
2470 case GL_TRIANGLE_STRIP:
2471 case GL_TRIANGLE_FAN:
2472 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002473
2474 case GL_LINES_ADJACENCY_EXT:
2475 case GL_LINE_STRIP_ADJACENCY_EXT:
2476 case GL_TRIANGLES_ADJACENCY_EXT:
2477 case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
2478 if (!extensions.geometryShader)
2479 {
2480 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2481 return false;
2482 }
2483 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002484 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002485 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002486 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002487 }
2488
Jamie Madill250d33f2014-06-06 17:09:03 -04002489 if (count < 0)
2490 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002491 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002492 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002493 }
2494
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002495 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002496
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002497 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2498 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2499 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2500 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002501 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002502 // Check for mapped buffers
2503 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002504 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002505 {
2506 context->handleError(InvalidOperation());
2507 return false;
2508 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002509 }
2510
Jamie Madillcbcde722017-01-06 14:50:00 -05002511 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2512 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002513 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002514 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002515 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002516 const FramebufferAttachment *dsAttachment =
2517 framebuffer->getStencilOrDepthStencilAttachment();
2518 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002519 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002520 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002521
2522 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2523 bool differentWritemasks =
2524 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2525 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2526 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2527 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2528
2529 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002530 {
Martin Radevffe754b2017-07-31 10:38:07 +03002531 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002532 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002533 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2534 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002535 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002536 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002537 return false;
2538 }
Jamie Madillac528012014-06-20 13:21:23 -04002539 }
2540
Jamie Madille98b1b52018-03-08 09:47:23 -05002541 if (!ValidateFramebufferComplete(context, framebuffer, true))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002542 {
Geoff Langb1196682014-07-23 13:47:29 -04002543 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002544 }
2545
Geoff Lang7dd2e102014-11-10 15:19:26 -05002546 gl::Program *program = state.getProgram();
2547 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002548 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002549 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002550 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002551 }
2552
Yunchao Hecddcb592017-11-13 15:27:35 +08002553 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2554 // vertex shader stage or fragment shader stage is a undefined behaviour.
2555 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2556 // produce undefined result.
Yunchao Heece12532017-11-21 15:50:21 +08002557 if (!program->hasLinkedVertexShader() || !program->hasLinkedFragmentShader())
Yunchao Hecddcb592017-11-13 15:27:35 +08002558 {
2559 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2560 "vertex shader stage or fragment shader stage.");
2561 return false;
2562 }
2563
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002564 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002565 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002566 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002567 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002568 }
2569
Martin Radevffe754b2017-07-31 10:38:07 +03002570 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002571 {
Martin Radevda8e2572017-09-12 17:21:16 +03002572 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002573 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002574 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002575 {
2576 context->handleError(InvalidOperation() << "The number of views in the active program "
2577 "and draw framebuffer does not match.");
2578 return false;
2579 }
Martin Radev7e69f762017-07-27 14:54:13 +03002580
2581 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2582 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2583 framebufferNumViews > 1)
2584 {
2585 context->handleError(InvalidOperation()
2586 << "There is an active transform feedback object "
2587 "when the number of views in the active draw "
2588 "framebuffer is greater than 1.");
2589 return false;
2590 }
Martin Radevffe754b2017-07-31 10:38:07 +03002591
2592 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2593 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2594 {
2595 context->handleError(InvalidOperation() << "There is an active query for target "
2596 "GL_TIME_ELAPSED_EXT when the number of "
2597 "views in the active draw framebuffer is "
2598 "greater than 1.");
2599 return false;
2600 }
Martin Radev7cf61662017-07-26 17:10:53 +03002601 }
2602
Jiawei Shaofccebff2018-03-08 13:51:02 +08002603 // Do geometry shader specific validations
2604 if (program->hasLinkedGeometryShader())
2605 {
2606 if (!IsCompatibleDrawModeWithGeometryShader(mode,
2607 program->getGeometryShaderInputPrimitiveType()))
2608 {
2609 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2610 IncompatibleDrawModeAgainstGeometryShader);
2611 return false;
2612 }
2613 }
2614
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002615 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002616 for (unsigned int uniformBlockIndex = 0;
2617 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002618 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002619 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002620 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002621 const OffsetBindingPointer<Buffer> &uniformBuffer =
2622 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002623
Geoff Lang5d124a62015-09-15 13:03:27 -04002624 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002625 {
2626 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002627 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002628 InvalidOperation()
2629 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002630 return false;
2631 }
2632
Geoff Lang5d124a62015-09-15 13:03:27 -04002633 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002634 if (uniformBufferSize == 0)
2635 {
2636 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002637 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002638 }
2639
Jamie Madill62d31cb2015-09-11 13:25:51 -04002640 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002641 {
2642 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002643 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002644 InvalidOperation()
2645 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002646 return false;
2647 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002648
2649 if (extensions.webglCompatibility &&
2650 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2651 {
2652 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2653 UniformBufferBoundForTransformFeedback);
2654 return false;
2655 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002656 }
2657
Geoff Lange0cff192017-05-30 13:04:56 -04002658 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002659 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002660 {
James Darpiniane8a93c62018-01-04 18:02:24 -08002661 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2662 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2663 transformFeedbackObject->buffersBoundForOtherUse())
2664 {
2665 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferDoubleBound);
2666 return false;
2667 }
Geoff Lange0cff192017-05-30 13:04:56 -04002668 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002669 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2670 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002671 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002672 return false;
2673 }
Geoff Lange0cff192017-05-30 13:04:56 -04002674
Geoff Lang9ab5b822017-05-30 16:19:23 -04002675 // Detect that the vertex shader input types match the attribute types
2676 if (!ValidateVertexShaderAttributeTypeMatch(context))
2677 {
2678 return false;
2679 }
2680
Geoff Lange0cff192017-05-30 13:04:56 -04002681 // Detect that the color buffer types match the fragment shader output types
2682 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2683 {
2684 return false;
2685 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002686 }
2687
Jamie Madill9fdaa492018-02-16 10:52:11 -05002688 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002689}
2690
Jamie Madill5b772312018-03-08 20:28:32 -05002691bool ValidateDrawArraysCommon(Context *context,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002692 GLenum mode,
2693 GLint first,
2694 GLsizei count,
2695 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002696{
Jamie Madillfd716582014-06-06 17:09:04 -04002697 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002698 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002699 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002700 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002701 }
2702
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002703 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002704 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002705 if (curTransformFeedback && curTransformFeedback->isActive() &&
2706 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002707 {
2708 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002709 // that does not match the current transform feedback object's draw mode (if transform
2710 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002711 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002712 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002713 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002714 }
2715
Jiajia Qind9671222016-11-29 16:30:31 +08002716 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002717 {
2718 return false;
2719 }
2720
Corentin Wallez71168a02016-12-19 15:11:18 -08002721 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002722 // - first < 0 has been checked as an error condition.
2723 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002724 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002725 ASSERT(first >= 0);
2726 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002727 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002728 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2729 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2730 {
2731 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2732 return false;
2733 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002734
Jamie Madill9fdaa492018-02-16 10:52:11 -05002735 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2736 {
2737 return false;
2738 }
Jamie Madillfd716582014-06-06 17:09:04 -04002739 }
2740
2741 return true;
2742}
2743
He Yunchaoced53ae2016-11-29 15:00:51 +08002744bool ValidateDrawArraysInstancedANGLE(Context *context,
2745 GLenum mode,
2746 GLint first,
2747 GLsizei count,
2748 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002749{
Geoff Lang63c5a592017-09-27 14:08:16 -04002750 if (!context->getExtensions().instancedArrays)
2751 {
2752 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2753 return false;
2754 }
2755
Corentin Wallez170efbf2017-05-02 13:45:01 -04002756 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002757 {
2758 return false;
2759 }
2760
Corentin Wallez0dc97812017-06-22 14:38:44 -04002761 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002762}
2763
Jamie Madill5b772312018-03-08 20:28:32 -05002764bool ValidateDrawElementsBase(Context *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002765{
Jamie Madill250d33f2014-06-06 17:09:03 -04002766 switch (type)
2767 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002768 case GL_UNSIGNED_BYTE:
2769 case GL_UNSIGNED_SHORT:
2770 break;
2771 case GL_UNSIGNED_INT:
2772 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2773 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002774 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002775 return false;
2776 }
2777 break;
2778 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002779 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002780 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002781 }
2782
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002783 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002784
2785 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002786 if (curTransformFeedback && curTransformFeedback->isActive() &&
2787 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002788 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002789 // It is an invalid operation to call DrawElements, DrawRangeElements or
2790 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002791 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002792 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002793 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002794 }
2795
Jiajia Qind9671222016-11-29 16:30:31 +08002796 return true;
2797}
2798
Jamie Madill5b772312018-03-08 20:28:32 -05002799bool ValidateDrawElementsCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002800 GLenum mode,
2801 GLsizei count,
2802 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002803 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002804 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002805{
2806 if (!ValidateDrawElementsBase(context, type))
2807 return false;
2808
2809 const State &state = context->getGLState();
2810
Corentin Wallez170efbf2017-05-02 13:45:01 -04002811 if (!ValidateDrawBase(context, mode, count))
2812 {
2813 return false;
2814 }
2815
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002816 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2817 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2818 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2819 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002820 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002821 // Check for mapped buffers
2822 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002823 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002824 {
2825 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2826 return false;
2827 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002828 }
2829
He Yunchaoced53ae2016-11-29 15:00:51 +08002830 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002831 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002832
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002833 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2834
2835 if (context->getExtensions().webglCompatibility)
2836 {
2837 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2838 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2839 {
2840 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2841 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2842 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002843 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002844 return false;
2845 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002846
2847 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2848 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2849 // error is generated.
2850 if (reinterpret_cast<intptr_t>(indices) < 0)
2851 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002852 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002853 return false;
2854 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002855 }
2856
2857 if (context->getExtensions().webglCompatibility ||
2858 !context->getGLState().areClientArraysEnabled())
2859 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002860 if (!elementArrayBuffer && count > 0)
2861 {
2862 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2863 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2864 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002865 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002866 return false;
2867 }
2868 }
2869
Jamie Madill9fdaa492018-02-16 10:52:11 -05002870 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04002871 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002872 // This is an application error that would normally result in a crash, but we catch it and
2873 // return an error
2874 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
2875 return false;
2876 }
2877
2878 if (count > 0 && elementArrayBuffer)
2879 {
2880 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2881 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2882 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2883 constexpr uint64_t kMaxTypeSize = 8;
2884 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2885 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2886 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
2887
2888 uint64_t typeSize = typeBytes;
2889 uint64_t elementCount = static_cast<uint64_t>(count);
2890 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2891
2892 // Doing the multiplication here is overflow-safe
2893 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2894
2895 // The offset can be any value, check for overflows
2896 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2897 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04002898 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002899 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2900 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002901 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05002902
2903 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2904 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002905 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002906 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
2907 return false;
2908 }
2909
2910 ASSERT(isPow2(typeSize) && typeSize > 0);
2911 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
2912 {
2913 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04002914 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002915 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002916
2917 if (context->getExtensions().webglCompatibility &&
2918 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
2919 {
2920 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2921 ElementArrayBufferBoundForTransformFeedback);
2922 return false;
2923 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002924 }
2925
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002926 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002927 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002928 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2929 // access is enabled.
2930 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2931 {
2932 return false;
2933 }
2934 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05002935 else if (count == 0)
2936 {
2937 // ValidateDrawAttribs also does some extra validation that is independent of the vertex
2938 // count.
2939 if (!ValidateDrawAttribs(context, 0, 0, 0))
2940 {
2941 return false;
2942 }
2943 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002944 else
2945 {
2946 // Use the parameter buffer to retrieve and cache the index range.
2947 const auto &params = context->getParams<HasIndexRange>();
2948 const auto &indexRangeOpt = params.getIndexRange();
2949 if (!indexRangeOpt.valid())
2950 {
2951 // Unexpected error.
2952 return false;
2953 }
2954
2955 // If we use an index greater than our maximum supported index range, return an error.
2956 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2957 // return an error if possible here.
2958 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2959 {
2960 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2961 return false;
2962 }
2963
2964 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2965 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2966 {
2967 return false;
2968 }
2969
2970 // No op if there are no real indices in the index data (all are primitive restart).
2971 return (indexRangeOpt.value().vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002972 }
2973
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002974 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002975}
2976
Jamie Madill5b772312018-03-08 20:28:32 -05002977bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002978 GLenum mode,
2979 GLsizei count,
2980 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002981 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002982 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002983{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002984 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002985}
2986
Geoff Lang3edfe032015-09-04 16:38:24 -04002987bool ValidateDrawElementsInstancedANGLE(Context *context,
2988 GLenum mode,
2989 GLsizei count,
2990 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002991 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002992 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002993{
Geoff Lang63c5a592017-09-27 14:08:16 -04002994 if (!context->getExtensions().instancedArrays)
2995 {
2996 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2997 return false;
2998 }
2999
Corentin Wallez170efbf2017-05-02 13:45:01 -04003000 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003001 {
3002 return false;
3003 }
3004
Corentin Wallez0dc97812017-06-22 14:38:44 -04003005 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003006}
3007
He Yunchaoced53ae2016-11-29 15:00:51 +08003008bool ValidateFramebufferTextureBase(Context *context,
3009 GLenum target,
3010 GLenum attachment,
3011 GLuint texture,
3012 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003013{
Geoff Lange8afa902017-09-27 15:00:43 -04003014 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003015 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003016 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003017 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003018 }
3019
3020 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003021 {
3022 return false;
3023 }
3024
Jamie Madill55ec3b12014-07-03 10:38:57 -04003025 if (texture != 0)
3026 {
3027 gl::Texture *tex = context->getTexture(texture);
3028
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003029 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003030 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003031 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003032 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003033 }
3034
3035 if (level < 0)
3036 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003037 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003038 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003039 }
3040 }
3041
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003042 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003043 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003044
Jamie Madill84115c92015-04-23 15:00:07 -04003045 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003046 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003047 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003048 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003049 }
3050
3051 return true;
3052}
3053
Geoff Langb1196682014-07-23 13:47:29 -04003054bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003055{
3056 if (program == 0)
3057 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003058 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003059 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003060 }
3061
Dian Xiang769769a2015-09-09 15:20:08 -07003062 gl::Program *programObject = GetValidProgram(context, program);
3063 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003064 {
3065 return false;
3066 }
3067
Jamie Madill0063c512014-08-25 15:47:53 -04003068 if (!programObject || !programObject->isLinked())
3069 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003070 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003071 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003072 }
3073
Geoff Lang7dd2e102014-11-10 15:19:26 -05003074 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003075 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003076 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003077 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003078 }
3079
Jamie Madill0063c512014-08-25 15:47:53 -04003080 return true;
3081}
3082
Geoff Langf41d0ee2016-10-07 13:04:23 -04003083static bool ValidateSizedGetUniform(Context *context,
3084 GLuint program,
3085 GLint location,
3086 GLsizei bufSize,
3087 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003088{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003089 if (length)
3090 {
3091 *length = 0;
3092 }
3093
Jamie Madill78f41802014-08-25 15:47:55 -04003094 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003095 {
Jamie Madill78f41802014-08-25 15:47:55 -04003096 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003097 }
3098
Geoff Langf41d0ee2016-10-07 13:04:23 -04003099 if (bufSize < 0)
3100 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003101 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003102 return false;
3103 }
3104
Jamie Madilla502c742014-08-28 17:19:13 -04003105 gl::Program *programObject = context->getProgram(program);
3106 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003107
Jamie Madill78f41802014-08-25 15:47:55 -04003108 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003109 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003110 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003111 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003112 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003113 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003114 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003115 }
3116
Geoff Langf41d0ee2016-10-07 13:04:23 -04003117 if (length)
3118 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003119 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003120 }
3121
Jamie Madill0063c512014-08-25 15:47:53 -04003122 return true;
3123}
3124
He Yunchaoced53ae2016-11-29 15:00:51 +08003125bool ValidateGetnUniformfvEXT(Context *context,
3126 GLuint program,
3127 GLint location,
3128 GLsizei bufSize,
3129 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003130{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003131 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003132}
3133
He Yunchaoced53ae2016-11-29 15:00:51 +08003134bool ValidateGetnUniformivEXT(Context *context,
3135 GLuint program,
3136 GLint location,
3137 GLsizei bufSize,
3138 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003139{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003140 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3141}
3142
3143bool ValidateGetUniformfvRobustANGLE(Context *context,
3144 GLuint program,
3145 GLint location,
3146 GLsizei bufSize,
3147 GLsizei *length,
3148 GLfloat *params)
3149{
3150 if (!ValidateRobustEntryPoint(context, bufSize))
3151 {
3152 return false;
3153 }
3154
3155 // bufSize is validated in ValidateSizedGetUniform
3156 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3157}
3158
3159bool ValidateGetUniformivRobustANGLE(Context *context,
3160 GLuint program,
3161 GLint location,
3162 GLsizei bufSize,
3163 GLsizei *length,
3164 GLint *params)
3165{
3166 if (!ValidateRobustEntryPoint(context, bufSize))
3167 {
3168 return false;
3169 }
3170
3171 // bufSize is validated in ValidateSizedGetUniform
3172 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3173}
3174
3175bool ValidateGetUniformuivRobustANGLE(Context *context,
3176 GLuint program,
3177 GLint location,
3178 GLsizei bufSize,
3179 GLsizei *length,
3180 GLuint *params)
3181{
3182 if (!ValidateRobustEntryPoint(context, bufSize))
3183 {
3184 return false;
3185 }
3186
3187 if (context->getClientMajorVersion() < 3)
3188 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003189 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003190 return false;
3191 }
3192
3193 // bufSize is validated in ValidateSizedGetUniform
3194 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003195}
3196
He Yunchaoced53ae2016-11-29 15:00:51 +08003197bool ValidateDiscardFramebufferBase(Context *context,
3198 GLenum target,
3199 GLsizei numAttachments,
3200 const GLenum *attachments,
3201 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003202{
3203 if (numAttachments < 0)
3204 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003205 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003206 return false;
3207 }
3208
3209 for (GLsizei i = 0; i < numAttachments; ++i)
3210 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003211 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003212 {
3213 if (defaultFramebuffer)
3214 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003215 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003216 return false;
3217 }
3218
3219 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3220 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003221 context->handleError(InvalidOperation() << "Requested color attachment is "
3222 "greater than the maximum supported "
3223 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003224 return false;
3225 }
3226 }
3227 else
3228 {
3229 switch (attachments[i])
3230 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003231 case GL_DEPTH_ATTACHMENT:
3232 case GL_STENCIL_ATTACHMENT:
3233 case GL_DEPTH_STENCIL_ATTACHMENT:
3234 if (defaultFramebuffer)
3235 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003236 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3237 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003238 return false;
3239 }
3240 break;
3241 case GL_COLOR:
3242 case GL_DEPTH:
3243 case GL_STENCIL:
3244 if (!defaultFramebuffer)
3245 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003246 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3247 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003248 return false;
3249 }
3250 break;
3251 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003252 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003253 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003254 }
3255 }
3256 }
3257
3258 return true;
3259}
3260
Austin Kinross6ee1e782015-05-29 17:05:37 -07003261bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3262{
Jamie Madill007530e2017-12-28 14:27:04 -05003263 if (!context->getExtensions().debugMarker)
3264 {
3265 // The debug marker calls should not set error state
3266 // However, it seems reasonable to set an error state if the extension is not enabled
3267 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3268 return false;
3269 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003270
Jamie Madill007530e2017-12-28 14:27:04 -05003271 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003272 if (length < 0)
3273 {
3274 return false;
3275 }
3276
3277 if (marker == nullptr)
3278 {
3279 return false;
3280 }
3281
3282 return true;
3283}
3284
3285bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3286{
Jamie Madill007530e2017-12-28 14:27:04 -05003287 if (!context->getExtensions().debugMarker)
3288 {
3289 // The debug marker calls should not set error state
3290 // However, it seems reasonable to set an error state if the extension is not enabled
3291 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3292 return false;
3293 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003294
Jamie Madill007530e2017-12-28 14:27:04 -05003295 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003296 if (length < 0)
3297 {
3298 return false;
3299 }
3300
3301 if (length > 0 && marker == nullptr)
3302 {
3303 return false;
3304 }
3305
3306 return true;
3307}
3308
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003309bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003310{
Geoff Langa8406172015-07-21 16:53:39 -04003311 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3312 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003313 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003314 return false;
3315 }
3316
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003317 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003318 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003319 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003320 if (!context->getExtensions().eglImage)
3321 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003322 context->handleError(InvalidEnum()
3323 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003324 }
3325 break;
3326
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003327 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003328 if (!context->getExtensions().eglImageExternal)
3329 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003330 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3331 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003332 }
Geoff Langa8406172015-07-21 16:53:39 -04003333 break;
3334
3335 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003336 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003337 return false;
3338 }
3339
Jamie Madill007530e2017-12-28 14:27:04 -05003340 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3341
Jamie Madill61e16b42017-06-19 11:13:23 -04003342 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003343 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003344 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003345 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003346 return false;
3347 }
3348
Jamie Madill007530e2017-12-28 14:27:04 -05003349 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003350 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003351 context->handleError(InvalidOperation()
3352 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003353 return false;
3354 }
3355
Geoff Langca271392017-04-05 12:30:00 -04003356 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003357 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003358 if (!textureCaps.texturable)
3359 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003360 context->handleError(InvalidOperation()
3361 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003362 return false;
3363 }
3364
Geoff Langdcab33b2015-07-21 13:03:16 -04003365 return true;
3366}
3367
3368bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003369 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003370 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003371{
Geoff Langa8406172015-07-21 16:53:39 -04003372 if (!context->getExtensions().eglImage)
3373 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003374 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003375 return false;
3376 }
3377
3378 switch (target)
3379 {
3380 case GL_RENDERBUFFER:
3381 break;
3382
3383 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003384 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003385 return false;
3386 }
3387
Jamie Madill007530e2017-12-28 14:27:04 -05003388 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3389
Jamie Madill61e16b42017-06-19 11:13:23 -04003390 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003391 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003392 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003393 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003394 return false;
3395 }
3396
Geoff Langca271392017-04-05 12:30:00 -04003397 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003398 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003399 if (!textureCaps.renderable)
3400 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003401 context->handleError(InvalidOperation()
3402 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003403 return false;
3404 }
3405
Geoff Langdcab33b2015-07-21 13:03:16 -04003406 return true;
3407}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003408
3409bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3410{
Geoff Lang36167ab2015-12-07 10:27:14 -05003411 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003412 {
3413 // The default VAO should always exist
3414 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003415 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003416 return false;
3417 }
3418
3419 return true;
3420}
3421
Geoff Langc5629752015-12-07 16:29:04 -05003422bool ValidateProgramBinaryBase(Context *context,
3423 GLuint program,
3424 GLenum binaryFormat,
3425 const void *binary,
3426 GLint length)
3427{
3428 Program *programObject = GetValidProgram(context, program);
3429 if (programObject == nullptr)
3430 {
3431 return false;
3432 }
3433
3434 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3435 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3436 programBinaryFormats.end())
3437 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003438 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003439 return false;
3440 }
3441
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003442 if (context->hasActiveTransformFeedback(program))
3443 {
3444 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003445 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3446 "is associated with an active transform "
3447 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003448 return false;
3449 }
3450
Geoff Langc5629752015-12-07 16:29:04 -05003451 return true;
3452}
3453
3454bool ValidateGetProgramBinaryBase(Context *context,
3455 GLuint program,
3456 GLsizei bufSize,
3457 GLsizei *length,
3458 GLenum *binaryFormat,
3459 void *binary)
3460{
3461 Program *programObject = GetValidProgram(context, program);
3462 if (programObject == nullptr)
3463 {
3464 return false;
3465 }
3466
3467 if (!programObject->isLinked())
3468 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003469 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003470 return false;
3471 }
3472
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003473 if (context->getCaps().programBinaryFormats.empty())
3474 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003475 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003476 return false;
3477 }
3478
Geoff Langc5629752015-12-07 16:29:04 -05003479 return true;
3480}
Jamie Madillc29968b2016-01-20 11:17:23 -05003481
Jamie Madill5b772312018-03-08 20:28:32 -05003482bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003483{
3484 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003485 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003486 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003487 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3488 return false;
3489 }
3490 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3491 {
3492 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003493 return false;
3494 }
3495
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003496 ASSERT(context->getGLState().getDrawFramebuffer());
3497 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003498 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3499
3500 // This should come first before the check for the default frame buffer
3501 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3502 // rather than INVALID_OPERATION
3503 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3504 {
3505 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3506
3507 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003508 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3509 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003510 {
3511 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003512 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3513 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3514 // 3.1 is still a bit ambiguous about the error, but future specs are
3515 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003516 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003517 return false;
3518 }
3519 else if (bufs[colorAttachment] >= maxColorAttachment)
3520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003521 context->handleError(InvalidOperation()
3522 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003523 return false;
3524 }
3525 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3526 frameBufferId != 0)
3527 {
3528 // INVALID_OPERATION-GL is bound to buffer and ith argument
3529 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003530 context->handleError(InvalidOperation()
3531 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003532 return false;
3533 }
3534 }
3535
3536 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3537 // and n is not 1 or bufs is bound to value other than BACK and NONE
3538 if (frameBufferId == 0)
3539 {
3540 if (n != 1)
3541 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003542 context->handleError(InvalidOperation()
3543 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003544 return false;
3545 }
3546
3547 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3548 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003549 context->handleError(
3550 InvalidOperation()
3551 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003552 return false;
3553 }
3554 }
3555
3556 return true;
3557}
3558
Geoff Lang496c02d2016-10-20 11:38:11 -07003559bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003560 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003561 GLenum pname,
3562 GLsizei *length,
3563 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003564{
Geoff Lang496c02d2016-10-20 11:38:11 -07003565 if (length)
3566 {
3567 *length = 0;
3568 }
3569
3570 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3571 {
3572 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003573 InvalidOperation()
3574 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003575 return false;
3576 }
3577
Corentin Walleze4477002017-12-01 14:39:58 -05003578 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003579 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003580 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003581 return false;
3582 }
3583
Geoff Lang496c02d2016-10-20 11:38:11 -07003584 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003585 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003586 case GL_BUFFER_MAP_POINTER:
3587 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003588
Geoff Lang496c02d2016-10-20 11:38:11 -07003589 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003590 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003591 return false;
3592 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003593
3594 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3595 // target bound to zero generate an INVALID_OPERATION error."
3596 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003597 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003598 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003599 context->handleError(InvalidOperation()
3600 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003601 return false;
3602 }
3603
Geoff Lang496c02d2016-10-20 11:38:11 -07003604 if (length)
3605 {
3606 *length = 1;
3607 }
3608
Olli Etuaho4f667482016-03-30 15:56:35 +03003609 return true;
3610}
3611
Corentin Wallez336129f2017-10-17 15:55:40 -04003612bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003613{
Corentin Walleze4477002017-12-01 14:39:58 -05003614 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003615 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003616 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003617 return false;
3618 }
3619
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003620 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003621
3622 if (buffer == nullptr || !buffer->isMapped())
3623 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003624 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003625 return false;
3626 }
3627
3628 return true;
3629}
3630
3631bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003632 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003633 GLintptr offset,
3634 GLsizeiptr length,
3635 GLbitfield access)
3636{
Corentin Walleze4477002017-12-01 14:39:58 -05003637 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003638 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003639 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003640 return false;
3641 }
3642
Brandon Jones6cad5662017-06-14 13:25:13 -07003643 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003644 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003645 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3646 return false;
3647 }
3648
3649 if (length < 0)
3650 {
3651 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003652 return false;
3653 }
3654
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003655 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003656
3657 if (!buffer)
3658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003659 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003660 return false;
3661 }
3662
3663 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003664 CheckedNumeric<size_t> checkedOffset(offset);
3665 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003666
Jamie Madille2e406c2016-06-02 13:04:10 -04003667 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003668 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003669 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003670 return false;
3671 }
3672
3673 // Check for invalid bits in the mask
3674 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3675 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3676 GL_MAP_UNSYNCHRONIZED_BIT;
3677
3678 if (access & ~(allAccessBits))
3679 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003680 context->handleError(InvalidValue()
3681 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003682 return false;
3683 }
3684
3685 if (length == 0)
3686 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003687 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003688 return false;
3689 }
3690
3691 if (buffer->isMapped())
3692 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003693 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003694 return false;
3695 }
3696
3697 // Check for invalid bit combinations
3698 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3699 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003700 context->handleError(InvalidOperation()
3701 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003702 return false;
3703 }
3704
3705 GLbitfield writeOnlyBits =
3706 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3707
3708 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3709 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003710 context->handleError(InvalidOperation()
3711 << "Invalid access bits when mapping buffer for reading: 0x"
3712 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003713 return false;
3714 }
3715
3716 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3717 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003718 context->handleError(
3719 InvalidOperation()
3720 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003721 return false;
3722 }
Geoff Lang79f71042017-08-14 16:43:43 -04003723
3724 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003725}
3726
3727bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003728 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003729 GLintptr offset,
3730 GLsizeiptr length)
3731{
Brandon Jones6cad5662017-06-14 13:25:13 -07003732 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003733 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003734 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3735 return false;
3736 }
3737
3738 if (length < 0)
3739 {
3740 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003741 return false;
3742 }
3743
Corentin Walleze4477002017-12-01 14:39:58 -05003744 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003745 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003746 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003747 return false;
3748 }
3749
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003750 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003751
3752 if (buffer == nullptr)
3753 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003754 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003755 return false;
3756 }
3757
3758 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3759 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003760 context->handleError(InvalidOperation()
3761 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003762 return false;
3763 }
3764
3765 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003766 CheckedNumeric<size_t> checkedOffset(offset);
3767 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003768
Jamie Madille2e406c2016-06-02 13:04:10 -04003769 if (!checkedSize.IsValid() ||
3770 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003771 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003772 context->handleError(InvalidValue()
3773 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003774 return false;
3775 }
3776
3777 return true;
3778}
3779
Olli Etuaho41997e72016-03-10 13:38:39 +02003780bool ValidateGenOrDelete(Context *context, GLint n)
3781{
3782 if (n < 0)
3783 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003784 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003785 return false;
3786 }
3787 return true;
3788}
3789
Jamie Madill5b772312018-03-08 20:28:32 -05003790bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003791{
3792 if (!context->getExtensions().robustClientMemory)
3793 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003794 context->handleError(InvalidOperation()
3795 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003796 return false;
3797 }
3798
3799 if (bufSize < 0)
3800 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003801 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003802 return false;
3803 }
3804
3805 return true;
3806}
3807
Jamie Madill5b772312018-03-08 20:28:32 -05003808bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003809{
3810 if (bufSize < numParams)
3811 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003812 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3813 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003814 return false;
3815 }
3816
3817 return true;
3818}
3819
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003820bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04003821 GLenum target,
3822 GLenum attachment,
3823 GLenum pname,
3824 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003825{
Geoff Lange8afa902017-09-27 15:00:43 -04003826 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003827 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003828 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003829 return false;
3830 }
3831
3832 int clientVersion = context->getClientMajorVersion();
3833
3834 switch (pname)
3835 {
3836 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3837 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3838 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3839 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3840 break;
3841
Martin Radeve5285d22017-07-14 16:23:53 +03003842 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3843 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3844 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3845 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3846 if (clientVersion < 3 || !context->getExtensions().multiview)
3847 {
3848 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3849 return false;
3850 }
3851 break;
3852
Geoff Langff5b2d52016-09-07 11:32:23 -04003853 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3854 if (clientVersion < 3 && !context->getExtensions().sRGB)
3855 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003856 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003857 return false;
3858 }
3859 break;
3860
3861 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3862 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3863 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3864 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3865 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3866 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3867 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3868 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3869 if (clientVersion < 3)
3870 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003871 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003872 return false;
3873 }
3874 break;
3875
3876 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003877 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003878 return false;
3879 }
3880
3881 // Determine if the attachment is a valid enum
3882 switch (attachment)
3883 {
3884 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04003885 case GL_DEPTH:
3886 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04003887 if (clientVersion < 3)
3888 {
Geoff Langfa125c92017-10-24 13:01:46 -04003889 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003890 return false;
3891 }
3892 break;
3893
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003894 case GL_DEPTH_STENCIL_ATTACHMENT:
3895 if (clientVersion < 3 && !context->isWebGL1())
3896 {
3897 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3898 return false;
3899 }
3900 break;
3901
Geoff Langfa125c92017-10-24 13:01:46 -04003902 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003903 case GL_DEPTH_ATTACHMENT:
3904 case GL_STENCIL_ATTACHMENT:
3905 break;
3906
3907 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003908 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3909 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003910 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3911 {
Geoff Langfa125c92017-10-24 13:01:46 -04003912 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003913 return false;
3914 }
3915 break;
3916 }
3917
3918 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3919 ASSERT(framebuffer);
3920
3921 if (framebuffer->id() == 0)
3922 {
3923 if (clientVersion < 3)
3924 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003925 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003926 return false;
3927 }
3928
3929 switch (attachment)
3930 {
3931 case GL_BACK:
3932 case GL_DEPTH:
3933 case GL_STENCIL:
3934 break;
3935
3936 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003937 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003938 return false;
3939 }
3940 }
3941 else
3942 {
3943 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3944 {
3945 // Valid attachment query
3946 }
3947 else
3948 {
3949 switch (attachment)
3950 {
3951 case GL_DEPTH_ATTACHMENT:
3952 case GL_STENCIL_ATTACHMENT:
3953 break;
3954
3955 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003956 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04003957 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003958 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003959 return false;
3960 }
3961 break;
3962
3963 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003964 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003965 return false;
3966 }
3967 }
3968 }
3969
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003970 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003971 if (attachmentObject)
3972 {
3973 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3974 attachmentObject->type() == GL_TEXTURE ||
3975 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3976
3977 switch (pname)
3978 {
3979 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3980 if (attachmentObject->type() != GL_RENDERBUFFER &&
3981 attachmentObject->type() != GL_TEXTURE)
3982 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003983 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003984 return false;
3985 }
3986 break;
3987
3988 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3989 if (attachmentObject->type() != GL_TEXTURE)
3990 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003991 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003992 return false;
3993 }
3994 break;
3995
3996 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3997 if (attachmentObject->type() != GL_TEXTURE)
3998 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003999 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004000 return false;
4001 }
4002 break;
4003
4004 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4005 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4006 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004007 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004008 return false;
4009 }
4010 break;
4011
4012 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4013 if (attachmentObject->type() != GL_TEXTURE)
4014 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004015 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004016 return false;
4017 }
4018 break;
4019
4020 default:
4021 break;
4022 }
4023 }
4024 else
4025 {
4026 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4027 // is NONE, then querying any other pname will generate INVALID_ENUM.
4028
4029 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4030 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4031 // INVALID_OPERATION for all other pnames
4032
4033 switch (pname)
4034 {
4035 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4036 break;
4037
4038 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4039 if (clientVersion < 3)
4040 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004041 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004042 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004043 return false;
4044 }
4045 break;
4046
4047 default:
4048 if (clientVersion < 3)
4049 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004050 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004051 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004052 return false;
4053 }
4054 else
4055 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004056 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004057 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004058 return false;
4059 }
4060 }
4061 }
4062
Martin Radeve5285d22017-07-14 16:23:53 +03004063 if (numParams)
4064 {
4065 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4066 {
4067 // Only when the viewport offsets are queried we can have a varying number of output
4068 // parameters.
4069 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4070 *numParams = numViews * 2;
4071 }
4072 else
4073 {
4074 // For all other queries we can have only one output parameter.
4075 *numParams = 1;
4076 }
4077 }
4078
Geoff Langff5b2d52016-09-07 11:32:23 -04004079 return true;
4080}
4081
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004082bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004083 GLenum target,
4084 GLenum attachment,
4085 GLenum pname,
4086 GLsizei bufSize,
4087 GLsizei *numParams)
4088{
4089 if (!ValidateRobustEntryPoint(context, bufSize))
4090 {
4091 return false;
4092 }
4093
Jamie Madillbe849e42017-05-02 15:49:00 -04004094 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4095 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004096 {
4097 return false;
4098 }
4099
4100 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4101 {
4102 return false;
4103 }
4104
4105 return true;
4106}
4107
Jamie Madill5b772312018-03-08 20:28:32 -05004108bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004109 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004110 GLenum pname,
4111 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004112 GLsizei *length,
4113 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004114{
4115 if (!ValidateRobustEntryPoint(context, bufSize))
4116 {
4117 return false;
4118 }
4119
Geoff Langebebe1c2016-10-14 12:01:31 -04004120 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004121 {
4122 return false;
4123 }
4124
Geoff Langebebe1c2016-10-14 12:01:31 -04004125 if (!ValidateRobustBufferSize(context, bufSize, *length))
4126 {
4127 return false;
4128 }
4129
4130 return true;
4131}
4132
Jamie Madill5b772312018-03-08 20:28:32 -05004133bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004134 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004135 GLenum pname,
4136 GLsizei bufSize,
4137 GLsizei *length,
4138 GLint64 *params)
4139{
4140 if (!ValidateRobustEntryPoint(context, bufSize))
4141 {
4142 return false;
4143 }
4144
4145 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4146 {
4147 return false;
4148 }
4149
4150 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004151 {
4152 return false;
4153 }
4154
4155 return true;
4156}
4157
Jamie Madill5b772312018-03-08 20:28:32 -05004158bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004159{
4160 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004161 if (numParams)
4162 {
4163 *numParams = 1;
4164 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004165
4166 Program *programObject = GetValidProgram(context, program);
4167 if (!programObject)
4168 {
4169 return false;
4170 }
4171
4172 switch (pname)
4173 {
4174 case GL_DELETE_STATUS:
4175 case GL_LINK_STATUS:
4176 case GL_VALIDATE_STATUS:
4177 case GL_INFO_LOG_LENGTH:
4178 case GL_ATTACHED_SHADERS:
4179 case GL_ACTIVE_ATTRIBUTES:
4180 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4181 case GL_ACTIVE_UNIFORMS:
4182 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4183 break;
4184
4185 case GL_PROGRAM_BINARY_LENGTH:
4186 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4187 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004188 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4189 "requires GL_OES_get_program_binary or "
4190 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004191 return false;
4192 }
4193 break;
4194
4195 case GL_ACTIVE_UNIFORM_BLOCKS:
4196 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4197 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4198 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4199 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4200 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4201 if (context->getClientMajorVersion() < 3)
4202 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004203 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004204 return false;
4205 }
4206 break;
4207
Yunchao He61afff12017-03-14 15:34:03 +08004208 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004209 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004210 if (context->getClientVersion() < Version(3, 1))
4211 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004212 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004213 return false;
4214 }
4215 break;
4216
Jiawei Shao6ae51612018-02-23 14:03:25 +08004217 case GL_COMPUTE_WORK_GROUP_SIZE:
4218 if (context->getClientVersion() < Version(3, 1))
4219 {
4220 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4221 return false;
4222 }
4223
4224 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4225 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4226 // program which has not been linked successfully, or which does not contain objects to
4227 // form a compute shader.
4228 if (!programObject->isLinked())
4229 {
4230 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4231 return false;
4232 }
4233 if (!programObject->hasLinkedComputeShader())
4234 {
4235 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4236 return false;
4237 }
4238 break;
4239
Geoff Langff5b2d52016-09-07 11:32:23 -04004240 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004241 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004242 return false;
4243 }
4244
4245 return true;
4246}
4247
4248bool ValidateGetProgramivRobustANGLE(Context *context,
4249 GLuint program,
4250 GLenum pname,
4251 GLsizei bufSize,
4252 GLsizei *numParams)
4253{
4254 if (!ValidateRobustEntryPoint(context, bufSize))
4255 {
4256 return false;
4257 }
4258
Jamie Madillbe849e42017-05-02 15:49:00 -04004259 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004260 {
4261 return false;
4262 }
4263
4264 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4265 {
4266 return false;
4267 }
4268
4269 return true;
4270}
4271
Geoff Lang740d9022016-10-07 11:20:52 -04004272bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4273 GLenum target,
4274 GLenum pname,
4275 GLsizei bufSize,
4276 GLsizei *length,
4277 GLint *params)
4278{
4279 if (!ValidateRobustEntryPoint(context, bufSize))
4280 {
4281 return false;
4282 }
4283
4284 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4285 {
4286 return false;
4287 }
4288
4289 if (!ValidateRobustBufferSize(context, bufSize, *length))
4290 {
4291 return false;
4292 }
4293
4294 return true;
4295}
4296
Geoff Langd7d0ed32016-10-07 11:33:51 -04004297bool ValidateGetShaderivRobustANGLE(Context *context,
4298 GLuint shader,
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 (!ValidateGetShaderivBase(context, shader, 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 Langc1984ed2016-10-07 12:41:00 -04004322bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004323 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004324 GLenum pname,
4325 GLsizei bufSize,
4326 GLsizei *length,
4327 GLfloat *params)
4328{
4329 if (!ValidateRobustEntryPoint(context, bufSize))
4330 {
4331 return false;
4332 }
4333
4334 if (!ValidateGetTexParameterBase(context, target, 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 ValidateGetTexParameterivRobustANGLE(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 GLint *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 ValidateTexParameterfvRobustANGLE(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 const GLfloat *params)
4377{
4378 if (!ValidateRobustEntryPoint(context, bufSize))
4379 {
4380 return false;
4381 }
4382
4383 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4384}
4385
Geoff Langc1984ed2016-10-07 12:41:00 -04004386bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004387 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004388 GLenum pname,
4389 GLsizei bufSize,
4390 const GLint *params)
4391{
4392 if (!ValidateRobustEntryPoint(context, bufSize))
4393 {
4394 return false;
4395 }
4396
4397 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4398}
4399
Geoff Langc1984ed2016-10-07 12:41:00 -04004400bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4401 GLuint sampler,
4402 GLenum pname,
4403 GLuint bufSize,
4404 GLsizei *length,
4405 GLfloat *params)
4406{
4407 if (!ValidateRobustEntryPoint(context, bufSize))
4408 {
4409 return false;
4410 }
4411
4412 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4413 {
4414 return false;
4415 }
4416
4417 if (!ValidateRobustBufferSize(context, bufSize, *length))
4418 {
4419 return false;
4420 }
4421
4422 return true;
4423}
4424
Geoff Langc1984ed2016-10-07 12:41:00 -04004425bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4426 GLuint sampler,
4427 GLenum pname,
4428 GLuint bufSize,
4429 GLsizei *length,
4430 GLint *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 ValidateSamplerParameterfvRobustANGLE(Context *context,
4451 GLuint sampler,
4452 GLenum pname,
4453 GLsizei bufSize,
4454 const GLfloat *params)
4455{
4456 if (!ValidateRobustEntryPoint(context, bufSize))
4457 {
4458 return false;
4459 }
4460
4461 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4462}
4463
Geoff Langc1984ed2016-10-07 12:41:00 -04004464bool ValidateSamplerParameterivRobustANGLE(Context *context,
4465 GLuint sampler,
4466 GLenum pname,
4467 GLsizei bufSize,
4468 const GLint *params)
4469{
4470 if (!ValidateRobustEntryPoint(context, bufSize))
4471 {
4472 return false;
4473 }
4474
4475 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4476}
4477
Geoff Lang0b031062016-10-13 14:30:04 -04004478bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4479 GLuint index,
4480 GLenum pname,
4481 GLsizei bufSize,
4482 GLsizei *length,
4483 GLfloat *params)
4484{
4485 if (!ValidateRobustEntryPoint(context, bufSize))
4486 {
4487 return false;
4488 }
4489
4490 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4491 {
4492 return false;
4493 }
4494
4495 if (!ValidateRobustBufferSize(context, bufSize, *length))
4496 {
4497 return false;
4498 }
4499
4500 return true;
4501}
4502
Geoff Lang0b031062016-10-13 14:30:04 -04004503bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4504 GLuint index,
4505 GLenum pname,
4506 GLsizei bufSize,
4507 GLsizei *length,
4508 GLint *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 ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4529 GLuint index,
4530 GLenum pname,
4531 GLsizei bufSize,
4532 GLsizei *length,
4533 void **pointer)
4534{
4535 if (!ValidateRobustEntryPoint(context, bufSize))
4536 {
4537 return false;
4538 }
4539
4540 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, 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 ValidateGetVertexAttribIivRobustANGLE(Context *context,
4554 GLuint index,
4555 GLenum pname,
4556 GLsizei bufSize,
4557 GLsizei *length,
4558 GLint *params)
4559{
4560 if (!ValidateRobustEntryPoint(context, bufSize))
4561 {
4562 return false;
4563 }
4564
4565 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
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 ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4579 GLuint index,
4580 GLenum pname,
4581 GLsizei bufSize,
4582 GLsizei *length,
4583 GLuint *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 Lang6899b872016-10-14 11:30:13 -04004603bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4604 GLuint program,
4605 GLuint uniformBlockIndex,
4606 GLenum pname,
4607 GLsizei bufSize,
4608 GLsizei *length,
4609 GLint *params)
4610{
4611 if (!ValidateRobustEntryPoint(context, bufSize))
4612 {
4613 return false;
4614 }
4615
4616 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4617 {
4618 return false;
4619 }
4620
4621 if (!ValidateRobustBufferSize(context, bufSize, *length))
4622 {
4623 return false;
4624 }
4625
4626 return true;
4627}
4628
Geoff Lang0a9661f2016-10-20 10:59:20 -07004629bool ValidateGetInternalFormativRobustANGLE(Context *context,
4630 GLenum target,
4631 GLenum internalformat,
4632 GLenum pname,
4633 GLsizei bufSize,
4634 GLsizei *length,
4635 GLint *params)
4636{
4637 if (!ValidateRobustEntryPoint(context, bufSize))
4638 {
4639 return false;
4640 }
4641
4642 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4643 {
4644 return false;
4645 }
4646
4647 if (!ValidateRobustBufferSize(context, bufSize, *length))
4648 {
4649 return false;
4650 }
4651
4652 return true;
4653}
4654
Jamie Madill5b772312018-03-08 20:28:32 -05004655bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08004656 GLuint attribIndex,
4657 GLint size,
4658 GLenum type,
4659 GLboolean pureInteger)
4660{
4661 const Caps &caps = context->getCaps();
4662 if (attribIndex >= caps.maxVertexAttributes)
4663 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004664 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004665 return false;
4666 }
4667
4668 if (size < 1 || size > 4)
4669 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004670 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004671 return false;
Shao80957d92017-02-20 21:25:59 +08004672 }
4673
4674 switch (type)
4675 {
4676 case GL_BYTE:
4677 case GL_UNSIGNED_BYTE:
4678 case GL_SHORT:
4679 case GL_UNSIGNED_SHORT:
4680 break;
4681
4682 case GL_INT:
4683 case GL_UNSIGNED_INT:
4684 if (context->getClientMajorVersion() < 3)
4685 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004686 context->handleError(InvalidEnum()
4687 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004688 return false;
4689 }
4690 break;
4691
4692 case GL_FIXED:
4693 case GL_FLOAT:
4694 if (pureInteger)
4695 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004696 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004697 return false;
4698 }
4699 break;
4700
4701 case GL_HALF_FLOAT:
4702 if (context->getClientMajorVersion() < 3)
4703 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004704 context->handleError(InvalidEnum()
4705 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004706 return false;
4707 }
4708 if (pureInteger)
4709 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004710 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004711 return false;
4712 }
4713 break;
4714
4715 case GL_INT_2_10_10_10_REV:
4716 case GL_UNSIGNED_INT_2_10_10_10_REV:
4717 if (context->getClientMajorVersion() < 3)
4718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004719 context->handleError(InvalidEnum()
4720 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004721 return false;
4722 }
4723 if (pureInteger)
4724 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004725 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004726 return false;
4727 }
4728 if (size != 4)
4729 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004730 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4731 "UNSIGNED_INT_2_10_10_10_REV and "
4732 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004733 return false;
4734 }
4735 break;
4736
4737 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004738 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004739 return false;
4740 }
4741
4742 return true;
4743}
4744
Geoff Lang76e65652017-03-27 14:58:02 -04004745// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4746// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4747// specified clear value and the type of a buffer that is being cleared generates an
4748// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05004749bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04004750 GLint drawbuffer,
4751 const GLenum *validComponentTypes,
4752 size_t validComponentTypeCount)
4753{
4754 const FramebufferAttachment *attachment =
4755 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4756 if (attachment)
4757 {
4758 GLenum componentType = attachment->getFormat().info->componentType;
4759 const GLenum *end = validComponentTypes + validComponentTypeCount;
4760 if (std::find(validComponentTypes, end, componentType) == end)
4761 {
4762 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004763 InvalidOperation()
4764 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004765 return false;
4766 }
4767 }
4768
4769 return true;
4770}
4771
Jamie Madill5b772312018-03-08 20:28:32 -05004772bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04004773{
4774 if (!ValidateRobustEntryPoint(context, dataSize))
4775 {
4776 return false;
4777 }
4778
Corentin Wallez336129f2017-10-17 15:55:40 -04004779 gl::Buffer *pixelUnpackBuffer =
4780 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004781 if (pixelUnpackBuffer == nullptr)
4782 {
4783 if (dataSize < imageSize)
4784 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004785 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004786 }
4787 }
4788 return true;
4789}
4790
Jamie Madill5b772312018-03-08 20:28:32 -05004791bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004792 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004793 GLenum pname,
4794 bool pointerVersion,
4795 GLsizei *numParams)
4796{
4797 if (numParams)
4798 {
4799 *numParams = 0;
4800 }
4801
Corentin Walleze4477002017-12-01 14:39:58 -05004802 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004803 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004804 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004805 return false;
4806 }
4807
4808 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4809 if (!buffer)
4810 {
4811 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004812 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004813 return false;
4814 }
4815
4816 const Extensions &extensions = context->getExtensions();
4817
4818 switch (pname)
4819 {
4820 case GL_BUFFER_USAGE:
4821 case GL_BUFFER_SIZE:
4822 break;
4823
4824 case GL_BUFFER_ACCESS_OES:
4825 if (!extensions.mapBuffer)
4826 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004827 context->handleError(InvalidEnum()
4828 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004829 return false;
4830 }
4831 break;
4832
4833 case GL_BUFFER_MAPPED:
4834 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4835 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4836 !extensions.mapBufferRange)
4837 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004838 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4839 "GL_OES_mapbuffer or "
4840 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004841 return false;
4842 }
4843 break;
4844
4845 case GL_BUFFER_MAP_POINTER:
4846 if (!pointerVersion)
4847 {
4848 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004849 InvalidEnum()
4850 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004851 return false;
4852 }
4853 break;
4854
4855 case GL_BUFFER_ACCESS_FLAGS:
4856 case GL_BUFFER_MAP_OFFSET:
4857 case GL_BUFFER_MAP_LENGTH:
4858 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4859 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004860 context->handleError(InvalidEnum()
4861 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004862 return false;
4863 }
4864 break;
4865
4866 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004867 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004868 return false;
4869 }
4870
4871 // All buffer parameter queries return one value.
4872 if (numParams)
4873 {
4874 *numParams = 1;
4875 }
4876
4877 return true;
4878}
4879
4880bool ValidateGetRenderbufferParameterivBase(Context *context,
4881 GLenum target,
4882 GLenum pname,
4883 GLsizei *length)
4884{
4885 if (length)
4886 {
4887 *length = 0;
4888 }
4889
4890 if (target != GL_RENDERBUFFER)
4891 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004892 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004893 return false;
4894 }
4895
4896 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4897 if (renderbuffer == nullptr)
4898 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004899 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004900 return false;
4901 }
4902
4903 switch (pname)
4904 {
4905 case GL_RENDERBUFFER_WIDTH:
4906 case GL_RENDERBUFFER_HEIGHT:
4907 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4908 case GL_RENDERBUFFER_RED_SIZE:
4909 case GL_RENDERBUFFER_GREEN_SIZE:
4910 case GL_RENDERBUFFER_BLUE_SIZE:
4911 case GL_RENDERBUFFER_ALPHA_SIZE:
4912 case GL_RENDERBUFFER_DEPTH_SIZE:
4913 case GL_RENDERBUFFER_STENCIL_SIZE:
4914 break;
4915
4916 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4917 if (!context->getExtensions().framebufferMultisample)
4918 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004919 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004920 return false;
4921 }
4922 break;
4923
4924 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004925 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004926 return false;
4927 }
4928
4929 if (length)
4930 {
4931 *length = 1;
4932 }
4933 return true;
4934}
4935
4936bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4937{
4938 if (length)
4939 {
4940 *length = 0;
4941 }
4942
4943 if (GetValidShader(context, shader) == nullptr)
4944 {
4945 return false;
4946 }
4947
4948 switch (pname)
4949 {
4950 case GL_SHADER_TYPE:
4951 case GL_DELETE_STATUS:
4952 case GL_COMPILE_STATUS:
4953 case GL_INFO_LOG_LENGTH:
4954 case GL_SHADER_SOURCE_LENGTH:
4955 break;
4956
4957 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4958 if (!context->getExtensions().translatedShaderSource)
4959 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004960 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004961 return false;
4962 }
4963 break;
4964
4965 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004966 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004967 return false;
4968 }
4969
4970 if (length)
4971 {
4972 *length = 1;
4973 }
4974 return true;
4975}
4976
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004977bool ValidateGetTexParameterBase(Context *context,
4978 TextureType target,
4979 GLenum pname,
4980 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04004981{
4982 if (length)
4983 {
4984 *length = 0;
4985 }
4986
4987 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4988 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004989 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004990 return false;
4991 }
4992
4993 if (context->getTargetTexture(target) == nullptr)
4994 {
4995 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004996 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004997 return false;
4998 }
4999
5000 switch (pname)
5001 {
5002 case GL_TEXTURE_MAG_FILTER:
5003 case GL_TEXTURE_MIN_FILTER:
5004 case GL_TEXTURE_WRAP_S:
5005 case GL_TEXTURE_WRAP_T:
5006 break;
5007
5008 case GL_TEXTURE_USAGE_ANGLE:
5009 if (!context->getExtensions().textureUsage)
5010 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005011 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005012 return false;
5013 }
5014 break;
5015
5016 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005017 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005018 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005019 return false;
5020 }
5021 break;
5022
5023 case GL_TEXTURE_IMMUTABLE_FORMAT:
5024 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5025 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005026 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005027 return false;
5028 }
5029 break;
5030
5031 case GL_TEXTURE_WRAP_R:
5032 case GL_TEXTURE_IMMUTABLE_LEVELS:
5033 case GL_TEXTURE_SWIZZLE_R:
5034 case GL_TEXTURE_SWIZZLE_G:
5035 case GL_TEXTURE_SWIZZLE_B:
5036 case GL_TEXTURE_SWIZZLE_A:
5037 case GL_TEXTURE_BASE_LEVEL:
5038 case GL_TEXTURE_MAX_LEVEL:
5039 case GL_TEXTURE_MIN_LOD:
5040 case GL_TEXTURE_MAX_LOD:
5041 case GL_TEXTURE_COMPARE_MODE:
5042 case GL_TEXTURE_COMPARE_FUNC:
5043 if (context->getClientMajorVersion() < 3)
5044 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005045 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005046 return false;
5047 }
5048 break;
5049
5050 case GL_TEXTURE_SRGB_DECODE_EXT:
5051 if (!context->getExtensions().textureSRGBDecode)
5052 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005053 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005054 return false;
5055 }
5056 break;
5057
Yunchao Hebacaa712018-01-30 14:01:39 +08005058 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5059 if (context->getClientVersion() < Version(3, 1))
5060 {
5061 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5062 return false;
5063 }
5064 break;
5065
Jamie Madillbe849e42017-05-02 15:49:00 -04005066 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005067 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005068 return false;
5069 }
5070
5071 if (length)
5072 {
5073 *length = 1;
5074 }
5075 return true;
5076}
5077
5078bool ValidateGetVertexAttribBase(Context *context,
5079 GLuint index,
5080 GLenum pname,
5081 GLsizei *length,
5082 bool pointer,
5083 bool pureIntegerEntryPoint)
5084{
5085 if (length)
5086 {
5087 *length = 0;
5088 }
5089
5090 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5091 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005092 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005093 return false;
5094 }
5095
5096 if (index >= context->getCaps().maxVertexAttributes)
5097 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005098 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005099 return false;
5100 }
5101
5102 if (pointer)
5103 {
5104 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5105 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005106 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005107 return false;
5108 }
5109 }
5110 else
5111 {
5112 switch (pname)
5113 {
5114 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5115 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5116 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5117 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5118 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5119 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5120 case GL_CURRENT_VERTEX_ATTRIB:
5121 break;
5122
5123 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5124 static_assert(
5125 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5126 "ANGLE extension enums not equal to GL enums.");
5127 if (context->getClientMajorVersion() < 3 &&
5128 !context->getExtensions().instancedArrays)
5129 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005130 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5131 "requires OpenGL ES 3.0 or "
5132 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005133 return false;
5134 }
5135 break;
5136
5137 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5138 if (context->getClientMajorVersion() < 3)
5139 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005140 context->handleError(
5141 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005142 return false;
5143 }
5144 break;
5145
5146 case GL_VERTEX_ATTRIB_BINDING:
5147 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5148 if (context->getClientVersion() < ES_3_1)
5149 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005150 context->handleError(InvalidEnum()
5151 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005152 return false;
5153 }
5154 break;
5155
5156 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005157 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005158 return false;
5159 }
5160 }
5161
5162 if (length)
5163 {
5164 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5165 {
5166 *length = 4;
5167 }
5168 else
5169 {
5170 *length = 1;
5171 }
5172 }
5173
5174 return true;
5175}
5176
Jamie Madill4928b7c2017-06-20 12:57:39 -04005177bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005178 GLint x,
5179 GLint y,
5180 GLsizei width,
5181 GLsizei height,
5182 GLenum format,
5183 GLenum type,
5184 GLsizei bufSize,
5185 GLsizei *length,
5186 GLsizei *columns,
5187 GLsizei *rows,
5188 void *pixels)
5189{
5190 if (length != nullptr)
5191 {
5192 *length = 0;
5193 }
5194 if (rows != nullptr)
5195 {
5196 *rows = 0;
5197 }
5198 if (columns != nullptr)
5199 {
5200 *columns = 0;
5201 }
5202
5203 if (width < 0 || height < 0)
5204 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005205 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005206 return false;
5207 }
5208
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005209 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005210
Jamie Madille98b1b52018-03-08 09:47:23 -05005211 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madillbe849e42017-05-02 15:49:00 -04005212 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005213 return false;
5214 }
5215
Jamie Madille98b1b52018-03-08 09:47:23 -05005216 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005217 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005218 return false;
5219 }
5220
Jamie Madill690c8eb2018-03-12 15:20:03 -04005221 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005222 ASSERT(framebuffer);
5223
5224 if (framebuffer->getReadBufferState() == GL_NONE)
5225 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005226 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005227 return false;
5228 }
5229
5230 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5231 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5232 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5233 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5234 // situation is an application error that would lead to a crash in ANGLE.
5235 if (readBuffer == nullptr)
5236 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005237 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005238 return false;
5239 }
5240
Martin Radev28031682017-07-28 14:47:56 +03005241 // ANGLE_multiview, Revision 1:
5242 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5243 // current read framebuffer is not NONE.
5244 if (readBuffer->getMultiviewLayout() != GL_NONE)
5245 {
5246 context->handleError(InvalidFramebufferOperation()
5247 << "Attempting to read from a multi-view framebuffer.");
5248 return false;
5249 }
5250
Geoff Lang280ba992017-04-18 16:30:58 -04005251 if (context->getExtensions().webglCompatibility)
5252 {
5253 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5254 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5255 // and type before validating the combination of format and type. However, the
5256 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5257 // verifies that GL_INVALID_OPERATION is generated.
5258 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5259 // dEQP/WebGL.
5260 if (!ValidReadPixelsFormatEnum(context, format))
5261 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005262 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005263 return false;
5264 }
5265
5266 if (!ValidReadPixelsTypeEnum(context, type))
5267 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005268 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005269 return false;
5270 }
5271 }
5272
Jamie Madill690c8eb2018-03-12 15:20:03 -04005273 GLenum currentFormat = GL_NONE;
5274 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5275
5276 GLenum currentType = GL_NONE;
5277 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5278
Jamie Madillbe849e42017-05-02 15:49:00 -04005279 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5280
5281 bool validFormatTypeCombination =
5282 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5283
5284 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5285 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005286 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005287 return false;
5288 }
5289
5290 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005291 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005292 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5293 {
5294 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005295 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005296 return false;
5297 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005298 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5299 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5300 {
5301 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5302 return false;
5303 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005304
5305 // .. the data would be packed to the buffer object such that the memory writes required
5306 // would exceed the data store size.
5307 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5308 const gl::Extents size(width, height, 1);
5309 const auto &pack = context->getGLState().getPackState();
5310
5311 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5312 if (endByteOrErr.isError())
5313 {
5314 context->handleError(endByteOrErr.getError());
5315 return false;
5316 }
5317
5318 size_t endByte = endByteOrErr.getResult();
5319 if (bufSize >= 0)
5320 {
5321 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5322 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005323 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005324 return false;
5325 }
5326 }
5327
5328 if (pixelPackBuffer != nullptr)
5329 {
5330 CheckedNumeric<size_t> checkedEndByte(endByte);
5331 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5332 checkedEndByte += checkedOffset;
5333
5334 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5335 {
5336 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005337 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005338 return false;
5339 }
5340 }
5341
5342 if (pixelPackBuffer == nullptr && length != nullptr)
5343 {
5344 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5345 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005346 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005347 return false;
5348 }
5349
5350 *length = static_cast<GLsizei>(endByte);
5351 }
5352
Geoff Langa953b522018-02-21 16:56:23 -05005353 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005354 angle::CheckedNumeric<int> clippedExtent(length);
5355 if (start < 0)
5356 {
5357 // "subtract" the area that is less than 0
5358 clippedExtent += start;
5359 }
5360
Geoff Langa953b522018-02-21 16:56:23 -05005361 angle::CheckedNumeric<int> readExtent = start;
5362 readExtent += length;
5363 if (!readExtent.IsValid())
5364 {
5365 return false;
5366 }
5367
5368 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005369 {
5370 // Subtract the region to the right of the read buffer
5371 clippedExtent -= (readExtent - bufferSize);
5372 }
5373
5374 if (!clippedExtent.IsValid())
5375 {
Geoff Langa953b522018-02-21 16:56:23 -05005376 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005377 }
5378
Geoff Langa953b522018-02-21 16:56:23 -05005379 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5380 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005381 };
5382
Geoff Langa953b522018-02-21 16:56:23 -05005383 GLsizei writtenColumns = 0;
5384 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5385 {
5386 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5387 return false;
5388 }
5389
5390 GLsizei writtenRows = 0;
5391 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5392 {
5393 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5394 return false;
5395 }
5396
Jamie Madillbe849e42017-05-02 15:49:00 -04005397 if (columns != nullptr)
5398 {
Geoff Langa953b522018-02-21 16:56:23 -05005399 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005400 }
5401
5402 if (rows != nullptr)
5403 {
Geoff Langa953b522018-02-21 16:56:23 -05005404 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005405 }
5406
5407 return true;
5408}
5409
5410template <typename ParamType>
5411bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005412 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005413 GLenum pname,
5414 GLsizei bufSize,
5415 const ParamType *params)
5416{
5417 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5418 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005419 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005420 return false;
5421 }
5422
5423 if (context->getTargetTexture(target) == nullptr)
5424 {
5425 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005426 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005427 return false;
5428 }
5429
5430 const GLsizei minBufSize = 1;
5431 if (bufSize >= 0 && bufSize < minBufSize)
5432 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005433 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005434 return false;
5435 }
5436
5437 switch (pname)
5438 {
5439 case GL_TEXTURE_WRAP_R:
5440 case GL_TEXTURE_SWIZZLE_R:
5441 case GL_TEXTURE_SWIZZLE_G:
5442 case GL_TEXTURE_SWIZZLE_B:
5443 case GL_TEXTURE_SWIZZLE_A:
5444 case GL_TEXTURE_BASE_LEVEL:
5445 case GL_TEXTURE_MAX_LEVEL:
5446 case GL_TEXTURE_COMPARE_MODE:
5447 case GL_TEXTURE_COMPARE_FUNC:
5448 case GL_TEXTURE_MIN_LOD:
5449 case GL_TEXTURE_MAX_LOD:
5450 if (context->getClientMajorVersion() < 3)
5451 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005452 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005453 return false;
5454 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005455 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005456 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005457 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5458 "available without "
5459 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005460 return false;
5461 }
5462 break;
5463
5464 default:
5465 break;
5466 }
5467
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005468 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005469 {
5470 switch (pname)
5471 {
5472 case GL_TEXTURE_MIN_FILTER:
5473 case GL_TEXTURE_MAG_FILTER:
5474 case GL_TEXTURE_WRAP_S:
5475 case GL_TEXTURE_WRAP_T:
5476 case GL_TEXTURE_WRAP_R:
5477 case GL_TEXTURE_MIN_LOD:
5478 case GL_TEXTURE_MAX_LOD:
5479 case GL_TEXTURE_COMPARE_MODE:
5480 case GL_TEXTURE_COMPARE_FUNC:
5481 context->handleError(InvalidEnum()
5482 << "Invalid parameter for 2D multisampled textures.");
5483 return false;
5484 }
5485 }
5486
Jamie Madillbe849e42017-05-02 15:49:00 -04005487 switch (pname)
5488 {
5489 case GL_TEXTURE_WRAP_S:
5490 case GL_TEXTURE_WRAP_T:
5491 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005492 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005493 bool restrictedWrapModes =
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005494 target == TextureType::External || target == TextureType::Rectangle;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005495 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5496 {
5497 return false;
5498 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005499 }
5500 break;
5501
5502 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005503 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005504 bool restrictedMinFilter =
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005505 target == TextureType::External || target == TextureType::Rectangle;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005506 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5507 {
5508 return false;
5509 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005510 }
5511 break;
5512
5513 case GL_TEXTURE_MAG_FILTER:
5514 if (!ValidateTextureMagFilterValue(context, params))
5515 {
5516 return false;
5517 }
5518 break;
5519
5520 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005521 if (!context->getExtensions().textureUsage)
5522 {
5523 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5524 return false;
5525 }
5526
Jamie Madillbe849e42017-05-02 15:49:00 -04005527 switch (ConvertToGLenum(params[0]))
5528 {
5529 case GL_NONE:
5530 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5531 break;
5532
5533 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005534 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005535 return false;
5536 }
5537 break;
5538
5539 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Jamie Madillbe849e42017-05-02 15:49:00 -04005540 {
Luc Ferron1b1a8642018-01-23 15:12:01 -05005541 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5542 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5543 {
5544 return false;
5545 }
5546 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
Jamie Madillbe849e42017-05-02 15:49:00 -04005547 }
5548 break;
5549
5550 case GL_TEXTURE_MIN_LOD:
5551 case GL_TEXTURE_MAX_LOD:
5552 // any value is permissible
5553 break;
5554
5555 case GL_TEXTURE_COMPARE_MODE:
5556 if (!ValidateTextureCompareModeValue(context, params))
5557 {
5558 return false;
5559 }
5560 break;
5561
5562 case GL_TEXTURE_COMPARE_FUNC:
5563 if (!ValidateTextureCompareFuncValue(context, params))
5564 {
5565 return false;
5566 }
5567 break;
5568
5569 case GL_TEXTURE_SWIZZLE_R:
5570 case GL_TEXTURE_SWIZZLE_G:
5571 case GL_TEXTURE_SWIZZLE_B:
5572 case GL_TEXTURE_SWIZZLE_A:
5573 switch (ConvertToGLenum(params[0]))
5574 {
5575 case GL_RED:
5576 case GL_GREEN:
5577 case GL_BLUE:
5578 case GL_ALPHA:
5579 case GL_ZERO:
5580 case GL_ONE:
5581 break;
5582
5583 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005584 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005585 return false;
5586 }
5587 break;
5588
5589 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005590 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005591 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005592 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005593 return false;
5594 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005595 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005596 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005597 context->handleError(InvalidOperation()
5598 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005599 return false;
5600 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005601 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005602 {
5603 context->handleError(InvalidOperation()
5604 << "Base level must be 0 for multisampled textures.");
5605 return false;
5606 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005607 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005608 {
5609 context->handleError(InvalidOperation()
5610 << "Base level must be 0 for rectangle textures.");
5611 return false;
5612 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005613 break;
5614
5615 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005616 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005617 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005618 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005619 return false;
5620 }
5621 break;
5622
5623 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5624 if (context->getClientVersion() < Version(3, 1))
5625 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005626 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005627 return false;
5628 }
5629 switch (ConvertToGLenum(params[0]))
5630 {
5631 case GL_DEPTH_COMPONENT:
5632 case GL_STENCIL_INDEX:
5633 break;
5634
5635 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005636 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005637 return false;
5638 }
5639 break;
5640
5641 case GL_TEXTURE_SRGB_DECODE_EXT:
5642 if (!ValidateTextureSRGBDecodeValue(context, params))
5643 {
5644 return false;
5645 }
5646 break;
5647
5648 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005649 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005650 return false;
5651 }
5652
5653 return true;
5654}
5655
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005656template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
5657template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04005658
Jamie Madill5b772312018-03-08 20:28:32 -05005659bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04005660{
5661 if (index >= MAX_VERTEX_ATTRIBS)
5662 {
5663 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5664 return false;
5665 }
5666
5667 return true;
5668}
5669
5670bool ValidateGetActiveUniformBlockivBase(Context *context,
5671 GLuint program,
5672 GLuint uniformBlockIndex,
5673 GLenum pname,
5674 GLsizei *length)
5675{
5676 if (length)
5677 {
5678 *length = 0;
5679 }
5680
5681 if (context->getClientMajorVersion() < 3)
5682 {
5683 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5684 return false;
5685 }
5686
5687 Program *programObject = GetValidProgram(context, program);
5688 if (!programObject)
5689 {
5690 return false;
5691 }
5692
5693 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5694 {
5695 context->handleError(InvalidValue()
5696 << "uniformBlockIndex exceeds active uniform block count.");
5697 return false;
5698 }
5699
5700 switch (pname)
5701 {
5702 case GL_UNIFORM_BLOCK_BINDING:
5703 case GL_UNIFORM_BLOCK_DATA_SIZE:
5704 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5705 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5706 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5707 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5708 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5709 break;
5710
5711 default:
5712 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5713 return false;
5714 }
5715
5716 if (length)
5717 {
5718 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5719 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005720 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005721 programObject->getUniformBlockByIndex(uniformBlockIndex);
5722 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5723 }
5724 else
5725 {
5726 *length = 1;
5727 }
5728 }
5729
5730 return true;
5731}
5732
Jamie Madill9696d072017-08-26 23:19:57 -04005733template <typename ParamType>
5734bool ValidateSamplerParameterBase(Context *context,
5735 GLuint sampler,
5736 GLenum pname,
5737 GLsizei bufSize,
5738 ParamType *params)
5739{
5740 if (context->getClientMajorVersion() < 3)
5741 {
5742 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5743 return false;
5744 }
5745
5746 if (!context->isSampler(sampler))
5747 {
5748 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5749 return false;
5750 }
5751
5752 const GLsizei minBufSize = 1;
5753 if (bufSize >= 0 && bufSize < minBufSize)
5754 {
5755 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5756 return false;
5757 }
5758
5759 switch (pname)
5760 {
5761 case GL_TEXTURE_WRAP_S:
5762 case GL_TEXTURE_WRAP_T:
5763 case GL_TEXTURE_WRAP_R:
5764 if (!ValidateTextureWrapModeValue(context, params, false))
5765 {
5766 return false;
5767 }
5768 break;
5769
5770 case GL_TEXTURE_MIN_FILTER:
5771 if (!ValidateTextureMinFilterValue(context, params, false))
5772 {
5773 return false;
5774 }
5775 break;
5776
5777 case GL_TEXTURE_MAG_FILTER:
5778 if (!ValidateTextureMagFilterValue(context, params))
5779 {
5780 return false;
5781 }
5782 break;
5783
5784 case GL_TEXTURE_MIN_LOD:
5785 case GL_TEXTURE_MAX_LOD:
5786 // any value is permissible
5787 break;
5788
5789 case GL_TEXTURE_COMPARE_MODE:
5790 if (!ValidateTextureCompareModeValue(context, params))
5791 {
5792 return false;
5793 }
5794 break;
5795
5796 case GL_TEXTURE_COMPARE_FUNC:
5797 if (!ValidateTextureCompareFuncValue(context, params))
5798 {
5799 return false;
5800 }
5801 break;
5802
5803 case GL_TEXTURE_SRGB_DECODE_EXT:
5804 if (!ValidateTextureSRGBDecodeValue(context, params))
5805 {
5806 return false;
5807 }
5808 break;
5809
Luc Ferron1b1a8642018-01-23 15:12:01 -05005810 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5811 {
5812 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5813 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5814 {
5815 return false;
5816 }
5817 }
5818 break;
5819
Jamie Madill9696d072017-08-26 23:19:57 -04005820 default:
5821 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5822 return false;
5823 }
5824
5825 return true;
5826}
5827
5828template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5829template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5830
5831bool ValidateGetSamplerParameterBase(Context *context,
5832 GLuint sampler,
5833 GLenum pname,
5834 GLsizei *length)
5835{
5836 if (length)
5837 {
5838 *length = 0;
5839 }
5840
5841 if (context->getClientMajorVersion() < 3)
5842 {
5843 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5844 return false;
5845 }
5846
5847 if (!context->isSampler(sampler))
5848 {
5849 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5850 return false;
5851 }
5852
5853 switch (pname)
5854 {
5855 case GL_TEXTURE_WRAP_S:
5856 case GL_TEXTURE_WRAP_T:
5857 case GL_TEXTURE_WRAP_R:
5858 case GL_TEXTURE_MIN_FILTER:
5859 case GL_TEXTURE_MAG_FILTER:
5860 case GL_TEXTURE_MIN_LOD:
5861 case GL_TEXTURE_MAX_LOD:
5862 case GL_TEXTURE_COMPARE_MODE:
5863 case GL_TEXTURE_COMPARE_FUNC:
5864 break;
5865
Luc Ferron1b1a8642018-01-23 15:12:01 -05005866 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5867 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
5868 {
5869 return false;
5870 }
5871 break;
5872
Jamie Madill9696d072017-08-26 23:19:57 -04005873 case GL_TEXTURE_SRGB_DECODE_EXT:
5874 if (!context->getExtensions().textureSRGBDecode)
5875 {
5876 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5877 return false;
5878 }
5879 break;
5880
5881 default:
5882 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5883 return false;
5884 }
5885
5886 if (length)
5887 {
5888 *length = 1;
5889 }
5890 return true;
5891}
5892
5893bool ValidateGetInternalFormativBase(Context *context,
5894 GLenum target,
5895 GLenum internalformat,
5896 GLenum pname,
5897 GLsizei bufSize,
5898 GLsizei *numParams)
5899{
5900 if (numParams)
5901 {
5902 *numParams = 0;
5903 }
5904
5905 if (context->getClientMajorVersion() < 3)
5906 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005907 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005908 return false;
5909 }
5910
5911 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5912 if (!formatCaps.renderable)
5913 {
5914 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5915 return false;
5916 }
5917
5918 switch (target)
5919 {
5920 case GL_RENDERBUFFER:
5921 break;
5922
5923 case GL_TEXTURE_2D_MULTISAMPLE:
5924 if (context->getClientVersion() < ES_3_1)
5925 {
5926 context->handleError(InvalidOperation()
5927 << "Texture target requires at least OpenGL ES 3.1.");
5928 return false;
5929 }
5930 break;
5931
5932 default:
5933 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5934 return false;
5935 }
5936
5937 if (bufSize < 0)
5938 {
5939 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5940 return false;
5941 }
5942
5943 GLsizei maxWriteParams = 0;
5944 switch (pname)
5945 {
5946 case GL_NUM_SAMPLE_COUNTS:
5947 maxWriteParams = 1;
5948 break;
5949
5950 case GL_SAMPLES:
5951 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5952 break;
5953
5954 default:
5955 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5956 return false;
5957 }
5958
5959 if (numParams)
5960 {
5961 // glGetInternalFormativ will not overflow bufSize
5962 *numParams = std::min(bufSize, maxWriteParams);
5963 }
5964
5965 return true;
5966}
5967
Jamie Madille98b1b52018-03-08 09:47:23 -05005968// We should check with Khronos if returning INVALID_FRAMEBUFFER_OPERATION is OK when querying
5969// implementation format info for incomplete framebuffers. It seems like these queries are
5970// incongruent with the other errors.
5971bool ValidateFramebufferComplete(Context *context, Framebuffer *framebuffer, bool isFramebufferOp)
5972{
5973 bool complete = false;
5974 ANGLE_VALIDATION_TRY(framebuffer->isComplete(context, &complete));
5975 if (!complete)
5976 {
5977 if (isFramebufferOp)
5978 {
5979 context->handleError(InvalidFramebufferOperation());
5980 }
5981 else
5982 {
5983 context->handleError(InvalidOperation());
5984 }
5985 return false;
5986 }
5987 return true;
5988}
5989
5990bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
5991{
5992 GLint samples = 0;
5993 ANGLE_VALIDATION_TRY(framebuffer->getSamples(context, &samples));
5994 if (samples != 0)
5995 {
5996 context->handleError(InvalidOperation());
5997 return false;
5998 }
5999 return true;
6000}
6001
Jamie Madillc29968b2016-01-20 11:17:23 -05006002} // namespace gl