blob: e7f1e9a3cec6ca9195c819cc462fa801080b22e4 [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.
Jamie Madill6f5444d2018-03-14 10:08:11 -04002947 const DrawCallParams &params = context->getParams<DrawCallParams>();
2948 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
2949 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002950
2951 // If we use an index greater than our maximum supported index range, return an error.
2952 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2953 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04002954 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002955 {
2956 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2957 return false;
2958 }
2959
Jamie Madill6f5444d2018-03-14 10:08:11 -04002960 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end),
2961 static_cast<GLint>(indexRange.vertexCount())))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002962 {
2963 return false;
2964 }
2965
2966 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04002967 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002968 }
2969
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002970 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002971}
2972
Jamie Madill5b772312018-03-08 20:28:32 -05002973bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002974 GLenum mode,
2975 GLsizei count,
2976 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002977 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002978 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002979{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002980 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002981}
2982
Geoff Lang3edfe032015-09-04 16:38:24 -04002983bool ValidateDrawElementsInstancedANGLE(Context *context,
2984 GLenum mode,
2985 GLsizei count,
2986 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002987 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002988 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002989{
Geoff Lang63c5a592017-09-27 14:08:16 -04002990 if (!context->getExtensions().instancedArrays)
2991 {
2992 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2993 return false;
2994 }
2995
Corentin Wallez170efbf2017-05-02 13:45:01 -04002996 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002997 {
2998 return false;
2999 }
3000
Corentin Wallez0dc97812017-06-22 14:38:44 -04003001 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003002}
3003
He Yunchaoced53ae2016-11-29 15:00:51 +08003004bool ValidateFramebufferTextureBase(Context *context,
3005 GLenum target,
3006 GLenum attachment,
3007 GLuint texture,
3008 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003009{
Geoff Lange8afa902017-09-27 15:00:43 -04003010 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003011 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003012 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003013 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003014 }
3015
3016 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003017 {
3018 return false;
3019 }
3020
Jamie Madill55ec3b12014-07-03 10:38:57 -04003021 if (texture != 0)
3022 {
3023 gl::Texture *tex = context->getTexture(texture);
3024
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003025 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003026 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003027 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003028 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003029 }
3030
3031 if (level < 0)
3032 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003033 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003034 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003035 }
3036 }
3037
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003038 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003039 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003040
Jamie Madill84115c92015-04-23 15:00:07 -04003041 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003042 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003043 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003044 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003045 }
3046
3047 return true;
3048}
3049
Geoff Langb1196682014-07-23 13:47:29 -04003050bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003051{
3052 if (program == 0)
3053 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003054 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003055 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003056 }
3057
Dian Xiang769769a2015-09-09 15:20:08 -07003058 gl::Program *programObject = GetValidProgram(context, program);
3059 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003060 {
3061 return false;
3062 }
3063
Jamie Madill0063c512014-08-25 15:47:53 -04003064 if (!programObject || !programObject->isLinked())
3065 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003066 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003067 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003068 }
3069
Geoff Lang7dd2e102014-11-10 15:19:26 -05003070 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003071 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003072 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003073 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003074 }
3075
Jamie Madill0063c512014-08-25 15:47:53 -04003076 return true;
3077}
3078
Geoff Langf41d0ee2016-10-07 13:04:23 -04003079static bool ValidateSizedGetUniform(Context *context,
3080 GLuint program,
3081 GLint location,
3082 GLsizei bufSize,
3083 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003084{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003085 if (length)
3086 {
3087 *length = 0;
3088 }
3089
Jamie Madill78f41802014-08-25 15:47:55 -04003090 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003091 {
Jamie Madill78f41802014-08-25 15:47:55 -04003092 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003093 }
3094
Geoff Langf41d0ee2016-10-07 13:04:23 -04003095 if (bufSize < 0)
3096 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003097 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003098 return false;
3099 }
3100
Jamie Madilla502c742014-08-28 17:19:13 -04003101 gl::Program *programObject = context->getProgram(program);
3102 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003103
Jamie Madill78f41802014-08-25 15:47:55 -04003104 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003105 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003106 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003107 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003108 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003109 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003110 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003111 }
3112
Geoff Langf41d0ee2016-10-07 13:04:23 -04003113 if (length)
3114 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003115 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003116 }
3117
Jamie Madill0063c512014-08-25 15:47:53 -04003118 return true;
3119}
3120
He Yunchaoced53ae2016-11-29 15:00:51 +08003121bool ValidateGetnUniformfvEXT(Context *context,
3122 GLuint program,
3123 GLint location,
3124 GLsizei bufSize,
3125 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003126{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003127 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003128}
3129
He Yunchaoced53ae2016-11-29 15:00:51 +08003130bool ValidateGetnUniformivEXT(Context *context,
3131 GLuint program,
3132 GLint location,
3133 GLsizei bufSize,
3134 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003135{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003136 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3137}
3138
3139bool ValidateGetUniformfvRobustANGLE(Context *context,
3140 GLuint program,
3141 GLint location,
3142 GLsizei bufSize,
3143 GLsizei *length,
3144 GLfloat *params)
3145{
3146 if (!ValidateRobustEntryPoint(context, bufSize))
3147 {
3148 return false;
3149 }
3150
3151 // bufSize is validated in ValidateSizedGetUniform
3152 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3153}
3154
3155bool ValidateGetUniformivRobustANGLE(Context *context,
3156 GLuint program,
3157 GLint location,
3158 GLsizei bufSize,
3159 GLsizei *length,
3160 GLint *params)
3161{
3162 if (!ValidateRobustEntryPoint(context, bufSize))
3163 {
3164 return false;
3165 }
3166
3167 // bufSize is validated in ValidateSizedGetUniform
3168 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3169}
3170
3171bool ValidateGetUniformuivRobustANGLE(Context *context,
3172 GLuint program,
3173 GLint location,
3174 GLsizei bufSize,
3175 GLsizei *length,
3176 GLuint *params)
3177{
3178 if (!ValidateRobustEntryPoint(context, bufSize))
3179 {
3180 return false;
3181 }
3182
3183 if (context->getClientMajorVersion() < 3)
3184 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003185 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003186 return false;
3187 }
3188
3189 // bufSize is validated in ValidateSizedGetUniform
3190 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003191}
3192
He Yunchaoced53ae2016-11-29 15:00:51 +08003193bool ValidateDiscardFramebufferBase(Context *context,
3194 GLenum target,
3195 GLsizei numAttachments,
3196 const GLenum *attachments,
3197 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003198{
3199 if (numAttachments < 0)
3200 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003201 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003202 return false;
3203 }
3204
3205 for (GLsizei i = 0; i < numAttachments; ++i)
3206 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003207 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003208 {
3209 if (defaultFramebuffer)
3210 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003211 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003212 return false;
3213 }
3214
3215 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3216 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003217 context->handleError(InvalidOperation() << "Requested color attachment is "
3218 "greater than the maximum supported "
3219 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003220 return false;
3221 }
3222 }
3223 else
3224 {
3225 switch (attachments[i])
3226 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003227 case GL_DEPTH_ATTACHMENT:
3228 case GL_STENCIL_ATTACHMENT:
3229 case GL_DEPTH_STENCIL_ATTACHMENT:
3230 if (defaultFramebuffer)
3231 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003232 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3233 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003234 return false;
3235 }
3236 break;
3237 case GL_COLOR:
3238 case GL_DEPTH:
3239 case GL_STENCIL:
3240 if (!defaultFramebuffer)
3241 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003242 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3243 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003244 return false;
3245 }
3246 break;
3247 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003248 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003249 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003250 }
3251 }
3252 }
3253
3254 return true;
3255}
3256
Austin Kinross6ee1e782015-05-29 17:05:37 -07003257bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3258{
Jamie Madill007530e2017-12-28 14:27:04 -05003259 if (!context->getExtensions().debugMarker)
3260 {
3261 // The debug marker calls should not set error state
3262 // However, it seems reasonable to set an error state if the extension is not enabled
3263 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3264 return false;
3265 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003266
Jamie Madill007530e2017-12-28 14:27:04 -05003267 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003268 if (length < 0)
3269 {
3270 return false;
3271 }
3272
3273 if (marker == nullptr)
3274 {
3275 return false;
3276 }
3277
3278 return true;
3279}
3280
3281bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3282{
Jamie Madill007530e2017-12-28 14:27:04 -05003283 if (!context->getExtensions().debugMarker)
3284 {
3285 // The debug marker calls should not set error state
3286 // However, it seems reasonable to set an error state if the extension is not enabled
3287 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3288 return false;
3289 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003290
Jamie Madill007530e2017-12-28 14:27:04 -05003291 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003292 if (length < 0)
3293 {
3294 return false;
3295 }
3296
3297 if (length > 0 && marker == nullptr)
3298 {
3299 return false;
3300 }
3301
3302 return true;
3303}
3304
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003305bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003306{
Geoff Langa8406172015-07-21 16:53:39 -04003307 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3308 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003309 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003310 return false;
3311 }
3312
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003313 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003314 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003315 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003316 if (!context->getExtensions().eglImage)
3317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003318 context->handleError(InvalidEnum()
3319 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003320 }
3321 break;
3322
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003323 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003324 if (!context->getExtensions().eglImageExternal)
3325 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003326 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3327 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003328 }
Geoff Langa8406172015-07-21 16:53:39 -04003329 break;
3330
3331 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003332 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003333 return false;
3334 }
3335
Jamie Madill007530e2017-12-28 14:27:04 -05003336 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3337
Jamie Madill61e16b42017-06-19 11:13:23 -04003338 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003339 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003340 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003341 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003342 return false;
3343 }
3344
Jamie Madill007530e2017-12-28 14:27:04 -05003345 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003346 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003347 context->handleError(InvalidOperation()
3348 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003349 return false;
3350 }
3351
Geoff Langca271392017-04-05 12:30:00 -04003352 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003353 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003354 if (!textureCaps.texturable)
3355 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003356 context->handleError(InvalidOperation()
3357 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003358 return false;
3359 }
3360
Geoff Langdcab33b2015-07-21 13:03:16 -04003361 return true;
3362}
3363
3364bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003365 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003366 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003367{
Geoff Langa8406172015-07-21 16:53:39 -04003368 if (!context->getExtensions().eglImage)
3369 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003370 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003371 return false;
3372 }
3373
3374 switch (target)
3375 {
3376 case GL_RENDERBUFFER:
3377 break;
3378
3379 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003380 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003381 return false;
3382 }
3383
Jamie Madill007530e2017-12-28 14:27:04 -05003384 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3385
Jamie Madill61e16b42017-06-19 11:13:23 -04003386 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003387 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003388 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003389 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003390 return false;
3391 }
3392
Geoff Langca271392017-04-05 12:30:00 -04003393 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003394 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003395 if (!textureCaps.renderable)
3396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003397 context->handleError(InvalidOperation()
3398 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003399 return false;
3400 }
3401
Geoff Langdcab33b2015-07-21 13:03:16 -04003402 return true;
3403}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003404
3405bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3406{
Geoff Lang36167ab2015-12-07 10:27:14 -05003407 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003408 {
3409 // The default VAO should always exist
3410 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003411 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003412 return false;
3413 }
3414
3415 return true;
3416}
3417
Geoff Langc5629752015-12-07 16:29:04 -05003418bool ValidateProgramBinaryBase(Context *context,
3419 GLuint program,
3420 GLenum binaryFormat,
3421 const void *binary,
3422 GLint length)
3423{
3424 Program *programObject = GetValidProgram(context, program);
3425 if (programObject == nullptr)
3426 {
3427 return false;
3428 }
3429
3430 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3431 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3432 programBinaryFormats.end())
3433 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003434 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003435 return false;
3436 }
3437
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003438 if (context->hasActiveTransformFeedback(program))
3439 {
3440 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003441 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3442 "is associated with an active transform "
3443 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003444 return false;
3445 }
3446
Geoff Langc5629752015-12-07 16:29:04 -05003447 return true;
3448}
3449
3450bool ValidateGetProgramBinaryBase(Context *context,
3451 GLuint program,
3452 GLsizei bufSize,
3453 GLsizei *length,
3454 GLenum *binaryFormat,
3455 void *binary)
3456{
3457 Program *programObject = GetValidProgram(context, program);
3458 if (programObject == nullptr)
3459 {
3460 return false;
3461 }
3462
3463 if (!programObject->isLinked())
3464 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003465 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003466 return false;
3467 }
3468
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003469 if (context->getCaps().programBinaryFormats.empty())
3470 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003471 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003472 return false;
3473 }
3474
Geoff Langc5629752015-12-07 16:29:04 -05003475 return true;
3476}
Jamie Madillc29968b2016-01-20 11:17:23 -05003477
Jamie Madill5b772312018-03-08 20:28:32 -05003478bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003479{
3480 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003481 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003482 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003483 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3484 return false;
3485 }
3486 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3487 {
3488 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003489 return false;
3490 }
3491
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003492 ASSERT(context->getGLState().getDrawFramebuffer());
3493 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003494 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3495
3496 // This should come first before the check for the default frame buffer
3497 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3498 // rather than INVALID_OPERATION
3499 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3500 {
3501 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3502
3503 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003504 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3505 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003506 {
3507 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003508 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3509 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3510 // 3.1 is still a bit ambiguous about the error, but future specs are
3511 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003512 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003513 return false;
3514 }
3515 else if (bufs[colorAttachment] >= maxColorAttachment)
3516 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003517 context->handleError(InvalidOperation()
3518 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003519 return false;
3520 }
3521 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3522 frameBufferId != 0)
3523 {
3524 // INVALID_OPERATION-GL is bound to buffer and ith argument
3525 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003526 context->handleError(InvalidOperation()
3527 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003528 return false;
3529 }
3530 }
3531
3532 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3533 // and n is not 1 or bufs is bound to value other than BACK and NONE
3534 if (frameBufferId == 0)
3535 {
3536 if (n != 1)
3537 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003538 context->handleError(InvalidOperation()
3539 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003540 return false;
3541 }
3542
3543 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3544 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003545 context->handleError(
3546 InvalidOperation()
3547 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003548 return false;
3549 }
3550 }
3551
3552 return true;
3553}
3554
Geoff Lang496c02d2016-10-20 11:38:11 -07003555bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003556 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003557 GLenum pname,
3558 GLsizei *length,
3559 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003560{
Geoff Lang496c02d2016-10-20 11:38:11 -07003561 if (length)
3562 {
3563 *length = 0;
3564 }
3565
3566 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3567 {
3568 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003569 InvalidOperation()
3570 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003571 return false;
3572 }
3573
Corentin Walleze4477002017-12-01 14:39:58 -05003574 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003575 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003576 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003577 return false;
3578 }
3579
Geoff Lang496c02d2016-10-20 11:38:11 -07003580 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003581 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003582 case GL_BUFFER_MAP_POINTER:
3583 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003584
Geoff Lang496c02d2016-10-20 11:38:11 -07003585 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003586 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003587 return false;
3588 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003589
3590 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3591 // target bound to zero generate an INVALID_OPERATION error."
3592 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003593 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003594 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003595 context->handleError(InvalidOperation()
3596 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003597 return false;
3598 }
3599
Geoff Lang496c02d2016-10-20 11:38:11 -07003600 if (length)
3601 {
3602 *length = 1;
3603 }
3604
Olli Etuaho4f667482016-03-30 15:56:35 +03003605 return true;
3606}
3607
Corentin Wallez336129f2017-10-17 15:55:40 -04003608bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003609{
Corentin Walleze4477002017-12-01 14:39:58 -05003610 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003611 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003612 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003613 return false;
3614 }
3615
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003616 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003617
3618 if (buffer == nullptr || !buffer->isMapped())
3619 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003620 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003621 return false;
3622 }
3623
3624 return true;
3625}
3626
3627bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003628 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003629 GLintptr offset,
3630 GLsizeiptr length,
3631 GLbitfield access)
3632{
Corentin Walleze4477002017-12-01 14:39:58 -05003633 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003634 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003635 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003636 return false;
3637 }
3638
Brandon Jones6cad5662017-06-14 13:25:13 -07003639 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003640 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003641 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3642 return false;
3643 }
3644
3645 if (length < 0)
3646 {
3647 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003648 return false;
3649 }
3650
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003651 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003652
3653 if (!buffer)
3654 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003655 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003656 return false;
3657 }
3658
3659 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003660 CheckedNumeric<size_t> checkedOffset(offset);
3661 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003662
Jamie Madille2e406c2016-06-02 13:04:10 -04003663 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003664 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003665 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003666 return false;
3667 }
3668
3669 // Check for invalid bits in the mask
3670 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3671 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3672 GL_MAP_UNSYNCHRONIZED_BIT;
3673
3674 if (access & ~(allAccessBits))
3675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003676 context->handleError(InvalidValue()
3677 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003678 return false;
3679 }
3680
3681 if (length == 0)
3682 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003683 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003684 return false;
3685 }
3686
3687 if (buffer->isMapped())
3688 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003689 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003690 return false;
3691 }
3692
3693 // Check for invalid bit combinations
3694 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3695 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003696 context->handleError(InvalidOperation()
3697 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003698 return false;
3699 }
3700
3701 GLbitfield writeOnlyBits =
3702 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3703
3704 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3705 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003706 context->handleError(InvalidOperation()
3707 << "Invalid access bits when mapping buffer for reading: 0x"
3708 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003709 return false;
3710 }
3711
3712 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3713 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003714 context->handleError(
3715 InvalidOperation()
3716 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003717 return false;
3718 }
Geoff Lang79f71042017-08-14 16:43:43 -04003719
3720 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003721}
3722
3723bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003724 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003725 GLintptr offset,
3726 GLsizeiptr length)
3727{
Brandon Jones6cad5662017-06-14 13:25:13 -07003728 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003729 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003730 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3731 return false;
3732 }
3733
3734 if (length < 0)
3735 {
3736 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003737 return false;
3738 }
3739
Corentin Walleze4477002017-12-01 14:39:58 -05003740 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003741 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003742 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003743 return false;
3744 }
3745
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003746 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003747
3748 if (buffer == nullptr)
3749 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003750 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003751 return false;
3752 }
3753
3754 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3755 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003756 context->handleError(InvalidOperation()
3757 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003758 return false;
3759 }
3760
3761 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003762 CheckedNumeric<size_t> checkedOffset(offset);
3763 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003764
Jamie Madille2e406c2016-06-02 13:04:10 -04003765 if (!checkedSize.IsValid() ||
3766 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003767 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003768 context->handleError(InvalidValue()
3769 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003770 return false;
3771 }
3772
3773 return true;
3774}
3775
Olli Etuaho41997e72016-03-10 13:38:39 +02003776bool ValidateGenOrDelete(Context *context, GLint n)
3777{
3778 if (n < 0)
3779 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003780 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003781 return false;
3782 }
3783 return true;
3784}
3785
Jamie Madill5b772312018-03-08 20:28:32 -05003786bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003787{
3788 if (!context->getExtensions().robustClientMemory)
3789 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003790 context->handleError(InvalidOperation()
3791 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003792 return false;
3793 }
3794
3795 if (bufSize < 0)
3796 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003797 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003798 return false;
3799 }
3800
3801 return true;
3802}
3803
Jamie Madill5b772312018-03-08 20:28:32 -05003804bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003805{
3806 if (bufSize < numParams)
3807 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003808 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3809 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003810 return false;
3811 }
3812
3813 return true;
3814}
3815
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003816bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04003817 GLenum target,
3818 GLenum attachment,
3819 GLenum pname,
3820 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003821{
Geoff Lange8afa902017-09-27 15:00:43 -04003822 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003823 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003824 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003825 return false;
3826 }
3827
3828 int clientVersion = context->getClientMajorVersion();
3829
3830 switch (pname)
3831 {
3832 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3833 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3834 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3835 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3836 break;
3837
Martin Radeve5285d22017-07-14 16:23:53 +03003838 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3839 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3840 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3841 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3842 if (clientVersion < 3 || !context->getExtensions().multiview)
3843 {
3844 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3845 return false;
3846 }
3847 break;
3848
Geoff Langff5b2d52016-09-07 11:32:23 -04003849 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3850 if (clientVersion < 3 && !context->getExtensions().sRGB)
3851 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003852 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003853 return false;
3854 }
3855 break;
3856
3857 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3858 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3859 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3860 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3861 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3862 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3863 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3864 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3865 if (clientVersion < 3)
3866 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003867 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003868 return false;
3869 }
3870 break;
3871
3872 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003873 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003874 return false;
3875 }
3876
3877 // Determine if the attachment is a valid enum
3878 switch (attachment)
3879 {
3880 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04003881 case GL_DEPTH:
3882 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04003883 if (clientVersion < 3)
3884 {
Geoff Langfa125c92017-10-24 13:01:46 -04003885 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003886 return false;
3887 }
3888 break;
3889
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003890 case GL_DEPTH_STENCIL_ATTACHMENT:
3891 if (clientVersion < 3 && !context->isWebGL1())
3892 {
3893 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3894 return false;
3895 }
3896 break;
3897
Geoff Langfa125c92017-10-24 13:01:46 -04003898 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003899 case GL_DEPTH_ATTACHMENT:
3900 case GL_STENCIL_ATTACHMENT:
3901 break;
3902
3903 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003904 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3905 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003906 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3907 {
Geoff Langfa125c92017-10-24 13:01:46 -04003908 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003909 return false;
3910 }
3911 break;
3912 }
3913
3914 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3915 ASSERT(framebuffer);
3916
3917 if (framebuffer->id() == 0)
3918 {
3919 if (clientVersion < 3)
3920 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003921 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003922 return false;
3923 }
3924
3925 switch (attachment)
3926 {
3927 case GL_BACK:
3928 case GL_DEPTH:
3929 case GL_STENCIL:
3930 break;
3931
3932 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003933 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003934 return false;
3935 }
3936 }
3937 else
3938 {
3939 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3940 {
3941 // Valid attachment query
3942 }
3943 else
3944 {
3945 switch (attachment)
3946 {
3947 case GL_DEPTH_ATTACHMENT:
3948 case GL_STENCIL_ATTACHMENT:
3949 break;
3950
3951 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003952 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04003953 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003954 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003955 return false;
3956 }
3957 break;
3958
3959 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003960 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003961 return false;
3962 }
3963 }
3964 }
3965
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003966 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003967 if (attachmentObject)
3968 {
3969 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3970 attachmentObject->type() == GL_TEXTURE ||
3971 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3972
3973 switch (pname)
3974 {
3975 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3976 if (attachmentObject->type() != GL_RENDERBUFFER &&
3977 attachmentObject->type() != GL_TEXTURE)
3978 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003979 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003980 return false;
3981 }
3982 break;
3983
3984 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3985 if (attachmentObject->type() != GL_TEXTURE)
3986 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003987 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003988 return false;
3989 }
3990 break;
3991
3992 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3993 if (attachmentObject->type() != GL_TEXTURE)
3994 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003995 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003996 return false;
3997 }
3998 break;
3999
4000 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4001 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4002 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004003 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004004 return false;
4005 }
4006 break;
4007
4008 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4009 if (attachmentObject->type() != GL_TEXTURE)
4010 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004011 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004012 return false;
4013 }
4014 break;
4015
4016 default:
4017 break;
4018 }
4019 }
4020 else
4021 {
4022 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4023 // is NONE, then querying any other pname will generate INVALID_ENUM.
4024
4025 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4026 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4027 // INVALID_OPERATION for all other pnames
4028
4029 switch (pname)
4030 {
4031 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4032 break;
4033
4034 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4035 if (clientVersion < 3)
4036 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004037 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004038 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004039 return false;
4040 }
4041 break;
4042
4043 default:
4044 if (clientVersion < 3)
4045 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004046 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004047 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004048 return false;
4049 }
4050 else
4051 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004052 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004053 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004054 return false;
4055 }
4056 }
4057 }
4058
Martin Radeve5285d22017-07-14 16:23:53 +03004059 if (numParams)
4060 {
4061 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4062 {
4063 // Only when the viewport offsets are queried we can have a varying number of output
4064 // parameters.
4065 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4066 *numParams = numViews * 2;
4067 }
4068 else
4069 {
4070 // For all other queries we can have only one output parameter.
4071 *numParams = 1;
4072 }
4073 }
4074
Geoff Langff5b2d52016-09-07 11:32:23 -04004075 return true;
4076}
4077
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004078bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004079 GLenum target,
4080 GLenum attachment,
4081 GLenum pname,
4082 GLsizei bufSize,
4083 GLsizei *numParams)
4084{
4085 if (!ValidateRobustEntryPoint(context, bufSize))
4086 {
4087 return false;
4088 }
4089
Jamie Madillbe849e42017-05-02 15:49:00 -04004090 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4091 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004092 {
4093 return false;
4094 }
4095
4096 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4097 {
4098 return false;
4099 }
4100
4101 return true;
4102}
4103
Jamie Madill5b772312018-03-08 20:28:32 -05004104bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004105 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004106 GLenum pname,
4107 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004108 GLsizei *length,
4109 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004110{
4111 if (!ValidateRobustEntryPoint(context, bufSize))
4112 {
4113 return false;
4114 }
4115
Geoff Langebebe1c2016-10-14 12:01:31 -04004116 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004117 {
4118 return false;
4119 }
4120
Geoff Langebebe1c2016-10-14 12:01:31 -04004121 if (!ValidateRobustBufferSize(context, bufSize, *length))
4122 {
4123 return false;
4124 }
4125
4126 return true;
4127}
4128
Jamie Madill5b772312018-03-08 20:28:32 -05004129bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004130 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004131 GLenum pname,
4132 GLsizei bufSize,
4133 GLsizei *length,
4134 GLint64 *params)
4135{
4136 if (!ValidateRobustEntryPoint(context, bufSize))
4137 {
4138 return false;
4139 }
4140
4141 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4142 {
4143 return false;
4144 }
4145
4146 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004147 {
4148 return false;
4149 }
4150
4151 return true;
4152}
4153
Jamie Madill5b772312018-03-08 20:28:32 -05004154bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004155{
4156 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004157 if (numParams)
4158 {
4159 *numParams = 1;
4160 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004161
4162 Program *programObject = GetValidProgram(context, program);
4163 if (!programObject)
4164 {
4165 return false;
4166 }
4167
4168 switch (pname)
4169 {
4170 case GL_DELETE_STATUS:
4171 case GL_LINK_STATUS:
4172 case GL_VALIDATE_STATUS:
4173 case GL_INFO_LOG_LENGTH:
4174 case GL_ATTACHED_SHADERS:
4175 case GL_ACTIVE_ATTRIBUTES:
4176 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4177 case GL_ACTIVE_UNIFORMS:
4178 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4179 break;
4180
4181 case GL_PROGRAM_BINARY_LENGTH:
4182 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4183 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004184 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4185 "requires GL_OES_get_program_binary or "
4186 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004187 return false;
4188 }
4189 break;
4190
4191 case GL_ACTIVE_UNIFORM_BLOCKS:
4192 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4193 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4194 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4195 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4196 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4197 if (context->getClientMajorVersion() < 3)
4198 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004199 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004200 return false;
4201 }
4202 break;
4203
Yunchao He61afff12017-03-14 15:34:03 +08004204 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004205 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004206 if (context->getClientVersion() < Version(3, 1))
4207 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004208 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004209 return false;
4210 }
4211 break;
4212
Jiawei Shao6ae51612018-02-23 14:03:25 +08004213 case GL_COMPUTE_WORK_GROUP_SIZE:
4214 if (context->getClientVersion() < Version(3, 1))
4215 {
4216 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4217 return false;
4218 }
4219
4220 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4221 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4222 // program which has not been linked successfully, or which does not contain objects to
4223 // form a compute shader.
4224 if (!programObject->isLinked())
4225 {
4226 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4227 return false;
4228 }
4229 if (!programObject->hasLinkedComputeShader())
4230 {
4231 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4232 return false;
4233 }
4234 break;
4235
Jiawei Shao447bfac2018-03-14 14:23:40 +08004236 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4237 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4238 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4239 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4240 if (!context->getExtensions().geometryShader)
4241 {
4242 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4243 return false;
4244 }
4245
4246 // [EXT_geometry_shader] Chapter 7.12
4247 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4248 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4249 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4250 // successfully, or which does not contain objects to form a geometry shader.
4251 if (!programObject->isLinked())
4252 {
4253 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4254 return false;
4255 }
4256 if (!programObject->hasLinkedGeometryShader())
4257 {
4258 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4259 return false;
4260 }
4261 break;
4262
Geoff Langff5b2d52016-09-07 11:32:23 -04004263 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004264 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004265 return false;
4266 }
4267
4268 return true;
4269}
4270
4271bool ValidateGetProgramivRobustANGLE(Context *context,
4272 GLuint program,
4273 GLenum pname,
4274 GLsizei bufSize,
4275 GLsizei *numParams)
4276{
4277 if (!ValidateRobustEntryPoint(context, bufSize))
4278 {
4279 return false;
4280 }
4281
Jamie Madillbe849e42017-05-02 15:49:00 -04004282 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004283 {
4284 return false;
4285 }
4286
4287 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4288 {
4289 return false;
4290 }
4291
4292 return true;
4293}
4294
Geoff Lang740d9022016-10-07 11:20:52 -04004295bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4296 GLenum target,
4297 GLenum pname,
4298 GLsizei bufSize,
4299 GLsizei *length,
4300 GLint *params)
4301{
4302 if (!ValidateRobustEntryPoint(context, bufSize))
4303 {
4304 return false;
4305 }
4306
4307 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4308 {
4309 return false;
4310 }
4311
4312 if (!ValidateRobustBufferSize(context, bufSize, *length))
4313 {
4314 return false;
4315 }
4316
4317 return true;
4318}
4319
Geoff Langd7d0ed32016-10-07 11:33:51 -04004320bool ValidateGetShaderivRobustANGLE(Context *context,
4321 GLuint shader,
4322 GLenum pname,
4323 GLsizei bufSize,
4324 GLsizei *length,
4325 GLint *params)
4326{
4327 if (!ValidateRobustEntryPoint(context, bufSize))
4328 {
4329 return false;
4330 }
4331
4332 if (!ValidateGetShaderivBase(context, shader, pname, length))
4333 {
4334 return false;
4335 }
4336
4337 if (!ValidateRobustBufferSize(context, bufSize, *length))
4338 {
4339 return false;
4340 }
4341
4342 return true;
4343}
4344
Geoff Langc1984ed2016-10-07 12:41:00 -04004345bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004346 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004347 GLenum pname,
4348 GLsizei bufSize,
4349 GLsizei *length,
4350 GLfloat *params)
4351{
4352 if (!ValidateRobustEntryPoint(context, bufSize))
4353 {
4354 return false;
4355 }
4356
4357 if (!ValidateGetTexParameterBase(context, target, pname, length))
4358 {
4359 return false;
4360 }
4361
4362 if (!ValidateRobustBufferSize(context, bufSize, *length))
4363 {
4364 return false;
4365 }
4366
4367 return true;
4368}
4369
Geoff Langc1984ed2016-10-07 12:41:00 -04004370bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004371 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004372 GLenum pname,
4373 GLsizei bufSize,
4374 GLsizei *length,
4375 GLint *params)
4376{
4377 if (!ValidateRobustEntryPoint(context, bufSize))
4378 {
4379 return false;
4380 }
4381
4382 if (!ValidateGetTexParameterBase(context, target, pname, length))
4383 {
4384 return false;
4385 }
4386
4387 if (!ValidateRobustBufferSize(context, bufSize, *length))
4388 {
4389 return false;
4390 }
4391
4392 return true;
4393}
4394
Geoff Langc1984ed2016-10-07 12:41:00 -04004395bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004396 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004397 GLenum pname,
4398 GLsizei bufSize,
4399 const GLfloat *params)
4400{
4401 if (!ValidateRobustEntryPoint(context, bufSize))
4402 {
4403 return false;
4404 }
4405
4406 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4407}
4408
Geoff Langc1984ed2016-10-07 12:41:00 -04004409bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004410 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004411 GLenum pname,
4412 GLsizei bufSize,
4413 const GLint *params)
4414{
4415 if (!ValidateRobustEntryPoint(context, bufSize))
4416 {
4417 return false;
4418 }
4419
4420 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4421}
4422
Geoff Langc1984ed2016-10-07 12:41:00 -04004423bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4424 GLuint sampler,
4425 GLenum pname,
4426 GLuint bufSize,
4427 GLsizei *length,
4428 GLfloat *params)
4429{
4430 if (!ValidateRobustEntryPoint(context, bufSize))
4431 {
4432 return false;
4433 }
4434
4435 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4436 {
4437 return false;
4438 }
4439
4440 if (!ValidateRobustBufferSize(context, bufSize, *length))
4441 {
4442 return false;
4443 }
4444
4445 return true;
4446}
4447
Geoff Langc1984ed2016-10-07 12:41:00 -04004448bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4449 GLuint sampler,
4450 GLenum pname,
4451 GLuint bufSize,
4452 GLsizei *length,
4453 GLint *params)
4454{
4455 if (!ValidateRobustEntryPoint(context, bufSize))
4456 {
4457 return false;
4458 }
4459
4460 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4461 {
4462 return false;
4463 }
4464
4465 if (!ValidateRobustBufferSize(context, bufSize, *length))
4466 {
4467 return false;
4468 }
4469
4470 return true;
4471}
4472
Geoff Langc1984ed2016-10-07 12:41:00 -04004473bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4474 GLuint sampler,
4475 GLenum pname,
4476 GLsizei bufSize,
4477 const GLfloat *params)
4478{
4479 if (!ValidateRobustEntryPoint(context, bufSize))
4480 {
4481 return false;
4482 }
4483
4484 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4485}
4486
Geoff Langc1984ed2016-10-07 12:41:00 -04004487bool ValidateSamplerParameterivRobustANGLE(Context *context,
4488 GLuint sampler,
4489 GLenum pname,
4490 GLsizei bufSize,
4491 const GLint *params)
4492{
4493 if (!ValidateRobustEntryPoint(context, bufSize))
4494 {
4495 return false;
4496 }
4497
4498 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4499}
4500
Geoff Lang0b031062016-10-13 14:30:04 -04004501bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4502 GLuint index,
4503 GLenum pname,
4504 GLsizei bufSize,
4505 GLsizei *length,
4506 GLfloat *params)
4507{
4508 if (!ValidateRobustEntryPoint(context, bufSize))
4509 {
4510 return false;
4511 }
4512
4513 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4514 {
4515 return false;
4516 }
4517
4518 if (!ValidateRobustBufferSize(context, bufSize, *length))
4519 {
4520 return false;
4521 }
4522
4523 return true;
4524}
4525
Geoff Lang0b031062016-10-13 14:30:04 -04004526bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4527 GLuint index,
4528 GLenum pname,
4529 GLsizei bufSize,
4530 GLsizei *length,
4531 GLint *params)
4532{
4533 if (!ValidateRobustEntryPoint(context, bufSize))
4534 {
4535 return false;
4536 }
4537
4538 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4539 {
4540 return false;
4541 }
4542
4543 if (!ValidateRobustBufferSize(context, bufSize, *length))
4544 {
4545 return false;
4546 }
4547
4548 return true;
4549}
4550
Geoff Lang0b031062016-10-13 14:30:04 -04004551bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4552 GLuint index,
4553 GLenum pname,
4554 GLsizei bufSize,
4555 GLsizei *length,
4556 void **pointer)
4557{
4558 if (!ValidateRobustEntryPoint(context, bufSize))
4559 {
4560 return false;
4561 }
4562
4563 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4564 {
4565 return false;
4566 }
4567
4568 if (!ValidateRobustBufferSize(context, bufSize, *length))
4569 {
4570 return false;
4571 }
4572
4573 return true;
4574}
4575
Geoff Lang0b031062016-10-13 14:30:04 -04004576bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4577 GLuint index,
4578 GLenum pname,
4579 GLsizei bufSize,
4580 GLsizei *length,
4581 GLint *params)
4582{
4583 if (!ValidateRobustEntryPoint(context, bufSize))
4584 {
4585 return false;
4586 }
4587
4588 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4589 {
4590 return false;
4591 }
4592
4593 if (!ValidateRobustBufferSize(context, bufSize, *length))
4594 {
4595 return false;
4596 }
4597
4598 return true;
4599}
4600
Geoff Lang0b031062016-10-13 14:30:04 -04004601bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4602 GLuint index,
4603 GLenum pname,
4604 GLsizei bufSize,
4605 GLsizei *length,
4606 GLuint *params)
4607{
4608 if (!ValidateRobustEntryPoint(context, bufSize))
4609 {
4610 return false;
4611 }
4612
4613 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4614 {
4615 return false;
4616 }
4617
4618 if (!ValidateRobustBufferSize(context, bufSize, *length))
4619 {
4620 return false;
4621 }
4622
4623 return true;
4624}
4625
Geoff Lang6899b872016-10-14 11:30:13 -04004626bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4627 GLuint program,
4628 GLuint uniformBlockIndex,
4629 GLenum pname,
4630 GLsizei bufSize,
4631 GLsizei *length,
4632 GLint *params)
4633{
4634 if (!ValidateRobustEntryPoint(context, bufSize))
4635 {
4636 return false;
4637 }
4638
4639 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4640 {
4641 return false;
4642 }
4643
4644 if (!ValidateRobustBufferSize(context, bufSize, *length))
4645 {
4646 return false;
4647 }
4648
4649 return true;
4650}
4651
Geoff Lang0a9661f2016-10-20 10:59:20 -07004652bool ValidateGetInternalFormativRobustANGLE(Context *context,
4653 GLenum target,
4654 GLenum internalformat,
4655 GLenum pname,
4656 GLsizei bufSize,
4657 GLsizei *length,
4658 GLint *params)
4659{
4660 if (!ValidateRobustEntryPoint(context, bufSize))
4661 {
4662 return false;
4663 }
4664
4665 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4666 {
4667 return false;
4668 }
4669
4670 if (!ValidateRobustBufferSize(context, bufSize, *length))
4671 {
4672 return false;
4673 }
4674
4675 return true;
4676}
4677
Jamie Madill5b772312018-03-08 20:28:32 -05004678bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08004679 GLuint attribIndex,
4680 GLint size,
4681 GLenum type,
4682 GLboolean pureInteger)
4683{
4684 const Caps &caps = context->getCaps();
4685 if (attribIndex >= caps.maxVertexAttributes)
4686 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004687 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004688 return false;
4689 }
4690
4691 if (size < 1 || size > 4)
4692 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004693 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004694 return false;
Shao80957d92017-02-20 21:25:59 +08004695 }
4696
4697 switch (type)
4698 {
4699 case GL_BYTE:
4700 case GL_UNSIGNED_BYTE:
4701 case GL_SHORT:
4702 case GL_UNSIGNED_SHORT:
4703 break;
4704
4705 case GL_INT:
4706 case GL_UNSIGNED_INT:
4707 if (context->getClientMajorVersion() < 3)
4708 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004709 context->handleError(InvalidEnum()
4710 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004711 return false;
4712 }
4713 break;
4714
4715 case GL_FIXED:
4716 case GL_FLOAT:
4717 if (pureInteger)
4718 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004719 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004720 return false;
4721 }
4722 break;
4723
4724 case GL_HALF_FLOAT:
4725 if (context->getClientMajorVersion() < 3)
4726 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004727 context->handleError(InvalidEnum()
4728 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004729 return false;
4730 }
4731 if (pureInteger)
4732 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004733 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004734 return false;
4735 }
4736 break;
4737
4738 case GL_INT_2_10_10_10_REV:
4739 case GL_UNSIGNED_INT_2_10_10_10_REV:
4740 if (context->getClientMajorVersion() < 3)
4741 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004742 context->handleError(InvalidEnum()
4743 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004744 return false;
4745 }
4746 if (pureInteger)
4747 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004748 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004749 return false;
4750 }
4751 if (size != 4)
4752 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004753 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4754 "UNSIGNED_INT_2_10_10_10_REV and "
4755 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004756 return false;
4757 }
4758 break;
4759
4760 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004761 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004762 return false;
4763 }
4764
4765 return true;
4766}
4767
Geoff Lang76e65652017-03-27 14:58:02 -04004768// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4769// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4770// specified clear value and the type of a buffer that is being cleared generates an
4771// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05004772bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04004773 GLint drawbuffer,
4774 const GLenum *validComponentTypes,
4775 size_t validComponentTypeCount)
4776{
4777 const FramebufferAttachment *attachment =
4778 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4779 if (attachment)
4780 {
4781 GLenum componentType = attachment->getFormat().info->componentType;
4782 const GLenum *end = validComponentTypes + validComponentTypeCount;
4783 if (std::find(validComponentTypes, end, componentType) == end)
4784 {
4785 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004786 InvalidOperation()
4787 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004788 return false;
4789 }
4790 }
4791
4792 return true;
4793}
4794
Jamie Madill5b772312018-03-08 20:28:32 -05004795bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04004796{
4797 if (!ValidateRobustEntryPoint(context, dataSize))
4798 {
4799 return false;
4800 }
4801
Corentin Wallez336129f2017-10-17 15:55:40 -04004802 gl::Buffer *pixelUnpackBuffer =
4803 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004804 if (pixelUnpackBuffer == nullptr)
4805 {
4806 if (dataSize < imageSize)
4807 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004808 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004809 }
4810 }
4811 return true;
4812}
4813
Jamie Madill5b772312018-03-08 20:28:32 -05004814bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004815 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004816 GLenum pname,
4817 bool pointerVersion,
4818 GLsizei *numParams)
4819{
4820 if (numParams)
4821 {
4822 *numParams = 0;
4823 }
4824
Corentin Walleze4477002017-12-01 14:39:58 -05004825 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004826 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004827 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004828 return false;
4829 }
4830
4831 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4832 if (!buffer)
4833 {
4834 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004835 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004836 return false;
4837 }
4838
4839 const Extensions &extensions = context->getExtensions();
4840
4841 switch (pname)
4842 {
4843 case GL_BUFFER_USAGE:
4844 case GL_BUFFER_SIZE:
4845 break;
4846
4847 case GL_BUFFER_ACCESS_OES:
4848 if (!extensions.mapBuffer)
4849 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004850 context->handleError(InvalidEnum()
4851 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004852 return false;
4853 }
4854 break;
4855
4856 case GL_BUFFER_MAPPED:
4857 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4858 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4859 !extensions.mapBufferRange)
4860 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004861 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4862 "GL_OES_mapbuffer or "
4863 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004864 return false;
4865 }
4866 break;
4867
4868 case GL_BUFFER_MAP_POINTER:
4869 if (!pointerVersion)
4870 {
4871 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004872 InvalidEnum()
4873 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004874 return false;
4875 }
4876 break;
4877
4878 case GL_BUFFER_ACCESS_FLAGS:
4879 case GL_BUFFER_MAP_OFFSET:
4880 case GL_BUFFER_MAP_LENGTH:
4881 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4882 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004883 context->handleError(InvalidEnum()
4884 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004885 return false;
4886 }
4887 break;
4888
4889 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004890 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004891 return false;
4892 }
4893
4894 // All buffer parameter queries return one value.
4895 if (numParams)
4896 {
4897 *numParams = 1;
4898 }
4899
4900 return true;
4901}
4902
4903bool ValidateGetRenderbufferParameterivBase(Context *context,
4904 GLenum target,
4905 GLenum pname,
4906 GLsizei *length)
4907{
4908 if (length)
4909 {
4910 *length = 0;
4911 }
4912
4913 if (target != GL_RENDERBUFFER)
4914 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004915 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004916 return false;
4917 }
4918
4919 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4920 if (renderbuffer == nullptr)
4921 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004922 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004923 return false;
4924 }
4925
4926 switch (pname)
4927 {
4928 case GL_RENDERBUFFER_WIDTH:
4929 case GL_RENDERBUFFER_HEIGHT:
4930 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4931 case GL_RENDERBUFFER_RED_SIZE:
4932 case GL_RENDERBUFFER_GREEN_SIZE:
4933 case GL_RENDERBUFFER_BLUE_SIZE:
4934 case GL_RENDERBUFFER_ALPHA_SIZE:
4935 case GL_RENDERBUFFER_DEPTH_SIZE:
4936 case GL_RENDERBUFFER_STENCIL_SIZE:
4937 break;
4938
4939 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4940 if (!context->getExtensions().framebufferMultisample)
4941 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004942 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004943 return false;
4944 }
4945 break;
4946
4947 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004948 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004949 return false;
4950 }
4951
4952 if (length)
4953 {
4954 *length = 1;
4955 }
4956 return true;
4957}
4958
4959bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4960{
4961 if (length)
4962 {
4963 *length = 0;
4964 }
4965
4966 if (GetValidShader(context, shader) == nullptr)
4967 {
4968 return false;
4969 }
4970
4971 switch (pname)
4972 {
4973 case GL_SHADER_TYPE:
4974 case GL_DELETE_STATUS:
4975 case GL_COMPILE_STATUS:
4976 case GL_INFO_LOG_LENGTH:
4977 case GL_SHADER_SOURCE_LENGTH:
4978 break;
4979
4980 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4981 if (!context->getExtensions().translatedShaderSource)
4982 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004983 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004984 return false;
4985 }
4986 break;
4987
4988 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004989 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004990 return false;
4991 }
4992
4993 if (length)
4994 {
4995 *length = 1;
4996 }
4997 return true;
4998}
4999
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005000bool ValidateGetTexParameterBase(Context *context,
5001 TextureType target,
5002 GLenum pname,
5003 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005004{
5005 if (length)
5006 {
5007 *length = 0;
5008 }
5009
5010 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5011 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005012 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005013 return false;
5014 }
5015
5016 if (context->getTargetTexture(target) == nullptr)
5017 {
5018 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005019 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005020 return false;
5021 }
5022
5023 switch (pname)
5024 {
5025 case GL_TEXTURE_MAG_FILTER:
5026 case GL_TEXTURE_MIN_FILTER:
5027 case GL_TEXTURE_WRAP_S:
5028 case GL_TEXTURE_WRAP_T:
5029 break;
5030
5031 case GL_TEXTURE_USAGE_ANGLE:
5032 if (!context->getExtensions().textureUsage)
5033 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005034 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005035 return false;
5036 }
5037 break;
5038
5039 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005040 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005041 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005042 return false;
5043 }
5044 break;
5045
5046 case GL_TEXTURE_IMMUTABLE_FORMAT:
5047 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5048 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005049 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005050 return false;
5051 }
5052 break;
5053
5054 case GL_TEXTURE_WRAP_R:
5055 case GL_TEXTURE_IMMUTABLE_LEVELS:
5056 case GL_TEXTURE_SWIZZLE_R:
5057 case GL_TEXTURE_SWIZZLE_G:
5058 case GL_TEXTURE_SWIZZLE_B:
5059 case GL_TEXTURE_SWIZZLE_A:
5060 case GL_TEXTURE_BASE_LEVEL:
5061 case GL_TEXTURE_MAX_LEVEL:
5062 case GL_TEXTURE_MIN_LOD:
5063 case GL_TEXTURE_MAX_LOD:
5064 case GL_TEXTURE_COMPARE_MODE:
5065 case GL_TEXTURE_COMPARE_FUNC:
5066 if (context->getClientMajorVersion() < 3)
5067 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005068 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005069 return false;
5070 }
5071 break;
5072
5073 case GL_TEXTURE_SRGB_DECODE_EXT:
5074 if (!context->getExtensions().textureSRGBDecode)
5075 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005076 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005077 return false;
5078 }
5079 break;
5080
Yunchao Hebacaa712018-01-30 14:01:39 +08005081 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5082 if (context->getClientVersion() < Version(3, 1))
5083 {
5084 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5085 return false;
5086 }
5087 break;
5088
Jamie Madillbe849e42017-05-02 15:49:00 -04005089 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005090 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005091 return false;
5092 }
5093
5094 if (length)
5095 {
5096 *length = 1;
5097 }
5098 return true;
5099}
5100
5101bool ValidateGetVertexAttribBase(Context *context,
5102 GLuint index,
5103 GLenum pname,
5104 GLsizei *length,
5105 bool pointer,
5106 bool pureIntegerEntryPoint)
5107{
5108 if (length)
5109 {
5110 *length = 0;
5111 }
5112
5113 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5114 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005115 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005116 return false;
5117 }
5118
5119 if (index >= context->getCaps().maxVertexAttributes)
5120 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005121 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005122 return false;
5123 }
5124
5125 if (pointer)
5126 {
5127 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5128 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005129 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005130 return false;
5131 }
5132 }
5133 else
5134 {
5135 switch (pname)
5136 {
5137 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5138 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5139 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5140 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5141 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5142 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5143 case GL_CURRENT_VERTEX_ATTRIB:
5144 break;
5145
5146 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5147 static_assert(
5148 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5149 "ANGLE extension enums not equal to GL enums.");
5150 if (context->getClientMajorVersion() < 3 &&
5151 !context->getExtensions().instancedArrays)
5152 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005153 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5154 "requires OpenGL ES 3.0 or "
5155 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005156 return false;
5157 }
5158 break;
5159
5160 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5161 if (context->getClientMajorVersion() < 3)
5162 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005163 context->handleError(
5164 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005165 return false;
5166 }
5167 break;
5168
5169 case GL_VERTEX_ATTRIB_BINDING:
5170 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5171 if (context->getClientVersion() < ES_3_1)
5172 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005173 context->handleError(InvalidEnum()
5174 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005175 return false;
5176 }
5177 break;
5178
5179 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005180 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005181 return false;
5182 }
5183 }
5184
5185 if (length)
5186 {
5187 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5188 {
5189 *length = 4;
5190 }
5191 else
5192 {
5193 *length = 1;
5194 }
5195 }
5196
5197 return true;
5198}
5199
Jamie Madill4928b7c2017-06-20 12:57:39 -04005200bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005201 GLint x,
5202 GLint y,
5203 GLsizei width,
5204 GLsizei height,
5205 GLenum format,
5206 GLenum type,
5207 GLsizei bufSize,
5208 GLsizei *length,
5209 GLsizei *columns,
5210 GLsizei *rows,
5211 void *pixels)
5212{
5213 if (length != nullptr)
5214 {
5215 *length = 0;
5216 }
5217 if (rows != nullptr)
5218 {
5219 *rows = 0;
5220 }
5221 if (columns != nullptr)
5222 {
5223 *columns = 0;
5224 }
5225
5226 if (width < 0 || height < 0)
5227 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005228 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005229 return false;
5230 }
5231
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005232 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005233
Jamie Madille98b1b52018-03-08 09:47:23 -05005234 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madillbe849e42017-05-02 15:49:00 -04005235 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005236 return false;
5237 }
5238
Jamie Madille98b1b52018-03-08 09:47:23 -05005239 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005240 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005241 return false;
5242 }
5243
Jamie Madill690c8eb2018-03-12 15:20:03 -04005244 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005245 ASSERT(framebuffer);
5246
5247 if (framebuffer->getReadBufferState() == GL_NONE)
5248 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005249 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005250 return false;
5251 }
5252
5253 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5254 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5255 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5256 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5257 // situation is an application error that would lead to a crash in ANGLE.
5258 if (readBuffer == nullptr)
5259 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005260 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005261 return false;
5262 }
5263
Martin Radev28031682017-07-28 14:47:56 +03005264 // ANGLE_multiview, Revision 1:
5265 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5266 // current read framebuffer is not NONE.
5267 if (readBuffer->getMultiviewLayout() != GL_NONE)
5268 {
5269 context->handleError(InvalidFramebufferOperation()
5270 << "Attempting to read from a multi-view framebuffer.");
5271 return false;
5272 }
5273
Geoff Lang280ba992017-04-18 16:30:58 -04005274 if (context->getExtensions().webglCompatibility)
5275 {
5276 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5277 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5278 // and type before validating the combination of format and type. However, the
5279 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5280 // verifies that GL_INVALID_OPERATION is generated.
5281 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5282 // dEQP/WebGL.
5283 if (!ValidReadPixelsFormatEnum(context, format))
5284 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005285 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005286 return false;
5287 }
5288
5289 if (!ValidReadPixelsTypeEnum(context, type))
5290 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005291 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005292 return false;
5293 }
5294 }
5295
Jamie Madill690c8eb2018-03-12 15:20:03 -04005296 GLenum currentFormat = GL_NONE;
5297 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5298
5299 GLenum currentType = GL_NONE;
5300 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5301
Jamie Madillbe849e42017-05-02 15:49:00 -04005302 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5303
5304 bool validFormatTypeCombination =
5305 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5306
5307 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5308 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005309 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005310 return false;
5311 }
5312
5313 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005314 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005315 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5316 {
5317 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005318 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005319 return false;
5320 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005321 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5322 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5323 {
5324 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5325 return false;
5326 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005327
5328 // .. the data would be packed to the buffer object such that the memory writes required
5329 // would exceed the data store size.
5330 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5331 const gl::Extents size(width, height, 1);
5332 const auto &pack = context->getGLState().getPackState();
5333
5334 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5335 if (endByteOrErr.isError())
5336 {
5337 context->handleError(endByteOrErr.getError());
5338 return false;
5339 }
5340
5341 size_t endByte = endByteOrErr.getResult();
5342 if (bufSize >= 0)
5343 {
5344 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5345 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005346 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005347 return false;
5348 }
5349 }
5350
5351 if (pixelPackBuffer != nullptr)
5352 {
5353 CheckedNumeric<size_t> checkedEndByte(endByte);
5354 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5355 checkedEndByte += checkedOffset;
5356
5357 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5358 {
5359 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005360 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005361 return false;
5362 }
5363 }
5364
5365 if (pixelPackBuffer == nullptr && length != nullptr)
5366 {
5367 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5368 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005369 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005370 return false;
5371 }
5372
5373 *length = static_cast<GLsizei>(endByte);
5374 }
5375
Geoff Langa953b522018-02-21 16:56:23 -05005376 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005377 angle::CheckedNumeric<int> clippedExtent(length);
5378 if (start < 0)
5379 {
5380 // "subtract" the area that is less than 0
5381 clippedExtent += start;
5382 }
5383
Geoff Langa953b522018-02-21 16:56:23 -05005384 angle::CheckedNumeric<int> readExtent = start;
5385 readExtent += length;
5386 if (!readExtent.IsValid())
5387 {
5388 return false;
5389 }
5390
5391 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005392 {
5393 // Subtract the region to the right of the read buffer
5394 clippedExtent -= (readExtent - bufferSize);
5395 }
5396
5397 if (!clippedExtent.IsValid())
5398 {
Geoff Langa953b522018-02-21 16:56:23 -05005399 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005400 }
5401
Geoff Langa953b522018-02-21 16:56:23 -05005402 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5403 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005404 };
5405
Geoff Langa953b522018-02-21 16:56:23 -05005406 GLsizei writtenColumns = 0;
5407 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5408 {
5409 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5410 return false;
5411 }
5412
5413 GLsizei writtenRows = 0;
5414 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5415 {
5416 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5417 return false;
5418 }
5419
Jamie Madillbe849e42017-05-02 15:49:00 -04005420 if (columns != nullptr)
5421 {
Geoff Langa953b522018-02-21 16:56:23 -05005422 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005423 }
5424
5425 if (rows != nullptr)
5426 {
Geoff Langa953b522018-02-21 16:56:23 -05005427 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005428 }
5429
5430 return true;
5431}
5432
5433template <typename ParamType>
5434bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005435 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005436 GLenum pname,
5437 GLsizei bufSize,
5438 const ParamType *params)
5439{
5440 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5441 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005442 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005443 return false;
5444 }
5445
5446 if (context->getTargetTexture(target) == nullptr)
5447 {
5448 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005449 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005450 return false;
5451 }
5452
5453 const GLsizei minBufSize = 1;
5454 if (bufSize >= 0 && bufSize < minBufSize)
5455 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005456 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005457 return false;
5458 }
5459
5460 switch (pname)
5461 {
5462 case GL_TEXTURE_WRAP_R:
5463 case GL_TEXTURE_SWIZZLE_R:
5464 case GL_TEXTURE_SWIZZLE_G:
5465 case GL_TEXTURE_SWIZZLE_B:
5466 case GL_TEXTURE_SWIZZLE_A:
5467 case GL_TEXTURE_BASE_LEVEL:
5468 case GL_TEXTURE_MAX_LEVEL:
5469 case GL_TEXTURE_COMPARE_MODE:
5470 case GL_TEXTURE_COMPARE_FUNC:
5471 case GL_TEXTURE_MIN_LOD:
5472 case GL_TEXTURE_MAX_LOD:
5473 if (context->getClientMajorVersion() < 3)
5474 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005475 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005476 return false;
5477 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005478 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005479 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005480 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5481 "available without "
5482 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005483 return false;
5484 }
5485 break;
5486
5487 default:
5488 break;
5489 }
5490
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005491 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005492 {
5493 switch (pname)
5494 {
5495 case GL_TEXTURE_MIN_FILTER:
5496 case GL_TEXTURE_MAG_FILTER:
5497 case GL_TEXTURE_WRAP_S:
5498 case GL_TEXTURE_WRAP_T:
5499 case GL_TEXTURE_WRAP_R:
5500 case GL_TEXTURE_MIN_LOD:
5501 case GL_TEXTURE_MAX_LOD:
5502 case GL_TEXTURE_COMPARE_MODE:
5503 case GL_TEXTURE_COMPARE_FUNC:
5504 context->handleError(InvalidEnum()
5505 << "Invalid parameter for 2D multisampled textures.");
5506 return false;
5507 }
5508 }
5509
Jamie Madillbe849e42017-05-02 15:49:00 -04005510 switch (pname)
5511 {
5512 case GL_TEXTURE_WRAP_S:
5513 case GL_TEXTURE_WRAP_T:
5514 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005515 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005516 bool restrictedWrapModes =
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005517 target == TextureType::External || target == TextureType::Rectangle;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005518 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5519 {
5520 return false;
5521 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005522 }
5523 break;
5524
5525 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005526 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005527 bool restrictedMinFilter =
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005528 target == TextureType::External || target == TextureType::Rectangle;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005529 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5530 {
5531 return false;
5532 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005533 }
5534 break;
5535
5536 case GL_TEXTURE_MAG_FILTER:
5537 if (!ValidateTextureMagFilterValue(context, params))
5538 {
5539 return false;
5540 }
5541 break;
5542
5543 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005544 if (!context->getExtensions().textureUsage)
5545 {
5546 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5547 return false;
5548 }
5549
Jamie Madillbe849e42017-05-02 15:49:00 -04005550 switch (ConvertToGLenum(params[0]))
5551 {
5552 case GL_NONE:
5553 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5554 break;
5555
5556 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005557 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005558 return false;
5559 }
5560 break;
5561
5562 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Jamie Madillbe849e42017-05-02 15:49:00 -04005563 {
Luc Ferron1b1a8642018-01-23 15:12:01 -05005564 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5565 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5566 {
5567 return false;
5568 }
5569 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
Jamie Madillbe849e42017-05-02 15:49:00 -04005570 }
5571 break;
5572
5573 case GL_TEXTURE_MIN_LOD:
5574 case GL_TEXTURE_MAX_LOD:
5575 // any value is permissible
5576 break;
5577
5578 case GL_TEXTURE_COMPARE_MODE:
5579 if (!ValidateTextureCompareModeValue(context, params))
5580 {
5581 return false;
5582 }
5583 break;
5584
5585 case GL_TEXTURE_COMPARE_FUNC:
5586 if (!ValidateTextureCompareFuncValue(context, params))
5587 {
5588 return false;
5589 }
5590 break;
5591
5592 case GL_TEXTURE_SWIZZLE_R:
5593 case GL_TEXTURE_SWIZZLE_G:
5594 case GL_TEXTURE_SWIZZLE_B:
5595 case GL_TEXTURE_SWIZZLE_A:
5596 switch (ConvertToGLenum(params[0]))
5597 {
5598 case GL_RED:
5599 case GL_GREEN:
5600 case GL_BLUE:
5601 case GL_ALPHA:
5602 case GL_ZERO:
5603 case GL_ONE:
5604 break;
5605
5606 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005607 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005608 return false;
5609 }
5610 break;
5611
5612 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005613 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005614 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005615 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005616 return false;
5617 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005618 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005619 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005620 context->handleError(InvalidOperation()
5621 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005622 return false;
5623 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005624 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005625 {
5626 context->handleError(InvalidOperation()
5627 << "Base level must be 0 for multisampled textures.");
5628 return false;
5629 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005630 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005631 {
5632 context->handleError(InvalidOperation()
5633 << "Base level must be 0 for rectangle textures.");
5634 return false;
5635 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005636 break;
5637
5638 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005639 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005640 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005641 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005642 return false;
5643 }
5644 break;
5645
5646 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5647 if (context->getClientVersion() < Version(3, 1))
5648 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005649 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005650 return false;
5651 }
5652 switch (ConvertToGLenum(params[0]))
5653 {
5654 case GL_DEPTH_COMPONENT:
5655 case GL_STENCIL_INDEX:
5656 break;
5657
5658 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005659 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005660 return false;
5661 }
5662 break;
5663
5664 case GL_TEXTURE_SRGB_DECODE_EXT:
5665 if (!ValidateTextureSRGBDecodeValue(context, params))
5666 {
5667 return false;
5668 }
5669 break;
5670
5671 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005672 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005673 return false;
5674 }
5675
5676 return true;
5677}
5678
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005679template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
5680template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04005681
Jamie Madill5b772312018-03-08 20:28:32 -05005682bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04005683{
5684 if (index >= MAX_VERTEX_ATTRIBS)
5685 {
5686 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5687 return false;
5688 }
5689
5690 return true;
5691}
5692
5693bool ValidateGetActiveUniformBlockivBase(Context *context,
5694 GLuint program,
5695 GLuint uniformBlockIndex,
5696 GLenum pname,
5697 GLsizei *length)
5698{
5699 if (length)
5700 {
5701 *length = 0;
5702 }
5703
5704 if (context->getClientMajorVersion() < 3)
5705 {
5706 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5707 return false;
5708 }
5709
5710 Program *programObject = GetValidProgram(context, program);
5711 if (!programObject)
5712 {
5713 return false;
5714 }
5715
5716 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5717 {
5718 context->handleError(InvalidValue()
5719 << "uniformBlockIndex exceeds active uniform block count.");
5720 return false;
5721 }
5722
5723 switch (pname)
5724 {
5725 case GL_UNIFORM_BLOCK_BINDING:
5726 case GL_UNIFORM_BLOCK_DATA_SIZE:
5727 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5728 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5729 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5730 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5731 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5732 break;
5733
5734 default:
5735 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5736 return false;
5737 }
5738
5739 if (length)
5740 {
5741 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5742 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005743 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005744 programObject->getUniformBlockByIndex(uniformBlockIndex);
5745 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5746 }
5747 else
5748 {
5749 *length = 1;
5750 }
5751 }
5752
5753 return true;
5754}
5755
Jamie Madill9696d072017-08-26 23:19:57 -04005756template <typename ParamType>
5757bool ValidateSamplerParameterBase(Context *context,
5758 GLuint sampler,
5759 GLenum pname,
5760 GLsizei bufSize,
5761 ParamType *params)
5762{
5763 if (context->getClientMajorVersion() < 3)
5764 {
5765 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5766 return false;
5767 }
5768
5769 if (!context->isSampler(sampler))
5770 {
5771 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5772 return false;
5773 }
5774
5775 const GLsizei minBufSize = 1;
5776 if (bufSize >= 0 && bufSize < minBufSize)
5777 {
5778 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5779 return false;
5780 }
5781
5782 switch (pname)
5783 {
5784 case GL_TEXTURE_WRAP_S:
5785 case GL_TEXTURE_WRAP_T:
5786 case GL_TEXTURE_WRAP_R:
5787 if (!ValidateTextureWrapModeValue(context, params, false))
5788 {
5789 return false;
5790 }
5791 break;
5792
5793 case GL_TEXTURE_MIN_FILTER:
5794 if (!ValidateTextureMinFilterValue(context, params, false))
5795 {
5796 return false;
5797 }
5798 break;
5799
5800 case GL_TEXTURE_MAG_FILTER:
5801 if (!ValidateTextureMagFilterValue(context, params))
5802 {
5803 return false;
5804 }
5805 break;
5806
5807 case GL_TEXTURE_MIN_LOD:
5808 case GL_TEXTURE_MAX_LOD:
5809 // any value is permissible
5810 break;
5811
5812 case GL_TEXTURE_COMPARE_MODE:
5813 if (!ValidateTextureCompareModeValue(context, params))
5814 {
5815 return false;
5816 }
5817 break;
5818
5819 case GL_TEXTURE_COMPARE_FUNC:
5820 if (!ValidateTextureCompareFuncValue(context, params))
5821 {
5822 return false;
5823 }
5824 break;
5825
5826 case GL_TEXTURE_SRGB_DECODE_EXT:
5827 if (!ValidateTextureSRGBDecodeValue(context, params))
5828 {
5829 return false;
5830 }
5831 break;
5832
Luc Ferron1b1a8642018-01-23 15:12:01 -05005833 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5834 {
5835 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5836 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5837 {
5838 return false;
5839 }
5840 }
5841 break;
5842
Jamie Madill9696d072017-08-26 23:19:57 -04005843 default:
5844 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5845 return false;
5846 }
5847
5848 return true;
5849}
5850
5851template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5852template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5853
5854bool ValidateGetSamplerParameterBase(Context *context,
5855 GLuint sampler,
5856 GLenum pname,
5857 GLsizei *length)
5858{
5859 if (length)
5860 {
5861 *length = 0;
5862 }
5863
5864 if (context->getClientMajorVersion() < 3)
5865 {
5866 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5867 return false;
5868 }
5869
5870 if (!context->isSampler(sampler))
5871 {
5872 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5873 return false;
5874 }
5875
5876 switch (pname)
5877 {
5878 case GL_TEXTURE_WRAP_S:
5879 case GL_TEXTURE_WRAP_T:
5880 case GL_TEXTURE_WRAP_R:
5881 case GL_TEXTURE_MIN_FILTER:
5882 case GL_TEXTURE_MAG_FILTER:
5883 case GL_TEXTURE_MIN_LOD:
5884 case GL_TEXTURE_MAX_LOD:
5885 case GL_TEXTURE_COMPARE_MODE:
5886 case GL_TEXTURE_COMPARE_FUNC:
5887 break;
5888
Luc Ferron1b1a8642018-01-23 15:12:01 -05005889 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5890 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
5891 {
5892 return false;
5893 }
5894 break;
5895
Jamie Madill9696d072017-08-26 23:19:57 -04005896 case GL_TEXTURE_SRGB_DECODE_EXT:
5897 if (!context->getExtensions().textureSRGBDecode)
5898 {
5899 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5900 return false;
5901 }
5902 break;
5903
5904 default:
5905 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5906 return false;
5907 }
5908
5909 if (length)
5910 {
5911 *length = 1;
5912 }
5913 return true;
5914}
5915
5916bool ValidateGetInternalFormativBase(Context *context,
5917 GLenum target,
5918 GLenum internalformat,
5919 GLenum pname,
5920 GLsizei bufSize,
5921 GLsizei *numParams)
5922{
5923 if (numParams)
5924 {
5925 *numParams = 0;
5926 }
5927
5928 if (context->getClientMajorVersion() < 3)
5929 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005930 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005931 return false;
5932 }
5933
5934 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5935 if (!formatCaps.renderable)
5936 {
5937 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5938 return false;
5939 }
5940
5941 switch (target)
5942 {
5943 case GL_RENDERBUFFER:
5944 break;
5945
5946 case GL_TEXTURE_2D_MULTISAMPLE:
5947 if (context->getClientVersion() < ES_3_1)
5948 {
5949 context->handleError(InvalidOperation()
5950 << "Texture target requires at least OpenGL ES 3.1.");
5951 return false;
5952 }
5953 break;
5954
5955 default:
5956 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5957 return false;
5958 }
5959
5960 if (bufSize < 0)
5961 {
5962 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5963 return false;
5964 }
5965
5966 GLsizei maxWriteParams = 0;
5967 switch (pname)
5968 {
5969 case GL_NUM_SAMPLE_COUNTS:
5970 maxWriteParams = 1;
5971 break;
5972
5973 case GL_SAMPLES:
5974 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5975 break;
5976
5977 default:
5978 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5979 return false;
5980 }
5981
5982 if (numParams)
5983 {
5984 // glGetInternalFormativ will not overflow bufSize
5985 *numParams = std::min(bufSize, maxWriteParams);
5986 }
5987
5988 return true;
5989}
5990
Jamie Madille98b1b52018-03-08 09:47:23 -05005991// We should check with Khronos if returning INVALID_FRAMEBUFFER_OPERATION is OK when querying
5992// implementation format info for incomplete framebuffers. It seems like these queries are
5993// incongruent with the other errors.
5994bool ValidateFramebufferComplete(Context *context, Framebuffer *framebuffer, bool isFramebufferOp)
5995{
5996 bool complete = false;
5997 ANGLE_VALIDATION_TRY(framebuffer->isComplete(context, &complete));
5998 if (!complete)
5999 {
6000 if (isFramebufferOp)
6001 {
6002 context->handleError(InvalidFramebufferOperation());
6003 }
6004 else
6005 {
6006 context->handleError(InvalidOperation());
6007 }
6008 return false;
6009 }
6010 return true;
6011}
6012
6013bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6014{
6015 GLint samples = 0;
6016 ANGLE_VALIDATION_TRY(framebuffer->getSamples(context, &samples));
6017 if (samples != 0)
6018 {
6019 context->handleError(InvalidOperation());
6020 return false;
6021 }
6022 return true;
6023}
6024
Jamie Madillc29968b2016-01-20 11:17:23 -05006025} // namespace gl