blob: ada0959ce7b8ac7090ee5303d5dfb933eb6e3c0f [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"
James Darpinian30b604d2018-03-12 17:26:57 -070022#include "libANGLE/angletypes.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040023#include "libANGLE/formatutils.h"
jchen10a99ed552017-09-22 08:10:32 +080024#include "libANGLE/queryconversions.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040025#include "libANGLE/validationES2.h"
26#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040027
28#include "common/mathutil.h"
29#include "common/utilities.h"
30
Jamie Madille2e406c2016-06-02 13:04:10 -040031using namespace angle;
32
Geoff Lange8ebe7f2013-08-05 15:03:13 -040033namespace gl
34{
Jamie Madill1ca74672015-07-21 15:14:11 -040035namespace
36{
Luc Ferron9dbaeba2018-02-01 07:26:59 -050037bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
38{
39 // List of compressed format that require that the texture size is smaller than or a multiple of
40 // the compressed block size.
41 switch (internalFormat)
42 {
43 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
44 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
45 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
46 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
47 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
48 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
49 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
50 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
51 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
52 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
53 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
54 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
55 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
56 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
57 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
58 return true;
jchen10a99ed552017-09-22 08:10:32 +080059
Luc Ferron9dbaeba2018-02-01 07:26:59 -050060 default:
61 return false;
62 }
63}
64bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
65{
66 // Compressed sub textures have additional formats that requires exact size.
67 // ES 3.1, Section 8.7, Page 171
68 return CompressedTextureFormatRequiresExactSize(internalFormat) ||
69 IsETC2EACFormat(internalFormat);
70}
Jamie Madill5b772312018-03-08 20:28:32 -050071bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex, GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040072{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070073 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040074 const gl::Program *program = state.getProgram();
75
Corentin Wallez327411e2016-12-09 11:09:17 -050076 bool webglCompatibility = context->getExtensions().webglCompatibility;
77
Jamie Madill231c7f52017-04-26 13:45:37 -040078 const VertexArray *vao = state.getVertexArray();
79 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080080 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madilld078c682018-01-02 11:50:24 -050081 for (size_t attributeIndex : vao->getEnabledAttributesMask())
Jamie Madill1ca74672015-07-21 15:14:11 -040082 {
83 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallez672f7f32017-06-15 17:42:17 -040084
85 // No need to range check for disabled attribs.
86 if (!attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040087 {
Corentin Wallezfd456442016-12-21 17:57:00 -050088 continue;
89 }
Jamie Madill1ca74672015-07-21 15:14:11 -040090
Jamie Madill231c7f52017-04-26 13:45:37 -040091 // If we have no buffer, then we either get an error, or there are no more checks to be
92 // done.
Corentin Wallez672f7f32017-06-15 17:42:17 -040093 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
94 gl::Buffer *buffer = binding.getBuffer().get();
Corentin Wallezfd456442016-12-21 17:57:00 -050095 if (!buffer)
96 {
Geoff Langfeb8c682017-02-13 16:07:35 -050097 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -050098 {
99 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -0500100 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
101 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
102 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
103 // error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700104 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
Corentin Wallezfd456442016-12-21 17:57:00 -0500105 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -0500106 }
Corentin Wallezfd456442016-12-21 17:57:00 -0500107 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -0400108 {
109 // This is an application error that would normally result in a crash,
110 // but we catch it and return an error
Brandon Jonesafa75152017-07-21 13:11:29 -0700111 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
Jamie Madill1ca74672015-07-21 15:14:11 -0400112 return false;
113 }
Corentin Wallezfd456442016-12-21 17:57:00 -0500114 continue;
115 }
116
Corentin Wallez672f7f32017-06-15 17:42:17 -0400117 // This needs to come after the check for client arrays as even unused attributes cannot use
118 // client-side arrays
119 if (!program->isAttribLocationActive(attributeIndex))
120 {
121 continue;
122 }
123
Corentin Wallezfd456442016-12-21 17:57:00 -0500124 // If we're drawing zero vertices, we have enough data.
125 if (vertexCount <= 0 || primcount <= 0)
126 {
127 continue;
128 }
129
130 GLint maxVertexElement = 0;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300131 GLuint divisor = binding.getDivisor();
132 if (divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500133 {
134 maxVertexElement = maxVertex;
135 }
136 else
137 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300138 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500139 }
140
141 // We do manual overflow checks here instead of using safe_math.h because it was
142 // a bottleneck. Thanks to some properties of GL we know inequalities that can
143 // help us make the overflow checks faster.
144
145 // The max possible attribSize is 16 for a vector of 4 32 bit values.
146 constexpr uint64_t kMaxAttribSize = 16;
147 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
148 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
149
150 // We know attribStride is given as a GLsizei which is typedefed to int.
151 // We also know an upper bound for attribSize.
152 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800153 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500154 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
155 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
156
157 // Computing the max offset using uint64_t without attrib.offset is overflow
158 // safe. Note: Last vertex element does not take the full stride!
159 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
160 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
161
162 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800163 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
164 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500165 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700166 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500167 return false;
168 }
169 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
170
171 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
172 // We can return INVALID_OPERATION if our vertex attribute does not have
173 // enough backing data.
174 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
175 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700176 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500177 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400178 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800179
180 if (webglCompatibility && buffer->isBoundForTransformFeedbackAndOtherUse())
181 {
182 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
183 VertexBufferBoundForTransformFeedback);
184 return false;
185 }
Jamie Madill1ca74672015-07-21 15:14:11 -0400186 }
187
188 return true;
189}
190
Jamie Madill5b772312018-03-08 20:28:32 -0500191bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400192{
193 switch (type)
194 {
195 // Types referenced in Table 3.4 of the ES 2.0.25 spec
196 case GL_UNSIGNED_BYTE:
197 case GL_UNSIGNED_SHORT_4_4_4_4:
198 case GL_UNSIGNED_SHORT_5_5_5_1:
199 case GL_UNSIGNED_SHORT_5_6_5:
200 return context->getClientVersion() >= ES_2_0;
201
202 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
203 case GL_BYTE:
204 case GL_INT:
205 case GL_SHORT:
206 case GL_UNSIGNED_INT:
207 case GL_UNSIGNED_INT_10F_11F_11F_REV:
208 case GL_UNSIGNED_INT_24_8:
209 case GL_UNSIGNED_INT_2_10_10_10_REV:
210 case GL_UNSIGNED_INT_5_9_9_9_REV:
211 case GL_UNSIGNED_SHORT:
212 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
213 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
214 return context->getClientVersion() >= ES_3_0;
215
216 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400217 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
218 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400219
220 case GL_HALF_FLOAT:
221 return context->getClientVersion() >= ES_3_0 ||
222 context->getExtensions().textureHalfFloat;
223
224 case GL_HALF_FLOAT_OES:
225 return context->getExtensions().colorBufferHalfFloat;
226
227 default:
228 return false;
229 }
230}
231
Jamie Madill5b772312018-03-08 20:28:32 -0500232bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400233{
234 switch (format)
235 {
236 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
237 case GL_RGBA:
238 case GL_RGB:
239 case GL_ALPHA:
240 return context->getClientVersion() >= ES_2_0;
241
242 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
243 case GL_RG:
244 case GL_RED:
245 case GL_RGBA_INTEGER:
246 case GL_RGB_INTEGER:
247 case GL_RG_INTEGER:
248 case GL_RED_INTEGER:
249 return context->getClientVersion() >= ES_3_0;
250
251 case GL_SRGB_ALPHA_EXT:
252 case GL_SRGB_EXT:
253 return context->getExtensions().sRGB;
254
255 case GL_BGRA_EXT:
256 return context->getExtensions().readFormatBGRA;
257
258 default:
259 return false;
260 }
261}
262
Jamie Madill5b772312018-03-08 20:28:32 -0500263bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400264 GLenum framebufferComponentType,
265 GLenum format,
266 GLenum type)
267{
268 switch (framebufferComponentType)
269 {
270 case GL_UNSIGNED_NORMALIZED:
271 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
272 // ReadPixels with BGRA even if the extension is not present
273 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
274 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
275 type == GL_UNSIGNED_BYTE);
276
277 case GL_SIGNED_NORMALIZED:
278 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
279
280 case GL_INT:
281 return (format == GL_RGBA_INTEGER && type == GL_INT);
282
283 case GL_UNSIGNED_INT:
284 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
285
286 case GL_FLOAT:
287 return (format == GL_RGBA && type == GL_FLOAT);
288
289 default:
290 UNREACHABLE();
291 return false;
292 }
293}
294
Geoff Langc1984ed2016-10-07 12:41:00 -0400295template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400296bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400297{
298 switch (ConvertToGLenum(params[0]))
299 {
300 case GL_CLAMP_TO_EDGE:
301 break;
302
303 case GL_REPEAT:
304 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400305 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400306 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400307 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700308 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400309 return false;
310 }
311 break;
312
313 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700314 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400315 return false;
316 }
317
318 return true;
319}
320
321template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400322bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400323{
324 switch (ConvertToGLenum(params[0]))
325 {
326 case GL_NEAREST:
327 case GL_LINEAR:
328 break;
329
330 case GL_NEAREST_MIPMAP_NEAREST:
331 case GL_LINEAR_MIPMAP_NEAREST:
332 case GL_NEAREST_MIPMAP_LINEAR:
333 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400334 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400335 {
336 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700337 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400338 return false;
339 }
340 break;
341
342 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700343 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400344 return false;
345 }
346
347 return true;
348}
349
350template <typename ParamType>
351bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
352{
353 switch (ConvertToGLenum(params[0]))
354 {
355 case GL_NEAREST:
356 case GL_LINEAR:
357 break;
358
359 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700360 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400361 return false;
362 }
363
364 return true;
365}
366
367template <typename ParamType>
368bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
369{
370 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
371 switch (ConvertToGLenum(params[0]))
372 {
373 case GL_NONE:
374 case GL_COMPARE_REF_TO_TEXTURE:
375 break;
376
377 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700378 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400379 return false;
380 }
381
382 return true;
383}
384
385template <typename ParamType>
386bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
387{
388 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
389 switch (ConvertToGLenum(params[0]))
390 {
391 case GL_LEQUAL:
392 case GL_GEQUAL:
393 case GL_LESS:
394 case GL_GREATER:
395 case GL_EQUAL:
396 case GL_NOTEQUAL:
397 case GL_ALWAYS:
398 case GL_NEVER:
399 break;
400
401 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700402 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400403 return false;
404 }
405
406 return true;
407}
408
409template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700410bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
411{
412 if (!context->getExtensions().textureSRGBDecode)
413 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700414 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700415 return false;
416 }
417
418 switch (ConvertToGLenum(params[0]))
419 {
420 case GL_DECODE_EXT:
421 case GL_SKIP_DECODE_EXT:
422 break;
423
424 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700425 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700426 return false;
427 }
428
429 return true;
430}
431
Luc Ferron1b1a8642018-01-23 15:12:01 -0500432bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
433{
434 if (!context->getExtensions().textureFilterAnisotropic)
435 {
436 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
437 return false;
438 }
439
440 return true;
441}
442
443bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
444{
445 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
446 {
447 return false;
448 }
449
450 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
451
452 if (paramValue < 1 || paramValue > largest)
453 {
454 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
455 return false;
456 }
457
458 return true;
459}
460
Jamie Madill5b772312018-03-08 20:28:32 -0500461bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400462{
463 const Program *program = context->getGLState().getProgram();
464 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
465
Brandon Jonesc405ae72017-12-06 14:15:03 -0800466 if (!ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
467 framebuffer->getDrawBufferTypeMask().to_ulong(),
468 program->getActiveOutputVariables().to_ulong(),
469 framebuffer->getDrawBufferMask().to_ulong()))
Geoff Lange0cff192017-05-30 13:04:56 -0400470 {
Brandon Jones76746f92017-11-22 11:44:41 -0800471 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
472 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400473 }
474
475 return true;
476}
477
Jamie Madill5b772312018-03-08 20:28:32 -0500478bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400479{
Jamie Madillcac94a92017-11-10 10:09:32 -0500480 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400481 const Program *program = context->getGLState().getProgram();
482 const VertexArray *vao = context->getGLState().getVertexArray();
483
Brandon Jonesc405ae72017-12-06 14:15:03 -0800484 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
485 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
486 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
487
488 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
489 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
490 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
491
492 if (!ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
493 program->getAttributesMask().to_ulong(), 0xFFFF))
Geoff Lang9ab5b822017-05-30 16:19:23 -0400494 {
Brandon Jonesc405ae72017-12-06 14:15:03 -0800495 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexShaderTypeMismatch);
496 return false;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400497 }
Geoff Lang9ab5b822017-05-30 16:19:23 -0400498 return true;
499}
500
Jiawei Shaofccebff2018-03-08 13:51:02 +0800501bool IsCompatibleDrawModeWithGeometryShader(GLenum drawMode,
502 GLenum geometryShaderInputPrimitiveType)
503{
504 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
505 switch (geometryShaderInputPrimitiveType)
506 {
507 case GL_POINTS:
508 return drawMode == GL_POINTS;
509 case GL_LINES:
510 return drawMode == GL_LINES || drawMode == GL_LINE_STRIP || drawMode == GL_LINE_LOOP;
511 case GL_LINES_ADJACENCY_EXT:
512 return drawMode == GL_LINES_ADJACENCY_EXT || drawMode == GL_LINE_STRIP_ADJACENCY_EXT;
513 case GL_TRIANGLES:
514 return drawMode == GL_TRIANGLES || drawMode == GL_TRIANGLE_FAN ||
515 drawMode == GL_TRIANGLE_STRIP;
516 case GL_TRIANGLES_ADJACENCY_EXT:
517 return drawMode == GL_TRIANGLES_ADJACENCY_EXT ||
518 drawMode == GL_TRIANGLE_STRIP_ADJACENCY_EXT;
519 default:
520 UNREACHABLE();
521 return false;
522 }
523}
524
Geoff Langf41a7152016-09-19 15:11:17 -0400525} // anonymous namespace
526
Brandon Jonesd1049182018-03-28 10:02:20 -0700527void SetRobustLengthParam(GLsizei *length, GLsizei value)
528{
529 if (length)
530 {
531 *length = value;
532 }
533}
534
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500535bool IsETC2EACFormat(const GLenum format)
536{
537 // ES 3.1, Table 8.19
538 switch (format)
539 {
540 case GL_COMPRESSED_R11_EAC:
541 case GL_COMPRESSED_SIGNED_R11_EAC:
542 case GL_COMPRESSED_RG11_EAC:
543 case GL_COMPRESSED_SIGNED_RG11_EAC:
544 case GL_COMPRESSED_RGB8_ETC2:
545 case GL_COMPRESSED_SRGB8_ETC2:
546 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
547 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
548 case GL_COMPRESSED_RGBA8_ETC2_EAC:
549 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
550 return true;
551
552 default:
553 return false;
554 }
555}
556
Jamie Madill5b772312018-03-08 20:28:32 -0500557bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400558{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800559 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400560 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800561 case TextureType::_2D:
562 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800563 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400564
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800565 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400566 return context->getExtensions().textureRectangle;
567
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800568 case TextureType::_3D:
569 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800570 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500571
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800572 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800573 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400574
He Yunchaoced53ae2016-11-29 15:00:51 +0800575 default:
576 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500577 }
Jamie Madill35d15012013-10-07 10:46:37 -0400578}
579
Jamie Madill5b772312018-03-08 20:28:32 -0500580bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500581{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800582 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500583 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800584 case TextureType::_2D:
585 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500586 return true;
587
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800588 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400589 return context->getExtensions().textureRectangle;
590
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500591 default:
592 return false;
593 }
594}
595
Jamie Madill5b772312018-03-08 20:28:32 -0500596bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500597{
598 switch (target)
599 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800600 case TextureType::_3D:
601 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300602 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500603
604 default:
605 return false;
606 }
607}
608
Ian Ewellbda75592016-04-18 17:25:54 -0400609// Most texture GL calls are not compatible with external textures, so we have a separate validation
610// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500611bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400612{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800613 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400614 (context->getExtensions().eglImageExternal ||
615 context->getExtensions().eglStreamConsumerExternal);
616}
617
Shannon Woods4dfed832014-03-17 20:03:39 -0400618// This function differs from ValidTextureTarget in that the target must be
619// usable as the destination of a 2D operation-- so a cube face is valid, but
620// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400621// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500622bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400623{
624 switch (target)
625 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800626 case TextureTarget::_2D:
627 case TextureTarget::CubeMapNegativeX:
628 case TextureTarget::CubeMapNegativeY:
629 case TextureTarget::CubeMapNegativeZ:
630 case TextureTarget::CubeMapPositiveX:
631 case TextureTarget::CubeMapPositiveY:
632 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800633 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800634 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400635 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800636 default:
637 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500638 }
639}
640
Jamie Madill5b772312018-03-08 20:28:32 -0500641bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -0400642 GLenum mode,
643 GLsizei count,
644 GLenum type,
645 const GLvoid *indices,
646 GLsizei primcount)
647{
648 if (primcount < 0)
649 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700650 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400651 return false;
652 }
653
654 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
655 {
656 return false;
657 }
658
Jamie Madill9fdaa492018-02-16 10:52:11 -0500659 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400660}
661
662bool ValidateDrawArraysInstancedBase(Context *context,
663 GLenum mode,
664 GLint first,
665 GLsizei count,
666 GLsizei primcount)
667{
668 if (primcount < 0)
669 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700670 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400671 return false;
672 }
673
674 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
675 {
676 return false;
677 }
678
Jamie Madill9fdaa492018-02-16 10:52:11 -0500679 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400680}
681
Jamie Madill5b772312018-03-08 20:28:32 -0500682bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400683{
684 // Verify there is at least one active attribute with a divisor of zero
685 const State &state = context->getGLState();
686
687 Program *program = state.getProgram();
688
689 const auto &attribs = state.getVertexArray()->getVertexAttributes();
690 const auto &bindings = state.getVertexArray()->getVertexBindings();
691 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
692 {
693 const VertexAttribute &attrib = attribs[attributeIndex];
694 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300695 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400696 {
697 return true;
698 }
699 }
700
Brandon Jonesafa75152017-07-21 13:11:29 -0700701 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400702 return false;
703}
704
Jamie Madill5b772312018-03-08 20:28:32 -0500705bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500706{
707 switch (target)
708 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800709 case TextureType::_3D:
710 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800711 return true;
712 default:
713 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400714 }
715}
716
Jamie Madill5b772312018-03-08 20:28:32 -0500717bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800718{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800719 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800720 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800721 case TextureType::_2D:
722 case TextureType::_2DArray:
723 case TextureType::_2DMultisample:
724 case TextureType::CubeMap:
725 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800726 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800727 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400728 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800729 default:
730 return false;
731 }
732}
733
Jamie Madill5b772312018-03-08 20:28:32 -0500734bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500735{
He Yunchaoced53ae2016-11-29 15:00:51 +0800736 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
737 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400738 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500739
740 switch (target)
741 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800742 case GL_FRAMEBUFFER:
743 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400744
He Yunchaoced53ae2016-11-29 15:00:51 +0800745 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800746 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400747 return (context->getExtensions().framebufferBlit ||
748 context->getClientMajorVersion() >= 3);
749
He Yunchaoced53ae2016-11-29 15:00:51 +0800750 default:
751 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500752 }
753}
754
Jamie Madill5b772312018-03-08 20:28:32 -0500755bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400756{
Jamie Madillc29968b2016-01-20 11:17:23 -0500757 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400758 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800759 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400760 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800761 case TextureType::_2D:
762 case TextureType::_2DArray:
763 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500764 maxDimension = caps.max2DTextureSize;
765 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800766 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800767 maxDimension = caps.maxCubeMapTextureSize;
768 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800769 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400770 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800771 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800772 maxDimension = caps.max3DTextureSize;
773 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800774 default:
775 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400776 }
777
Brandon Jones6cad5662017-06-14 13:25:13 -0700778 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400779}
780
Jamie Madill5b772312018-03-08 20:28:32 -0500781bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800782 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700783 GLint level,
784 GLsizei width,
785 GLsizei height,
786 GLsizei depth,
787 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400788{
Brandon Jones6cad5662017-06-14 13:25:13 -0700789 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400790 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700791 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400792 return false;
793 }
Austin Kinross08528e12015-10-07 16:24:40 -0700794 // TexSubImage parameters can be NPOT without textureNPOT extension,
795 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500796 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500797 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500798 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400799 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400800 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700801 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400802 return false;
803 }
804
805 if (!ValidMipLevel(context, target, level))
806 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700807 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400808 return false;
809 }
810
811 return true;
812}
813
Geoff Lang966c9402017-04-18 12:38:27 -0400814bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
815{
816 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
817 (size % blockSize == 0);
818}
819
Jamie Madill5b772312018-03-08 20:28:32 -0500820bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500821 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400822 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500823 GLsizei width,
824 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400825{
Geoff Langca271392017-04-05 12:30:00 -0400826 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400827 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400828 {
829 return false;
830 }
831
Geoff Lang966c9402017-04-18 12:38:27 -0400832 if (width < 0 || height < 0)
833 {
834 return false;
835 }
836
837 if (CompressedTextureFormatRequiresExactSize(internalFormat))
838 {
839 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
840 // block size for level 0 but WebGL disallows this.
841 bool smallerThanBlockSizeAllowed =
842 level > 0 || !context->getExtensions().webglCompatibility;
843
844 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
845 smallerThanBlockSizeAllowed) ||
846 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
847 smallerThanBlockSizeAllowed))
848 {
849 return false;
850 }
851 }
852
853 return true;
854}
855
Jamie Madill5b772312018-03-08 20:28:32 -0500856bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400857 GLenum internalFormat,
858 GLint xoffset,
859 GLint yoffset,
860 GLsizei width,
861 GLsizei height,
862 size_t textureWidth,
863 size_t textureHeight)
864{
865 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
866 if (!formatInfo.compressed)
867 {
868 return false;
869 }
870
Geoff Lang44ff5a72017-02-03 15:15:43 -0500871 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400872 {
873 return false;
874 }
875
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500876 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400877 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500878 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400879 yoffset % formatInfo.compressedBlockHeight != 0)
880 {
881 return false;
882 }
883
884 // Allowed to either have data that is a multiple of block size or is smaller than the block
885 // size but fills the entire mip
886 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
887 static_cast<size_t>(width) == textureWidth &&
888 static_cast<size_t>(height) == textureHeight;
889 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
890 (height % formatInfo.compressedBlockHeight) == 0;
891 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400892 {
893 return false;
894 }
895 }
896
Geoff Langd4f180b2013-09-24 13:57:44 -0400897 return true;
898}
899
Jamie Madill5b772312018-03-08 20:28:32 -0500900bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800901 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400902 GLsizei width,
903 GLsizei height,
904 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400905 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400906 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400907 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400908 GLsizei imageSize)
909{
Corentin Wallez336129f2017-10-17 15:55:40 -0400910 gl::Buffer *pixelUnpackBuffer =
911 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400912 if (pixelUnpackBuffer == nullptr && imageSize < 0)
913 {
914 // Checks are not required
915 return true;
916 }
917
918 // ...the data would be unpacked from the buffer object such that the memory reads required
919 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400920 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
921 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400922 const gl::Extents size(width, height, depth);
923 const auto &unpack = context->getGLState().getUnpackState();
924
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800925 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Geoff Langff5b2d52016-09-07 11:32:23 -0400926 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
927 if (endByteOrErr.isError())
928 {
929 context->handleError(endByteOrErr.getError());
930 return false;
931 }
932
933 GLuint endByte = endByteOrErr.getResult();
934
935 if (pixelUnpackBuffer)
936 {
937 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
938 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
939 checkedEndByte += checkedOffset;
940
941 if (!checkedEndByte.IsValid() ||
942 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
943 {
944 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500945 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -0400946 return false;
947 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800948 if (context->getExtensions().webglCompatibility &&
949 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
950 {
951 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
952 PixelUnpackBufferBoundForTransformFeedback);
953 return false;
954 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400955 }
956 else
957 {
958 ASSERT(imageSize >= 0);
959 if (pixels == nullptr && imageSize != 0)
960 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500961 context->handleError(InvalidOperation()
962 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400963 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400964 }
965
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400966 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400967 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500968 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400969 return false;
970 }
971 }
972
973 return true;
974}
975
Geoff Lang37dde692014-01-31 16:34:54 -0500976bool ValidQueryType(const Context *context, GLenum queryType)
977{
He Yunchaoced53ae2016-11-29 15:00:51 +0800978 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
979 "GL extension enums not equal.");
980 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
981 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -0500982
983 switch (queryType)
984 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800985 case GL_ANY_SAMPLES_PASSED:
986 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400987 return context->getClientMajorVersion() >= 3 ||
988 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +0800989 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
990 return (context->getClientMajorVersion() >= 3);
991 case GL_TIME_ELAPSED_EXT:
992 return context->getExtensions().disjointTimerQuery;
993 case GL_COMMANDS_COMPLETED_CHROMIUM:
994 return context->getExtensions().syncQuery;
Jiawei Shaod2fa07e2018-03-15 09:20:25 +0800995 case GL_PRIMITIVES_GENERATED_EXT:
996 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +0800997 default:
998 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500999 }
1000}
1001
Jamie Madill5b772312018-03-08 20:28:32 -05001002bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001003 GLenum type,
1004 GLboolean normalized,
1005 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001006 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001007 bool pureInteger)
1008{
1009 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001010 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1011 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1012 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1013 // parameter exceeds 255.
1014 constexpr GLsizei kMaxWebGLStride = 255;
1015 if (stride > kMaxWebGLStride)
1016 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001017 context->handleError(InvalidValue()
1018 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001019 return false;
1020 }
1021
1022 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1023 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1024 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1025 // or an INVALID_OPERATION error is generated.
1026 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1027 size_t typeSize = GetVertexFormatTypeSize(internalType);
1028
1029 ASSERT(isPow2(typeSize) && typeSize > 0);
1030 size_t sizeMask = (typeSize - 1);
1031 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1032 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001033 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001034 return false;
1035 }
1036
1037 if ((stride & sizeMask) != 0)
1038 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001039 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001040 return false;
1041 }
1042
1043 return true;
1044}
1045
Jamie Madill5b772312018-03-08 20:28:32 -05001046Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001047{
He Yunchaoced53ae2016-11-29 15:00:51 +08001048 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1049 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1050 // or program object and INVALID_OPERATION if the provided name identifies an object
1051 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001052
Dian Xiang769769a2015-09-09 15:20:08 -07001053 Program *validProgram = context->getProgram(id);
1054
1055 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001056 {
Dian Xiang769769a2015-09-09 15:20:08 -07001057 if (context->getShader(id))
1058 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001059 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001060 }
1061 else
1062 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001063 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001064 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001065 }
Dian Xiang769769a2015-09-09 15:20:08 -07001066
1067 return validProgram;
1068}
1069
Jamie Madill5b772312018-03-08 20:28:32 -05001070Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001071{
1072 // See ValidProgram for spec details.
1073
1074 Shader *validShader = context->getShader(id);
1075
1076 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001077 {
Dian Xiang769769a2015-09-09 15:20:08 -07001078 if (context->getProgram(id))
1079 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001080 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001081 }
1082 else
1083 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001084 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001085 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001086 }
Dian Xiang769769a2015-09-09 15:20:08 -07001087
1088 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001089}
1090
Geoff Langb1196682014-07-23 13:47:29 -04001091bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001092{
Geoff Langfa125c92017-10-24 13:01:46 -04001093 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001094 {
Geoff Langfa125c92017-10-24 13:01:46 -04001095 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1096 {
1097 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1098 return false;
1099 }
Jamie Madillb4472272014-07-03 10:38:55 -04001100
Geoff Langfa125c92017-10-24 13:01:46 -04001101 // Color attachment 0 is validated below because it is always valid
1102 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001103 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001104 {
Geoff Langfa125c92017-10-24 13:01:46 -04001105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001106 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001107 }
1108 }
1109 else
1110 {
1111 switch (attachment)
1112 {
Geoff Langfa125c92017-10-24 13:01:46 -04001113 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001114 case GL_DEPTH_ATTACHMENT:
1115 case GL_STENCIL_ATTACHMENT:
1116 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001117
He Yunchaoced53ae2016-11-29 15:00:51 +08001118 case GL_DEPTH_STENCIL_ATTACHMENT:
1119 if (!context->getExtensions().webglCompatibility &&
1120 context->getClientMajorVersion() < 3)
1121 {
Geoff Langfa125c92017-10-24 13:01:46 -04001122 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001123 return false;
1124 }
1125 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001126
He Yunchaoced53ae2016-11-29 15:00:51 +08001127 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001128 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001129 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001130 }
1131 }
1132
1133 return true;
1134}
1135
Jamie Madill5b772312018-03-08 20:28:32 -05001136bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001137 GLenum target,
1138 GLsizei samples,
1139 GLenum internalformat,
1140 GLsizei width,
1141 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001142{
1143 switch (target)
1144 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001145 case GL_RENDERBUFFER:
1146 break;
1147 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001148 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001149 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001150 }
1151
1152 if (width < 0 || height < 0 || samples < 0)
1153 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001154 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001155 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001156 }
1157
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001158 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1159 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1160
1161 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001162 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001163 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001164 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001165 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001166 }
1167
1168 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1169 // 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 -08001170 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001171 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1172 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001173 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001174 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001175 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001176 }
1177
Geoff Langaae65a42014-05-26 12:43:44 -04001178 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001179 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001180 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001181 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001182 }
1183
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001184 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001185 if (handle == 0)
1186 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001187 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001188 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001189 }
1190
1191 return true;
1192}
1193
He Yunchaoced53ae2016-11-29 15:00:51 +08001194bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1195 GLenum target,
1196 GLenum attachment,
1197 GLenum renderbuffertarget,
1198 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001199{
Geoff Lange8afa902017-09-27 15:00:43 -04001200 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001201 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001202 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001203 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001204 }
1205
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001206 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001207
Jamie Madill84115c92015-04-23 15:00:07 -04001208 ASSERT(framebuffer);
1209 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001210 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001211 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001212 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001213 }
1214
Jamie Madillb4472272014-07-03 10:38:55 -04001215 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001216 {
Jamie Madillb4472272014-07-03 10:38:55 -04001217 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001218 }
1219
Jamie Madillab9d82c2014-01-21 16:38:14 -05001220 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1221 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1222 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1223 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1224 if (renderbuffer != 0)
1225 {
1226 if (!context->getRenderbuffer(renderbuffer))
1227 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001228 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001229 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001230 }
1231 }
1232
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001233 return true;
1234}
1235
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001236bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001237 GLint srcX0,
1238 GLint srcY0,
1239 GLint srcX1,
1240 GLint srcY1,
1241 GLint dstX0,
1242 GLint dstY0,
1243 GLint dstX1,
1244 GLint dstY1,
1245 GLbitfield mask,
1246 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001247{
1248 switch (filter)
1249 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001250 case GL_NEAREST:
1251 break;
1252 case GL_LINEAR:
1253 break;
1254 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001255 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001256 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001257 }
1258
1259 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1260 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001261 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001262 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001263 }
1264
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001265 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1266 // color buffer, leaving only nearest being unfiltered from above
1267 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1268 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001269 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001270 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001271 }
1272
Jamie Madill51f40ec2016-06-15 14:06:00 -04001273 const auto &glState = context->getGLState();
1274 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1275 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001276
1277 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001278 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001279 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001280 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001281 }
1282
Jamie Madille98b1b52018-03-08 09:47:23 -05001283 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madill48faf802014-11-06 15:27:22 -05001284 {
Jamie Madill48faf802014-11-06 15:27:22 -05001285 return false;
1286 }
1287
Jamie Madille98b1b52018-03-08 09:47:23 -05001288 if (!ValidateFramebufferComplete(context, drawFramebuffer, true))
Jamie Madill48faf802014-11-06 15:27:22 -05001289 {
Jamie Madill48faf802014-11-06 15:27:22 -05001290 return false;
1291 }
1292
Qin Jiajiaaef92162018-02-27 13:51:44 +08001293 if (readFramebuffer->id() == drawFramebuffer->id())
1294 {
1295 context->handleError(InvalidOperation());
1296 return false;
1297 }
1298
Jamie Madille98b1b52018-03-08 09:47:23 -05001299 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001300 {
Geoff Langb1196682014-07-23 13:47:29 -04001301 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001302 }
1303
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001304 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1305
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001306 if (mask & GL_COLOR_BUFFER_BIT)
1307 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001308 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001309 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001310
He Yunchao66a41a22016-12-15 16:45:05 +08001311 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001312 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001313 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001314
Geoff Langa15472a2015-08-11 11:48:03 -04001315 for (size_t drawbufferIdx = 0;
1316 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001317 {
Geoff Langa15472a2015-08-11 11:48:03 -04001318 const FramebufferAttachment *attachment =
1319 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1320 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001321 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001322 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001323
Geoff Langb2f3d052013-08-13 12:49:27 -04001324 // The GL ES 3.0.2 spec (pg 193) states that:
1325 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001326 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1327 // as well
1328 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1329 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001330 // Changes with EXT_color_buffer_float:
1331 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001332 GLenum readComponentType = readFormat.info->componentType;
1333 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001334 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001335 readComponentType == GL_SIGNED_NORMALIZED);
1336 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1337 drawComponentType == GL_SIGNED_NORMALIZED);
1338
1339 if (extensions.colorBufferFloat)
1340 {
1341 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1342 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1343
1344 if (readFixedOrFloat != drawFixedOrFloat)
1345 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001346 context->handleError(InvalidOperation()
1347 << "If the read buffer contains fixed-point or "
1348 "floating-point values, the draw buffer must "
1349 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001350 return false;
1351 }
1352 }
1353 else if (readFixedPoint != drawFixedPoint)
1354 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001355 context->handleError(InvalidOperation()
1356 << "If the read buffer contains fixed-point values, "
1357 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001358 return false;
1359 }
1360
1361 if (readComponentType == GL_UNSIGNED_INT &&
1362 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001363 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001364 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001365 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001366 }
1367
Jamie Madill6163c752015-12-07 16:32:59 -05001368 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001369 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001370 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001371 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001372 }
1373
Jamie Madilla3944d42016-07-22 22:13:26 -04001374 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001375 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001376 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001377 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001378 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001379 }
Geoff Lange4915782017-04-12 15:19:07 -04001380
1381 if (context->getExtensions().webglCompatibility &&
1382 *readColorBuffer == *attachment)
1383 {
1384 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001385 InvalidOperation()
1386 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001387 return false;
1388 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001389 }
1390 }
1391
Jamie Madilla3944d42016-07-22 22:13:26 -04001392 if ((readFormat.info->componentType == GL_INT ||
1393 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1394 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001395 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001396 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001397 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001398 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001399 }
He Yunchao66a41a22016-12-15 16:45:05 +08001400 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1401 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1402 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1403 // situation is an application error that would lead to a crash in ANGLE.
1404 else if (drawFramebuffer->hasEnabledDrawBuffer())
1405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001406 context->handleError(
1407 InvalidOperation()
1408 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001409 return false;
1410 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001411 }
1412
He Yunchaoced53ae2016-11-29 15:00:51 +08001413 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001414 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1415 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001416 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001417 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001418 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001419 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001420 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001421 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001422 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001423
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001424 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001425 {
Kenneth Russell69382852017-07-21 16:38:44 -04001426 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001427 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001428 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001429 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001430 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001431
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001432 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001433 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001434 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001435 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001436 }
Geoff Lange4915782017-04-12 15:19:07 -04001437
1438 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1439 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001440 context->handleError(
1441 InvalidOperation()
1442 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001443 return false;
1444 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001445 }
He Yunchao66a41a22016-12-15 16:45:05 +08001446 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1447 else if (drawBuffer)
1448 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001449 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1450 "depth/stencil attachment of a "
1451 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001452 return false;
1453 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001454 }
1455 }
1456
Martin Radeva3ed4572017-07-27 18:29:37 +03001457 // ANGLE_multiview, Revision 1:
1458 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1459 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1460 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1461 {
1462 context->handleError(InvalidFramebufferOperation()
1463 << "Attempt to read from a multi-view framebuffer.");
1464 return false;
1465 }
1466 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1467 {
1468 context->handleError(InvalidFramebufferOperation()
1469 << "Attempt to write to a multi-view framebuffer.");
1470 return false;
1471 }
1472
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001473 return true;
1474}
1475
Jamie Madill4928b7c2017-06-20 12:57:39 -04001476bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001477 GLint x,
1478 GLint y,
1479 GLsizei width,
1480 GLsizei height,
1481 GLenum format,
1482 GLenum type,
1483 GLsizei bufSize,
1484 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001485 GLsizei *columns,
1486 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001487 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001488{
1489 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001490 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001491 return false;
1492 }
1493
Brandon Jonesd1049182018-03-28 10:02:20 -07001494 GLsizei writeLength = 0;
1495 GLsizei writeColumns = 0;
1496 GLsizei writeRows = 0;
1497
1498 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1499 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001500 {
Geoff Langb1196682014-07-23 13:47:29 -04001501 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001502 }
1503
Brandon Jonesd1049182018-03-28 10:02:20 -07001504 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001505 {
Geoff Langb1196682014-07-23 13:47:29 -04001506 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001507 }
1508
Brandon Jonesd1049182018-03-28 10:02:20 -07001509 SetRobustLengthParam(length, writeLength);
1510 SetRobustLengthParam(columns, writeColumns);
1511 SetRobustLengthParam(rows, writeRows);
1512
Jamie Madillc29968b2016-01-20 11:17:23 -05001513 return true;
1514}
1515
1516bool ValidateReadnPixelsEXT(Context *context,
1517 GLint x,
1518 GLint y,
1519 GLsizei width,
1520 GLsizei height,
1521 GLenum format,
1522 GLenum type,
1523 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001524 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001525{
1526 if (bufSize < 0)
1527 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001528 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001529 return false;
1530 }
1531
Geoff Lang62fce5b2016-09-30 10:46:35 -04001532 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001533 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001534}
Jamie Madill26e91952014-03-05 15:01:27 -05001535
Jamie Madill4928b7c2017-06-20 12:57:39 -04001536bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001537 GLint x,
1538 GLint y,
1539 GLsizei width,
1540 GLsizei height,
1541 GLenum format,
1542 GLenum type,
1543 GLsizei bufSize,
1544 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001545 GLsizei *columns,
1546 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001547 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001548{
Brandon Jonesd1049182018-03-28 10:02:20 -07001549 GLsizei writeLength = 0;
1550 GLsizei writeColumns = 0;
1551 GLsizei writeRows = 0;
1552
Geoff Lang62fce5b2016-09-30 10:46:35 -04001553 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001554 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001555 return false;
1556 }
1557
Brandon Jonesd1049182018-03-28 10:02:20 -07001558 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1559 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001560 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001561 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001562 }
1563
Brandon Jonesd1049182018-03-28 10:02:20 -07001564 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001565 {
1566 return false;
1567 }
1568
Brandon Jonesd1049182018-03-28 10:02:20 -07001569 SetRobustLengthParam(length, writeLength);
1570 SetRobustLengthParam(columns, writeColumns);
1571 SetRobustLengthParam(rows, writeRows);
1572
Geoff Lang62fce5b2016-09-30 10:46:35 -04001573 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001574}
1575
Jamie Madillf0e04492017-08-26 15:28:42 -04001576bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001577{
1578 if (!context->getExtensions().occlusionQueryBoolean &&
1579 !context->getExtensions().disjointTimerQuery)
1580 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001581 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001582 return false;
1583 }
1584
Olli Etuaho41997e72016-03-10 13:38:39 +02001585 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001586}
1587
Jamie Madillf0e04492017-08-26 15:28:42 -04001588bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001589{
1590 if (!context->getExtensions().occlusionQueryBoolean &&
1591 !context->getExtensions().disjointTimerQuery)
1592 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001593 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001594 return false;
1595 }
1596
Olli Etuaho41997e72016-03-10 13:38:39 +02001597 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001598}
1599
Jamie Madillf0e04492017-08-26 15:28:42 -04001600bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1601{
1602 if (!context->getExtensions().occlusionQueryBoolean &&
1603 !context->getExtensions().disjointTimerQuery)
1604 {
1605 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1606 return false;
1607 }
1608
1609 return true;
1610}
1611
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001612bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001613{
1614 if (!ValidQueryType(context, target))
1615 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001616 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001617 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001618 }
1619
1620 if (id == 0)
1621 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001622 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001623 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001624 }
1625
1626 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1627 // of zero, if the active query object name for <target> is non-zero (for the
1628 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1629 // the active query for either target is non-zero), if <id> is the name of an
1630 // existing query object whose type does not match <target>, or if <id> is the
1631 // active query object name for any query type, the error INVALID_OPERATION is
1632 // generated.
1633
1634 // Ensure no other queries are active
1635 // NOTE: If other queries than occlusion are supported, we will need to check
1636 // separately that:
1637 // a) The query ID passed is not the current active query for any target/type
1638 // b) There are no active queries for the requested target (and in the case
1639 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1640 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001641
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001642 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001643 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001644 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001645 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001646 }
1647
1648 Query *queryObject = context->getQuery(id, true, target);
1649
1650 // check that name was obtained with glGenQueries
1651 if (!queryObject)
1652 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001653 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001654 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001655 }
1656
1657 // check for type mismatch
1658 if (queryObject->getType() != target)
1659 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001660 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001661 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001662 }
1663
1664 return true;
1665}
1666
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001667bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1668{
1669 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001670 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001671 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001672 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001673 return false;
1674 }
1675
1676 return ValidateBeginQueryBase(context, target, id);
1677}
1678
1679bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001680{
1681 if (!ValidQueryType(context, target))
1682 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001683 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001684 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001685 }
1686
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001687 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001688
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001689 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001690 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001691 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001692 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001693 }
1694
Jamie Madill45c785d2014-05-13 14:09:34 -04001695 return true;
1696}
1697
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001698bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1699{
1700 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001701 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001702 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001703 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001704 return false;
1705 }
1706
1707 return ValidateEndQueryBase(context, target);
1708}
1709
1710bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1711{
1712 if (!context->getExtensions().disjointTimerQuery)
1713 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001714 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001715 return false;
1716 }
1717
1718 if (target != GL_TIMESTAMP_EXT)
1719 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001720 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001721 return false;
1722 }
1723
1724 Query *queryObject = context->getQuery(id, true, target);
1725 if (queryObject == nullptr)
1726 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001727 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001728 return false;
1729 }
1730
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001731 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001732 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001733 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001734 return false;
1735 }
1736
1737 return true;
1738}
1739
Geoff Lang2186c382016-10-14 10:54:54 -04001740bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001741{
Geoff Lang2186c382016-10-14 10:54:54 -04001742 if (numParams)
1743 {
1744 *numParams = 0;
1745 }
1746
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001747 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1748 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001749 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001750 return false;
1751 }
1752
1753 switch (pname)
1754 {
1755 case GL_CURRENT_QUERY_EXT:
1756 if (target == GL_TIMESTAMP_EXT)
1757 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001758 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001759 return false;
1760 }
1761 break;
1762 case GL_QUERY_COUNTER_BITS_EXT:
1763 if (!context->getExtensions().disjointTimerQuery ||
1764 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1765 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001766 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001767 return false;
1768 }
1769 break;
1770 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001771 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001772 return false;
1773 }
1774
Geoff Lang2186c382016-10-14 10:54:54 -04001775 if (numParams)
1776 {
1777 // All queries return only one value
1778 *numParams = 1;
1779 }
1780
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001781 return true;
1782}
1783
1784bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1785{
1786 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001787 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001788 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001789 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001790 return false;
1791 }
1792
Geoff Lang2186c382016-10-14 10:54:54 -04001793 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001794}
1795
Geoff Lang2186c382016-10-14 10:54:54 -04001796bool ValidateGetQueryivRobustANGLE(Context *context,
1797 GLenum target,
1798 GLenum pname,
1799 GLsizei bufSize,
1800 GLsizei *length,
1801 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001802{
Geoff Lang2186c382016-10-14 10:54:54 -04001803 if (!ValidateRobustEntryPoint(context, bufSize))
1804 {
1805 return false;
1806 }
1807
Brandon Jonesd1049182018-03-28 10:02:20 -07001808 GLsizei numParams = 0;
1809
1810 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001811 {
1812 return false;
1813 }
1814
Brandon Jonesd1049182018-03-28 10:02:20 -07001815 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001816 {
1817 return false;
1818 }
1819
Brandon Jonesd1049182018-03-28 10:02:20 -07001820 SetRobustLengthParam(length, numParams);
1821
Geoff Lang2186c382016-10-14 10:54:54 -04001822 return true;
1823}
1824
1825bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1826{
1827 if (numParams)
1828 {
1829 *numParams = 0;
1830 }
1831
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001832 Query *queryObject = context->getQuery(id, false, GL_NONE);
1833
1834 if (!queryObject)
1835 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001836 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001837 return false;
1838 }
1839
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001840 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001841 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001842 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001843 return false;
1844 }
1845
1846 switch (pname)
1847 {
1848 case GL_QUERY_RESULT_EXT:
1849 case GL_QUERY_RESULT_AVAILABLE_EXT:
1850 break;
1851
1852 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001853 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001854 return false;
1855 }
1856
Geoff Lang2186c382016-10-14 10:54:54 -04001857 if (numParams)
1858 {
1859 *numParams = 1;
1860 }
1861
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001862 return true;
1863}
1864
1865bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1866{
1867 if (!context->getExtensions().disjointTimerQuery)
1868 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001869 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001870 return false;
1871 }
Geoff Lang2186c382016-10-14 10:54:54 -04001872 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1873}
1874
1875bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1876 GLuint id,
1877 GLenum pname,
1878 GLsizei bufSize,
1879 GLsizei *length,
1880 GLint *params)
1881{
1882 if (!context->getExtensions().disjointTimerQuery)
1883 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001884 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001885 return false;
1886 }
1887
1888 if (!ValidateRobustEntryPoint(context, bufSize))
1889 {
1890 return false;
1891 }
1892
Brandon Jonesd1049182018-03-28 10:02:20 -07001893 GLsizei numParams = 0;
1894
1895 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001896 {
1897 return false;
1898 }
1899
Brandon Jonesd1049182018-03-28 10:02:20 -07001900 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001901 {
1902 return false;
1903 }
1904
Brandon Jonesd1049182018-03-28 10:02:20 -07001905 SetRobustLengthParam(length, numParams);
1906
Geoff Lang2186c382016-10-14 10:54:54 -04001907 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001908}
1909
1910bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1911{
1912 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001913 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001914 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001915 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001916 return false;
1917 }
Geoff Lang2186c382016-10-14 10:54:54 -04001918 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1919}
1920
1921bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1922 GLuint id,
1923 GLenum pname,
1924 GLsizei bufSize,
1925 GLsizei *length,
1926 GLuint *params)
1927{
1928 if (!context->getExtensions().disjointTimerQuery &&
1929 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1930 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001931 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001932 return false;
1933 }
1934
1935 if (!ValidateRobustEntryPoint(context, bufSize))
1936 {
1937 return false;
1938 }
1939
Brandon Jonesd1049182018-03-28 10:02:20 -07001940 GLsizei numParams = 0;
1941
1942 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001943 {
1944 return false;
1945 }
1946
Brandon Jonesd1049182018-03-28 10:02:20 -07001947 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001948 {
1949 return false;
1950 }
1951
Brandon Jonesd1049182018-03-28 10:02:20 -07001952 SetRobustLengthParam(length, numParams);
1953
Geoff Lang2186c382016-10-14 10:54:54 -04001954 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001955}
1956
1957bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1958{
1959 if (!context->getExtensions().disjointTimerQuery)
1960 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001961 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001962 return false;
1963 }
Geoff Lang2186c382016-10-14 10:54:54 -04001964 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1965}
1966
1967bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1968 GLuint id,
1969 GLenum pname,
1970 GLsizei bufSize,
1971 GLsizei *length,
1972 GLint64 *params)
1973{
1974 if (!context->getExtensions().disjointTimerQuery)
1975 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001976 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001977 return false;
1978 }
1979
1980 if (!ValidateRobustEntryPoint(context, bufSize))
1981 {
1982 return false;
1983 }
1984
Brandon Jonesd1049182018-03-28 10:02:20 -07001985 GLsizei numParams = 0;
1986
1987 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001988 {
1989 return false;
1990 }
1991
Brandon Jonesd1049182018-03-28 10:02:20 -07001992 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001993 {
1994 return false;
1995 }
1996
Brandon Jonesd1049182018-03-28 10:02:20 -07001997 SetRobustLengthParam(length, numParams);
1998
Geoff Lang2186c382016-10-14 10:54:54 -04001999 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002000}
2001
2002bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2003{
2004 if (!context->getExtensions().disjointTimerQuery)
2005 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002006 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002007 return false;
2008 }
Geoff Lang2186c382016-10-14 10:54:54 -04002009 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2010}
2011
2012bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2013 GLuint id,
2014 GLenum pname,
2015 GLsizei bufSize,
2016 GLsizei *length,
2017 GLuint64 *params)
2018{
2019 if (!context->getExtensions().disjointTimerQuery)
2020 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002021 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002022 return false;
2023 }
2024
2025 if (!ValidateRobustEntryPoint(context, bufSize))
2026 {
2027 return false;
2028 }
2029
Brandon Jonesd1049182018-03-28 10:02:20 -07002030 GLsizei numParams = 0;
2031
2032 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002033 {
2034 return false;
2035 }
2036
Brandon Jonesd1049182018-03-28 10:02:20 -07002037 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002038 {
2039 return false;
2040 }
2041
Brandon Jonesd1049182018-03-28 10:02:20 -07002042 SetRobustLengthParam(length, numParams);
2043
Geoff Lang2186c382016-10-14 10:54:54 -04002044 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002045}
2046
Jamie Madill5b772312018-03-08 20:28:32 -05002047bool ValidateUniformCommonBase(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002048 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002049 GLint location,
2050 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002051 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002052{
Jiajia Qin5451d532017-11-16 17:16:34 +08002053 // TODO(Jiajia): Add image uniform check in future.
2054 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002055 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002056 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002057 return false;
2058 }
2059
Jiajia Qin5451d532017-11-16 17:16:34 +08002060 if (!program)
2061 {
2062 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2063 return false;
2064 }
2065
2066 if (!program->isLinked())
2067 {
2068 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2069 return false;
2070 }
2071
2072 if (location == -1)
2073 {
2074 // Silently ignore the uniform command
2075 return false;
2076 }
2077
2078 const auto &uniformLocations = program->getUniformLocations();
2079 size_t castedLocation = static_cast<size_t>(location);
2080 if (castedLocation >= uniformLocations.size())
2081 {
2082 context->handleError(InvalidOperation() << "Invalid uniform location");
2083 return false;
2084 }
2085
2086 const auto &uniformLocation = uniformLocations[castedLocation];
2087 if (uniformLocation.ignored)
2088 {
2089 // Silently ignore the uniform command
2090 return false;
2091 }
2092
2093 if (!uniformLocation.used())
2094 {
2095 context->handleError(InvalidOperation());
2096 return false;
2097 }
2098
2099 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2100
2101 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2102 if (!uniform.isArray() && count > 1)
2103 {
2104 context->handleError(InvalidOperation());
2105 return false;
2106 }
2107
2108 *uniformOut = &uniform;
2109 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002110}
2111
Jamie Madill5b772312018-03-08 20:28:32 -05002112bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002113 GLenum uniformType,
2114 GLsizei count,
2115 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002116{
Jiajia Qin5451d532017-11-16 17:16:34 +08002117 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2118 // It is compatible with INT or BOOL.
2119 // Do these cheap tests first, for a little extra speed.
2120 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002121 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002122 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002123 }
2124
Jiajia Qin5451d532017-11-16 17:16:34 +08002125 if (IsSamplerType(uniformType))
2126 {
2127 // Check that the values are in range.
2128 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2129 for (GLsizei i = 0; i < count; ++i)
2130 {
2131 if (value[i] < 0 || value[i] >= max)
2132 {
2133 context->handleError(InvalidValue() << "sampler uniform value out of range");
2134 return false;
2135 }
2136 }
2137 return true;
2138 }
2139
2140 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2141 return false;
2142}
2143
Jamie Madill5b772312018-03-08 20:28:32 -05002144bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002145{
2146 // Check that the value type is compatible with uniform type.
2147 // Do the cheaper test first, for a little extra speed.
2148 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2149 {
2150 return true;
2151 }
2152
2153 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2154 return false;
2155}
2156
Jamie Madill5b772312018-03-08 20:28:32 -05002157bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002158{
2159 // Check that the value type is compatible with uniform type.
2160 if (valueType == uniformType)
2161 {
2162 return true;
2163 }
2164
2165 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2166 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002167}
2168
Jamie Madill5b772312018-03-08 20:28:32 -05002169bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002170{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002171 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002172 gl::Program *programObject = context->getGLState().getProgram();
2173 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2174 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002175}
2176
Jamie Madill5b772312018-03-08 20:28:32 -05002177bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002178{
2179 const LinkedUniform *uniform = nullptr;
2180 gl::Program *programObject = context->getGLState().getProgram();
2181 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2182 ValidateUniform1ivValue(context, uniform->type, count, value);
2183}
2184
Jamie Madill5b772312018-03-08 20:28:32 -05002185bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002186 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002187 GLint location,
2188 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002189 GLboolean transpose)
2190{
Geoff Lang92019432017-11-20 13:09:34 -05002191 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002193 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002194 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002195 }
2196
Jamie Madill62d31cb2015-09-11 13:25:51 -04002197 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002198 gl::Program *programObject = context->getGLState().getProgram();
2199 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2200 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002201}
2202
Jamie Madill5b772312018-03-08 20:28:32 -05002203bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002204{
2205 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2206 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002207 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002208 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002209 }
2210
Jamie Madill0af26e12015-03-05 19:54:33 -05002211 const Caps &caps = context->getCaps();
2212
Jamie Madill893ab082014-05-16 16:56:10 -04002213 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2214 {
2215 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2216
Jamie Madill0af26e12015-03-05 19:54:33 -05002217 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002218 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002219 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002220 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002221 }
2222 }
2223
2224 switch (pname)
2225 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002226 case GL_TEXTURE_BINDING_2D:
2227 case GL_TEXTURE_BINDING_CUBE_MAP:
2228 case GL_TEXTURE_BINDING_3D:
2229 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002230 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002231 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002232 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2233 if (!context->getExtensions().textureRectangle)
2234 {
2235 context->handleError(InvalidEnum()
2236 << "ANGLE_texture_rectangle extension not present");
2237 return false;
2238 }
2239 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002240 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2241 if (!context->getExtensions().eglStreamConsumerExternal &&
2242 !context->getExtensions().eglImageExternal)
2243 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002244 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2245 "nor GL_OES_EGL_image_external "
2246 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002247 return false;
2248 }
2249 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002250
He Yunchaoced53ae2016-11-29 15:00:51 +08002251 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2252 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002253 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002254 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2255 ASSERT(readFramebuffer);
2256
2257 if (!ValidateFramebufferComplete(context, readFramebuffer, false))
Jamie Madill893ab082014-05-16 16:56:10 -04002258 {
Geoff Langb1196682014-07-23 13:47:29 -04002259 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002260 }
2261
Jamie Madille98b1b52018-03-08 09:47:23 -05002262 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002263 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002264 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002265 return false;
2266 }
2267
Jamie Madille98b1b52018-03-08 09:47:23 -05002268 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002269 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002270 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002271 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002272 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002273 }
2274 }
2275 break;
2276
He Yunchaoced53ae2016-11-29 15:00:51 +08002277 default:
2278 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002279 }
2280
2281 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002282 if (*numParams == 0)
2283 {
2284 return false;
2285 }
2286
2287 return true;
2288}
2289
Brandon Jonesd1049182018-03-28 10:02:20 -07002290bool ValidateGetBooleanvRobustANGLE(Context *context,
2291 GLenum pname,
2292 GLsizei bufSize,
2293 GLsizei *length,
2294 GLboolean *params)
2295{
2296 GLenum nativeType;
2297 unsigned int numParams = 0;
2298
2299 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2300 {
2301 return false;
2302 }
2303
2304 SetRobustLengthParam(length, numParams);
2305
2306 return true;
2307}
2308
2309bool ValidateGetFloatvRobustANGLE(Context *context,
2310 GLenum pname,
2311 GLsizei bufSize,
2312 GLsizei *length,
2313 GLfloat *params)
2314{
2315 GLenum nativeType;
2316 unsigned int numParams = 0;
2317
2318 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2319 {
2320 return false;
2321 }
2322
2323 SetRobustLengthParam(length, numParams);
2324
2325 return true;
2326}
2327
2328bool ValidateGetIntegervRobustANGLE(Context *context,
2329 GLenum pname,
2330 GLsizei bufSize,
2331 GLsizei *length,
2332 GLint *data)
2333{
2334 GLenum nativeType;
2335 unsigned int numParams = 0;
2336
2337 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2338 {
2339 return false;
2340 }
2341
2342 SetRobustLengthParam(length, numParams);
2343
2344 return true;
2345}
2346
2347bool ValidateGetInteger64vRobustANGLE(Context *context,
2348 GLenum pname,
2349 GLsizei bufSize,
2350 GLsizei *length,
2351 GLint64 *data)
2352{
2353 GLenum nativeType;
2354 unsigned int numParams = 0;
2355
2356 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2357 {
2358 return false;
2359 }
2360
2361 if (nativeType == GL_INT_64_ANGLEX)
2362 {
2363 CastStateValues(context, nativeType, pname, numParams, data);
2364 return false;
2365 }
2366
2367 SetRobustLengthParam(length, numParams);
2368 return true;
2369}
2370
Jamie Madill5b772312018-03-08 20:28:32 -05002371bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002372 GLenum pname,
2373 GLsizei bufSize,
2374 GLenum *nativeType,
2375 unsigned int *numParams)
2376{
2377 if (!ValidateRobustEntryPoint(context, bufSize))
2378 {
2379 return false;
2380 }
2381
2382 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2383 {
2384 return false;
2385 }
2386
2387 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002388 {
2389 return false;
2390 }
2391
2392 return true;
2393}
2394
Jamie Madill5b772312018-03-08 20:28:32 -05002395bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002396 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002397 GLint level,
2398 GLenum internalformat,
2399 bool isSubImage,
2400 GLint xoffset,
2401 GLint yoffset,
2402 GLint zoffset,
2403 GLint x,
2404 GLint y,
2405 GLsizei width,
2406 GLsizei height,
2407 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002408 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002409{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002410 TextureType texType = TextureTargetToType(target);
2411
Brandon Jones6cad5662017-06-14 13:25:13 -07002412 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002413 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002414 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2415 return false;
2416 }
2417
2418 if (width < 0 || height < 0)
2419 {
2420 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002421 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002422 }
2423
He Yunchaoced53ae2016-11-29 15:00:51 +08002424 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2425 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002427 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002428 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002429 }
2430
2431 if (border != 0)
2432 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002433 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002434 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002435 }
2436
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002437 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002438 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002439 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002440 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002441 }
2442
Jamie Madille98b1b52018-03-08 09:47:23 -05002443 const gl::State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002444 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madille98b1b52018-03-08 09:47:23 -05002445 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madill560a8d82014-05-21 13:06:20 -04002446 {
Geoff Langb1196682014-07-23 13:47:29 -04002447 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002448 }
2449
Jamie Madille98b1b52018-03-08 09:47:23 -05002450 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002451 {
Geoff Langb1196682014-07-23 13:47:29 -04002452 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002453 }
2454
Martin Radev138064f2016-07-15 12:03:41 +03002455 if (readFramebuffer->getReadBufferState() == GL_NONE)
2456 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002457 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002458 return false;
2459 }
2460
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002461 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2462 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002463 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002464 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002465 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2466 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002467 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002468 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002469 return false;
2470 }
2471
Martin Radev04e2c3b2017-07-27 16:54:35 +03002472 // ANGLE_multiview spec, Revision 1:
2473 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2474 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2475 // is not NONE.
2476 if (source->getMultiviewLayout() != GL_NONE)
2477 {
2478 context->handleError(InvalidFramebufferOperation()
2479 << "The active read framebuffer object has multiview attachments.");
2480 return false;
2481 }
2482
Geoff Langaae65a42014-05-26 12:43:44 -04002483 const gl::Caps &caps = context->getCaps();
2484
Geoff Langaae65a42014-05-26 12:43:44 -04002485 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002486 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002487 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002488 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002489 maxDimension = caps.max2DTextureSize;
2490 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002491
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002492 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002493 maxDimension = caps.maxCubeMapTextureSize;
2494 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002495
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002496 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002497 maxDimension = caps.maxRectangleTextureSize;
2498 break;
2499
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002500 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002501 maxDimension = caps.max2DTextureSize;
2502 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002503
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002504 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002505 maxDimension = caps.max3DTextureSize;
2506 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002507
He Yunchaoced53ae2016-11-29 15:00:51 +08002508 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002509 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002510 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002511 }
2512
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002513 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002514 if (!texture)
2515 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002516 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002517 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002518 }
2519
Geoff Lang69cce582015-09-17 13:20:36 -04002520 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002521 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002522 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002523 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002524 }
2525
Geoff Langca271392017-04-05 12:30:00 -04002526 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002527 isSubImage ? *texture->getFormat(target, level).info
2528 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002529
Geoff Lang966c9402017-04-18 12:38:27 -04002530 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002531 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002532 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002533 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002534 }
2535
2536 if (isSubImage)
2537 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002538 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2539 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2540 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002541 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002542 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002543 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002544 }
2545 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002546 else
2547 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002548 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002549 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002550 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002551 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002552 }
2553
Geoff Langeb66a6e2016-10-31 13:06:12 -04002554 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002555 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002556 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002557 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002558 }
2559
2560 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002561 if (static_cast<int>(width) > maxLevelDimension ||
2562 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002563 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002564 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002565 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002566 }
2567 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002568
Jamie Madill0c8abca2016-07-22 20:21:26 -04002569 if (textureFormatOut)
2570 {
2571 *textureFormatOut = texture->getFormat(target, level);
2572 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002573
2574 // Detect texture copying feedback loops for WebGL.
2575 if (context->getExtensions().webglCompatibility)
2576 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002577 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002578 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002579 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002580 return false;
2581 }
2582 }
2583
Jamie Madill560a8d82014-05-21 13:06:20 -04002584 return true;
2585}
2586
Jamie Madill5b772312018-03-08 20:28:32 -05002587bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002588{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002589 const Extensions &extensions = context->getExtensions();
2590
Jamie Madill1aeb1312014-06-20 13:21:25 -04002591 switch (mode)
2592 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002593 case GL_POINTS:
2594 case GL_LINES:
2595 case GL_LINE_LOOP:
2596 case GL_LINE_STRIP:
2597 case GL_TRIANGLES:
2598 case GL_TRIANGLE_STRIP:
2599 case GL_TRIANGLE_FAN:
2600 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002601
2602 case GL_LINES_ADJACENCY_EXT:
2603 case GL_LINE_STRIP_ADJACENCY_EXT:
2604 case GL_TRIANGLES_ADJACENCY_EXT:
2605 case GL_TRIANGLE_STRIP_ADJACENCY_EXT:
2606 if (!extensions.geometryShader)
2607 {
2608 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2609 return false;
2610 }
2611 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002612 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002613 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002614 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002615 }
2616
Jamie Madill250d33f2014-06-06 17:09:03 -04002617 if (count < 0)
2618 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002619 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002620 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002621 }
2622
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002623 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002624
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002625 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2626 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2627 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2628 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002629 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002630 // Check for mapped buffers
2631 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002632 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002633 {
2634 context->handleError(InvalidOperation());
2635 return false;
2636 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002637 }
2638
Jamie Madillcbcde722017-01-06 14:50:00 -05002639 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2640 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002641 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002642 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002643 {
Ken Russellb9f92502018-01-27 19:00:26 -08002644 ASSERT(framebuffer);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002645 const FramebufferAttachment *dsAttachment =
2646 framebuffer->getStencilOrDepthStencilAttachment();
Ken Russellb9f92502018-01-27 19:00:26 -08002647 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2648 ASSERT(stencilBits <= 8);
2649
Jinyoung Hur85769f02015-10-20 17:08:44 -04002650 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Ken Russellb9f92502018-01-27 19:00:26 -08002651 if (depthStencilState.stencilTest && stencilBits > 0)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002652 {
Ken Russellb9f92502018-01-27 19:00:26 -08002653 GLuint maxStencilValue = (1 << stencilBits) - 1;
2654
2655 bool differentRefs =
2656 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2657 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2658 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2659 (depthStencilState.stencilBackWritemask & maxStencilValue);
2660 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2661 (depthStencilState.stencilBackMask & maxStencilValue);
2662
2663 if (differentRefs || differentWritemasks || differentMasks)
Jamie Madillcbcde722017-01-06 14:50:00 -05002664 {
Ken Russellb9f92502018-01-27 19:00:26 -08002665 if (!extensions.webglCompatibility)
2666 {
2667 ERR() << "This ANGLE implementation does not support separate front/back "
2668 "stencil writemasks, reference values, or stencil mask values.";
2669 }
2670 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
2671 return false;
Jamie Madillcbcde722017-01-06 14:50:00 -05002672 }
Geoff Lang3a86ad32015-09-01 11:47:05 -04002673 }
Jamie Madillac528012014-06-20 13:21:23 -04002674 }
2675
Jamie Madille98b1b52018-03-08 09:47:23 -05002676 if (!ValidateFramebufferComplete(context, framebuffer, true))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002677 {
Geoff Langb1196682014-07-23 13:47:29 -04002678 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002679 }
2680
Geoff Lang7dd2e102014-11-10 15:19:26 -05002681 gl::Program *program = state.getProgram();
2682 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002683 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002684 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002685 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002686 }
2687
Yunchao Hecddcb592017-11-13 15:27:35 +08002688 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2689 // vertex shader stage or fragment shader stage is a undefined behaviour.
2690 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2691 // produce undefined result.
Jiawei Shao385b3e02018-03-21 09:43:28 +08002692 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2693 !program->hasLinkedShaderStage(ShaderType::Fragment))
Yunchao Hecddcb592017-11-13 15:27:35 +08002694 {
2695 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2696 "vertex shader stage or fragment shader stage.");
2697 return false;
2698 }
2699
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002700 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002701 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002702 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002703 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002704 }
2705
Martin Radevffe754b2017-07-31 10:38:07 +03002706 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002707 {
Martin Radevda8e2572017-09-12 17:21:16 +03002708 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002709 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002710 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002711 {
2712 context->handleError(InvalidOperation() << "The number of views in the active program "
2713 "and draw framebuffer does not match.");
2714 return false;
2715 }
Martin Radev7e69f762017-07-27 14:54:13 +03002716
2717 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2718 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2719 framebufferNumViews > 1)
2720 {
2721 context->handleError(InvalidOperation()
2722 << "There is an active transform feedback object "
2723 "when the number of views in the active draw "
2724 "framebuffer is greater than 1.");
2725 return false;
2726 }
Martin Radevffe754b2017-07-31 10:38:07 +03002727
2728 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2729 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2730 {
2731 context->handleError(InvalidOperation() << "There is an active query for target "
2732 "GL_TIME_ELAPSED_EXT when the number of "
2733 "views in the active draw framebuffer is "
2734 "greater than 1.");
2735 return false;
2736 }
Martin Radev7cf61662017-07-26 17:10:53 +03002737 }
2738
Jiawei Shaofccebff2018-03-08 13:51:02 +08002739 // Do geometry shader specific validations
Jiawei Shao385b3e02018-03-21 09:43:28 +08002740 if (program->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shaofccebff2018-03-08 13:51:02 +08002741 {
2742 if (!IsCompatibleDrawModeWithGeometryShader(mode,
2743 program->getGeometryShaderInputPrimitiveType()))
2744 {
2745 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2746 IncompatibleDrawModeAgainstGeometryShader);
2747 return false;
2748 }
2749 }
2750
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002751 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002752 for (unsigned int uniformBlockIndex = 0;
2753 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002754 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002755 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002756 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002757 const OffsetBindingPointer<Buffer> &uniformBuffer =
2758 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002759
Geoff Lang5d124a62015-09-15 13:03:27 -04002760 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002761 {
2762 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002763 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002764 InvalidOperation()
2765 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002766 return false;
2767 }
2768
James Darpinian30b604d2018-03-12 17:26:57 -07002769 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
Jamie Madill62d31cb2015-09-11 13:25:51 -04002770 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002771 {
2772 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002773 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002774 InvalidOperation()
2775 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002776 return false;
2777 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002778
2779 if (extensions.webglCompatibility &&
2780 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2781 {
2782 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2783 UniformBufferBoundForTransformFeedback);
2784 return false;
2785 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002786 }
2787
Geoff Lange0cff192017-05-30 13:04:56 -04002788 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002789 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002790 {
James Darpiniane8a93c62018-01-04 18:02:24 -08002791 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2792 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2793 transformFeedbackObject->buffersBoundForOtherUse())
2794 {
2795 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferDoubleBound);
2796 return false;
2797 }
Geoff Lange0cff192017-05-30 13:04:56 -04002798 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002799 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2800 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002801 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002802 return false;
2803 }
Geoff Lange0cff192017-05-30 13:04:56 -04002804
Geoff Lang9ab5b822017-05-30 16:19:23 -04002805 // Detect that the vertex shader input types match the attribute types
2806 if (!ValidateVertexShaderAttributeTypeMatch(context))
2807 {
2808 return false;
2809 }
2810
Geoff Lange0cff192017-05-30 13:04:56 -04002811 // Detect that the color buffer types match the fragment shader output types
2812 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2813 {
2814 return false;
2815 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002816 }
2817
Jamie Madill9fdaa492018-02-16 10:52:11 -05002818 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002819}
2820
Jamie Madill5b772312018-03-08 20:28:32 -05002821bool ValidateDrawArraysCommon(Context *context,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002822 GLenum mode,
2823 GLint first,
2824 GLsizei count,
2825 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002826{
Jamie Madillfd716582014-06-06 17:09:04 -04002827 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002828 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002829 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002830 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002831 }
2832
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002833 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002834 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002835 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002836 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002837 {
James Darpinian30b604d2018-03-12 17:26:57 -07002838 if (curTransformFeedback->getPrimitiveMode() != mode)
2839 {
2840 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
2841 // that does not match the current transform feedback object's draw mode (if transform
2842 // feedback
2843 // is active), (3.0.2, section 2.14, pg 86)
2844 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2845 return false;
2846 }
2847
2848 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2849 {
2850 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2851 return false;
2852 }
Jamie Madillfd716582014-06-06 17:09:04 -04002853 }
2854
Jiajia Qind9671222016-11-29 16:30:31 +08002855 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002856 {
2857 return false;
2858 }
2859
Corentin Wallez71168a02016-12-19 15:11:18 -08002860 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002861 // - first < 0 has been checked as an error condition.
2862 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002863 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002864 ASSERT(first >= 0);
2865 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002866 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002867 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2868 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2869 {
2870 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2871 return false;
2872 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002873
Jamie Madill9fdaa492018-02-16 10:52:11 -05002874 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2875 {
2876 return false;
2877 }
Jamie Madillfd716582014-06-06 17:09:04 -04002878 }
2879
2880 return true;
2881}
2882
He Yunchaoced53ae2016-11-29 15:00:51 +08002883bool ValidateDrawArraysInstancedANGLE(Context *context,
2884 GLenum mode,
2885 GLint first,
2886 GLsizei count,
2887 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002888{
Geoff Lang63c5a592017-09-27 14:08:16 -04002889 if (!context->getExtensions().instancedArrays)
2890 {
2891 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2892 return false;
2893 }
2894
Corentin Wallez170efbf2017-05-02 13:45:01 -04002895 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002896 {
2897 return false;
2898 }
2899
Corentin Wallez0dc97812017-06-22 14:38:44 -04002900 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002901}
2902
Jamie Madill5b772312018-03-08 20:28:32 -05002903bool ValidateDrawElementsBase(Context *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002904{
Jamie Madill250d33f2014-06-06 17:09:03 -04002905 switch (type)
2906 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002907 case GL_UNSIGNED_BYTE:
2908 case GL_UNSIGNED_SHORT:
2909 break;
2910 case GL_UNSIGNED_INT:
2911 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2912 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002913 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002914 return false;
2915 }
2916 break;
2917 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002918 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002919 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002920 }
2921
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002922 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002923
2924 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002925 if (curTransformFeedback && curTransformFeedback->isActive() &&
2926 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002927 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002928 // It is an invalid operation to call DrawElements, DrawRangeElements or
2929 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002930 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002931 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002932 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002933 }
2934
Jiajia Qind9671222016-11-29 16:30:31 +08002935 return true;
2936}
2937
Jamie Madill5b772312018-03-08 20:28:32 -05002938bool ValidateDrawElementsCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002939 GLenum mode,
2940 GLsizei count,
2941 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002942 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002943 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002944{
2945 if (!ValidateDrawElementsBase(context, type))
2946 return false;
2947
2948 const State &state = context->getGLState();
2949
Corentin Wallez170efbf2017-05-02 13:45:01 -04002950 if (!ValidateDrawBase(context, mode, count))
2951 {
2952 return false;
2953 }
2954
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002955 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2956 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2957 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2958 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002959 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002960 // Check for mapped buffers
2961 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002962 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002963 {
2964 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2965 return false;
2966 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002967 }
2968
He Yunchaoced53ae2016-11-29 15:00:51 +08002969 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002970 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002971
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002972 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2973
2974 if (context->getExtensions().webglCompatibility)
2975 {
2976 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2977 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2978 {
2979 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2980 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2981 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002982 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002983 return false;
2984 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002985
2986 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2987 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2988 // error is generated.
2989 if (reinterpret_cast<intptr_t>(indices) < 0)
2990 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002991 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002992 return false;
2993 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002994 }
2995
2996 if (context->getExtensions().webglCompatibility ||
2997 !context->getGLState().areClientArraysEnabled())
2998 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002999 if (!elementArrayBuffer && count > 0)
3000 {
3001 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3002 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3003 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003004 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003005 return false;
3006 }
3007 }
3008
Jamie Madill9fdaa492018-02-16 10:52:11 -05003009 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003010 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003011 // This is an application error that would normally result in a crash, but we catch it and
3012 // return an error
3013 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3014 return false;
3015 }
3016
3017 if (count > 0 && elementArrayBuffer)
3018 {
3019 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3020 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3021 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3022 constexpr uint64_t kMaxTypeSize = 8;
3023 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3024 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3025 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3026
3027 uint64_t typeSize = typeBytes;
3028 uint64_t elementCount = static_cast<uint64_t>(count);
3029 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3030
3031 // Doing the multiplication here is overflow-safe
3032 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3033
3034 // The offset can be any value, check for overflows
3035 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3036 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003037 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003038 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3039 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003040 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003041
3042 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3043 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003044 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003045 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3046 return false;
3047 }
3048
3049 ASSERT(isPow2(typeSize) && typeSize > 0);
3050 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3051 {
3052 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003053 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003054 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003055
3056 if (context->getExtensions().webglCompatibility &&
3057 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3058 {
3059 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3060 ElementArrayBufferBoundForTransformFeedback);
3061 return false;
3062 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003063 }
3064
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003065 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003066 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003067 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
3068 // access is enabled.
3069 if (!ValidateDrawAttribs(context, primcount, 0, 1))
3070 {
3071 return false;
3072 }
3073 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003074 else if (count == 0)
3075 {
3076 // ValidateDrawAttribs also does some extra validation that is independent of the vertex
3077 // count.
3078 if (!ValidateDrawAttribs(context, 0, 0, 0))
3079 {
3080 return false;
3081 }
3082 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003083 else
3084 {
3085 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003086 const DrawCallParams &params = context->getParams<DrawCallParams>();
3087 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3088 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003089
3090 // If we use an index greater than our maximum supported index range, return an error.
3091 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3092 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003093 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003094 {
3095 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3096 return false;
3097 }
3098
Jamie Madill6f5444d2018-03-14 10:08:11 -04003099 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end),
3100 static_cast<GLint>(indexRange.vertexCount())))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003101 {
3102 return false;
3103 }
3104
3105 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003106 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003107 }
3108
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003109 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003110}
3111
Jamie Madill5b772312018-03-08 20:28:32 -05003112bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003113 GLenum mode,
3114 GLsizei count,
3115 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003116 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003117 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003118{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003119 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003120}
3121
Geoff Lang3edfe032015-09-04 16:38:24 -04003122bool ValidateDrawElementsInstancedANGLE(Context *context,
3123 GLenum mode,
3124 GLsizei count,
3125 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003126 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003127 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003128{
Geoff Lang63c5a592017-09-27 14:08:16 -04003129 if (!context->getExtensions().instancedArrays)
3130 {
3131 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3132 return false;
3133 }
3134
Corentin Wallez170efbf2017-05-02 13:45:01 -04003135 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003136 {
3137 return false;
3138 }
3139
Corentin Wallez0dc97812017-06-22 14:38:44 -04003140 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003141}
3142
He Yunchaoced53ae2016-11-29 15:00:51 +08003143bool ValidateFramebufferTextureBase(Context *context,
3144 GLenum target,
3145 GLenum attachment,
3146 GLuint texture,
3147 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003148{
Geoff Lange8afa902017-09-27 15:00:43 -04003149 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003150 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003151 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003152 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003153 }
3154
3155 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003156 {
3157 return false;
3158 }
3159
Jamie Madill55ec3b12014-07-03 10:38:57 -04003160 if (texture != 0)
3161 {
3162 gl::Texture *tex = context->getTexture(texture);
3163
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003164 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003165 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003166 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003167 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003168 }
3169
3170 if (level < 0)
3171 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003172 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003173 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003174 }
3175 }
3176
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003177 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003178 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003179
Jamie Madill84115c92015-04-23 15:00:07 -04003180 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003181 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003182 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003183 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003184 }
3185
3186 return true;
3187}
3188
Geoff Langb1196682014-07-23 13:47:29 -04003189bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003190{
3191 if (program == 0)
3192 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003193 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003194 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003195 }
3196
Dian Xiang769769a2015-09-09 15:20:08 -07003197 gl::Program *programObject = GetValidProgram(context, program);
3198 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003199 {
3200 return false;
3201 }
3202
Jamie Madill0063c512014-08-25 15:47:53 -04003203 if (!programObject || !programObject->isLinked())
3204 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003205 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003206 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003207 }
3208
Geoff Lang7dd2e102014-11-10 15:19:26 -05003209 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003210 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003211 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003212 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003213 }
3214
Jamie Madill0063c512014-08-25 15:47:53 -04003215 return true;
3216}
3217
Geoff Langf41d0ee2016-10-07 13:04:23 -04003218static bool ValidateSizedGetUniform(Context *context,
3219 GLuint program,
3220 GLint location,
3221 GLsizei bufSize,
3222 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003223{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003224 if (length)
3225 {
3226 *length = 0;
3227 }
3228
Jamie Madill78f41802014-08-25 15:47:55 -04003229 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003230 {
Jamie Madill78f41802014-08-25 15:47:55 -04003231 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003232 }
3233
Geoff Langf41d0ee2016-10-07 13:04:23 -04003234 if (bufSize < 0)
3235 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003236 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003237 return false;
3238 }
3239
Jamie Madilla502c742014-08-28 17:19:13 -04003240 gl::Program *programObject = context->getProgram(program);
3241 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003242
Jamie Madill78f41802014-08-25 15:47:55 -04003243 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003244 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003245 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003246 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003247 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003248 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003249 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003250 }
3251
Geoff Langf41d0ee2016-10-07 13:04:23 -04003252 if (length)
3253 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003254 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003255 }
3256
Jamie Madill0063c512014-08-25 15:47:53 -04003257 return true;
3258}
3259
He Yunchaoced53ae2016-11-29 15:00:51 +08003260bool ValidateGetnUniformfvEXT(Context *context,
3261 GLuint program,
3262 GLint location,
3263 GLsizei bufSize,
3264 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003265{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003266 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003267}
3268
He Yunchaoced53ae2016-11-29 15:00:51 +08003269bool ValidateGetnUniformivEXT(Context *context,
3270 GLuint program,
3271 GLint location,
3272 GLsizei bufSize,
3273 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003274{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003275 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3276}
3277
3278bool ValidateGetUniformfvRobustANGLE(Context *context,
3279 GLuint program,
3280 GLint location,
3281 GLsizei bufSize,
3282 GLsizei *length,
3283 GLfloat *params)
3284{
3285 if (!ValidateRobustEntryPoint(context, bufSize))
3286 {
3287 return false;
3288 }
3289
Brandon Jonesd1049182018-03-28 10:02:20 -07003290 GLsizei writeLength = 0;
3291
Geoff Langf41d0ee2016-10-07 13:04:23 -04003292 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003293 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3294 {
3295 return false;
3296 }
3297
3298 SetRobustLengthParam(length, writeLength);
3299
3300 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003301}
3302
3303bool ValidateGetUniformivRobustANGLE(Context *context,
3304 GLuint program,
3305 GLint location,
3306 GLsizei bufSize,
3307 GLsizei *length,
3308 GLint *params)
3309{
3310 if (!ValidateRobustEntryPoint(context, bufSize))
3311 {
3312 return false;
3313 }
3314
Brandon Jonesd1049182018-03-28 10:02:20 -07003315 GLsizei writeLength = 0;
3316
Geoff Langf41d0ee2016-10-07 13:04:23 -04003317 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003318 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3319 {
3320 return false;
3321 }
3322
3323 SetRobustLengthParam(length, writeLength);
3324
3325 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003326}
3327
3328bool ValidateGetUniformuivRobustANGLE(Context *context,
3329 GLuint program,
3330 GLint location,
3331 GLsizei bufSize,
3332 GLsizei *length,
3333 GLuint *params)
3334{
3335 if (!ValidateRobustEntryPoint(context, bufSize))
3336 {
3337 return false;
3338 }
3339
3340 if (context->getClientMajorVersion() < 3)
3341 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003342 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003343 return false;
3344 }
3345
Brandon Jonesd1049182018-03-28 10:02:20 -07003346 GLsizei writeLength = 0;
3347
Geoff Langf41d0ee2016-10-07 13:04:23 -04003348 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003349 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3350 {
3351 return false;
3352 }
3353
3354 SetRobustLengthParam(length, writeLength);
3355
3356 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003357}
3358
He Yunchaoced53ae2016-11-29 15:00:51 +08003359bool ValidateDiscardFramebufferBase(Context *context,
3360 GLenum target,
3361 GLsizei numAttachments,
3362 const GLenum *attachments,
3363 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003364{
3365 if (numAttachments < 0)
3366 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003367 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003368 return false;
3369 }
3370
3371 for (GLsizei i = 0; i < numAttachments; ++i)
3372 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003373 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003374 {
3375 if (defaultFramebuffer)
3376 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003377 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003378 return false;
3379 }
3380
3381 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3382 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003383 context->handleError(InvalidOperation() << "Requested color attachment is "
3384 "greater than the maximum supported "
3385 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003386 return false;
3387 }
3388 }
3389 else
3390 {
3391 switch (attachments[i])
3392 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003393 case GL_DEPTH_ATTACHMENT:
3394 case GL_STENCIL_ATTACHMENT:
3395 case GL_DEPTH_STENCIL_ATTACHMENT:
3396 if (defaultFramebuffer)
3397 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003398 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3399 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003400 return false;
3401 }
3402 break;
3403 case GL_COLOR:
3404 case GL_DEPTH:
3405 case GL_STENCIL:
3406 if (!defaultFramebuffer)
3407 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003408 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3409 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003410 return false;
3411 }
3412 break;
3413 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003414 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003415 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003416 }
3417 }
3418 }
3419
3420 return true;
3421}
3422
Austin Kinross6ee1e782015-05-29 17:05:37 -07003423bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3424{
Jamie Madill007530e2017-12-28 14:27:04 -05003425 if (!context->getExtensions().debugMarker)
3426 {
3427 // The debug marker calls should not set error state
3428 // However, it seems reasonable to set an error state if the extension is not enabled
3429 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3430 return false;
3431 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003432
Jamie Madill007530e2017-12-28 14:27:04 -05003433 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003434 if (length < 0)
3435 {
3436 return false;
3437 }
3438
3439 if (marker == nullptr)
3440 {
3441 return false;
3442 }
3443
3444 return true;
3445}
3446
3447bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3448{
Jamie Madill007530e2017-12-28 14:27:04 -05003449 if (!context->getExtensions().debugMarker)
3450 {
3451 // The debug marker calls should not set error state
3452 // However, it seems reasonable to set an error state if the extension is not enabled
3453 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3454 return false;
3455 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003456
Jamie Madill007530e2017-12-28 14:27:04 -05003457 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003458 if (length < 0)
3459 {
3460 return false;
3461 }
3462
3463 if (length > 0 && marker == nullptr)
3464 {
3465 return false;
3466 }
3467
3468 return true;
3469}
3470
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003471bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003472{
Geoff Langa8406172015-07-21 16:53:39 -04003473 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3474 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003475 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003476 return false;
3477 }
3478
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003479 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003480 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003481 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003482 if (!context->getExtensions().eglImage)
3483 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003484 context->handleError(InvalidEnum()
3485 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003486 }
3487 break;
3488
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003489 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003490 if (!context->getExtensions().eglImageExternal)
3491 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003492 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3493 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003494 }
Geoff Langa8406172015-07-21 16:53:39 -04003495 break;
3496
3497 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003498 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003499 return false;
3500 }
3501
Jamie Madill007530e2017-12-28 14:27:04 -05003502 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3503
Jamie Madill61e16b42017-06-19 11:13:23 -04003504 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003505 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003506 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003507 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003508 return false;
3509 }
3510
Jamie Madill007530e2017-12-28 14:27:04 -05003511 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003513 context->handleError(InvalidOperation()
3514 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003515 return false;
3516 }
3517
Geoff Langca271392017-04-05 12:30:00 -04003518 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003519 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003520 if (!textureCaps.texturable)
3521 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003522 context->handleError(InvalidOperation()
3523 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003524 return false;
3525 }
3526
Geoff Langdcab33b2015-07-21 13:03:16 -04003527 return true;
3528}
3529
3530bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003531 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003532 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003533{
Geoff Langa8406172015-07-21 16:53:39 -04003534 if (!context->getExtensions().eglImage)
3535 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003536 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003537 return false;
3538 }
3539
3540 switch (target)
3541 {
3542 case GL_RENDERBUFFER:
3543 break;
3544
3545 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003546 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003547 return false;
3548 }
3549
Jamie Madill007530e2017-12-28 14:27:04 -05003550 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3551
Jamie Madill61e16b42017-06-19 11:13:23 -04003552 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003553 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003554 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003555 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003556 return false;
3557 }
3558
Geoff Langca271392017-04-05 12:30:00 -04003559 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003560 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003561 if (!textureCaps.renderable)
3562 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003563 context->handleError(InvalidOperation()
3564 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003565 return false;
3566 }
3567
Geoff Langdcab33b2015-07-21 13:03:16 -04003568 return true;
3569}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003570
3571bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3572{
Geoff Lang36167ab2015-12-07 10:27:14 -05003573 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003574 {
3575 // The default VAO should always exist
3576 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003577 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003578 return false;
3579 }
3580
3581 return true;
3582}
3583
Geoff Langc5629752015-12-07 16:29:04 -05003584bool ValidateProgramBinaryBase(Context *context,
3585 GLuint program,
3586 GLenum binaryFormat,
3587 const void *binary,
3588 GLint length)
3589{
3590 Program *programObject = GetValidProgram(context, program);
3591 if (programObject == nullptr)
3592 {
3593 return false;
3594 }
3595
3596 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3597 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3598 programBinaryFormats.end())
3599 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003600 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003601 return false;
3602 }
3603
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003604 if (context->hasActiveTransformFeedback(program))
3605 {
3606 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003607 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3608 "is associated with an active transform "
3609 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003610 return false;
3611 }
3612
Geoff Langc5629752015-12-07 16:29:04 -05003613 return true;
3614}
3615
3616bool ValidateGetProgramBinaryBase(Context *context,
3617 GLuint program,
3618 GLsizei bufSize,
3619 GLsizei *length,
3620 GLenum *binaryFormat,
3621 void *binary)
3622{
3623 Program *programObject = GetValidProgram(context, program);
3624 if (programObject == nullptr)
3625 {
3626 return false;
3627 }
3628
3629 if (!programObject->isLinked())
3630 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003631 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003632 return false;
3633 }
3634
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003635 if (context->getCaps().programBinaryFormats.empty())
3636 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003637 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003638 return false;
3639 }
3640
Geoff Langc5629752015-12-07 16:29:04 -05003641 return true;
3642}
Jamie Madillc29968b2016-01-20 11:17:23 -05003643
Jamie Madill5b772312018-03-08 20:28:32 -05003644bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003645{
3646 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003647 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003648 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003649 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3650 return false;
3651 }
3652 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3653 {
3654 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003655 return false;
3656 }
3657
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003658 ASSERT(context->getGLState().getDrawFramebuffer());
3659 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003660 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3661
3662 // This should come first before the check for the default frame buffer
3663 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3664 // rather than INVALID_OPERATION
3665 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3666 {
3667 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3668
3669 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003670 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3671 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003672 {
3673 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003674 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3675 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3676 // 3.1 is still a bit ambiguous about the error, but future specs are
3677 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003678 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003679 return false;
3680 }
3681 else if (bufs[colorAttachment] >= maxColorAttachment)
3682 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003683 context->handleError(InvalidOperation()
3684 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003685 return false;
3686 }
3687 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3688 frameBufferId != 0)
3689 {
3690 // INVALID_OPERATION-GL is bound to buffer and ith argument
3691 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003692 context->handleError(InvalidOperation()
3693 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003694 return false;
3695 }
3696 }
3697
3698 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3699 // and n is not 1 or bufs is bound to value other than BACK and NONE
3700 if (frameBufferId == 0)
3701 {
3702 if (n != 1)
3703 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003704 context->handleError(InvalidOperation()
3705 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003706 return false;
3707 }
3708
3709 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3710 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003711 context->handleError(
3712 InvalidOperation()
3713 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003714 return false;
3715 }
3716 }
3717
3718 return true;
3719}
3720
Geoff Lang496c02d2016-10-20 11:38:11 -07003721bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003722 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003723 GLenum pname,
3724 GLsizei *length,
3725 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003726{
Geoff Lang496c02d2016-10-20 11:38:11 -07003727 if (length)
3728 {
3729 *length = 0;
3730 }
3731
3732 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3733 {
3734 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003735 InvalidOperation()
3736 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003737 return false;
3738 }
3739
Corentin Walleze4477002017-12-01 14:39:58 -05003740 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003741 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003742 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003743 return false;
3744 }
3745
Geoff Lang496c02d2016-10-20 11:38:11 -07003746 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003747 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003748 case GL_BUFFER_MAP_POINTER:
3749 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003750
Geoff Lang496c02d2016-10-20 11:38:11 -07003751 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003752 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003753 return false;
3754 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003755
3756 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3757 // target bound to zero generate an INVALID_OPERATION error."
3758 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003759 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003760 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003761 context->handleError(InvalidOperation()
3762 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003763 return false;
3764 }
3765
Geoff Lang496c02d2016-10-20 11:38:11 -07003766 if (length)
3767 {
3768 *length = 1;
3769 }
3770
Olli Etuaho4f667482016-03-30 15:56:35 +03003771 return true;
3772}
3773
Corentin Wallez336129f2017-10-17 15:55:40 -04003774bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003775{
Corentin Walleze4477002017-12-01 14:39:58 -05003776 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003777 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003778 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003779 return false;
3780 }
3781
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003782 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003783
3784 if (buffer == nullptr || !buffer->isMapped())
3785 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003786 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003787 return false;
3788 }
3789
3790 return true;
3791}
3792
3793bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003794 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003795 GLintptr offset,
3796 GLsizeiptr length,
3797 GLbitfield access)
3798{
Corentin Walleze4477002017-12-01 14:39:58 -05003799 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003800 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003801 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003802 return false;
3803 }
3804
Brandon Jones6cad5662017-06-14 13:25:13 -07003805 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003806 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003807 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3808 return false;
3809 }
3810
3811 if (length < 0)
3812 {
3813 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003814 return false;
3815 }
3816
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003817 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003818
3819 if (!buffer)
3820 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003821 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003822 return false;
3823 }
3824
3825 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003826 CheckedNumeric<size_t> checkedOffset(offset);
3827 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003828
Jamie Madille2e406c2016-06-02 13:04:10 -04003829 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003830 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003831 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003832 return false;
3833 }
3834
3835 // Check for invalid bits in the mask
3836 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3837 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3838 GL_MAP_UNSYNCHRONIZED_BIT;
3839
3840 if (access & ~(allAccessBits))
3841 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003842 context->handleError(InvalidValue()
3843 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003844 return false;
3845 }
3846
3847 if (length == 0)
3848 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003849 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003850 return false;
3851 }
3852
3853 if (buffer->isMapped())
3854 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003855 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003856 return false;
3857 }
3858
3859 // Check for invalid bit combinations
3860 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3861 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003862 context->handleError(InvalidOperation()
3863 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003864 return false;
3865 }
3866
3867 GLbitfield writeOnlyBits =
3868 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3869
3870 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3871 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003872 context->handleError(InvalidOperation()
3873 << "Invalid access bits when mapping buffer for reading: 0x"
3874 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003875 return false;
3876 }
3877
3878 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3879 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003880 context->handleError(
3881 InvalidOperation()
3882 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003883 return false;
3884 }
Geoff Lang79f71042017-08-14 16:43:43 -04003885
3886 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003887}
3888
3889bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003890 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003891 GLintptr offset,
3892 GLsizeiptr length)
3893{
Brandon Jones6cad5662017-06-14 13:25:13 -07003894 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003895 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003896 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3897 return false;
3898 }
3899
3900 if (length < 0)
3901 {
3902 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003903 return false;
3904 }
3905
Corentin Walleze4477002017-12-01 14:39:58 -05003906 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003907 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003908 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003909 return false;
3910 }
3911
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003912 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003913
3914 if (buffer == nullptr)
3915 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003916 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003917 return false;
3918 }
3919
3920 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3921 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003922 context->handleError(InvalidOperation()
3923 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003924 return false;
3925 }
3926
3927 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003928 CheckedNumeric<size_t> checkedOffset(offset);
3929 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003930
Jamie Madille2e406c2016-06-02 13:04:10 -04003931 if (!checkedSize.IsValid() ||
3932 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003933 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003934 context->handleError(InvalidValue()
3935 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003936 return false;
3937 }
3938
3939 return true;
3940}
3941
Olli Etuaho41997e72016-03-10 13:38:39 +02003942bool ValidateGenOrDelete(Context *context, GLint n)
3943{
3944 if (n < 0)
3945 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003946 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003947 return false;
3948 }
3949 return true;
3950}
3951
Jamie Madill5b772312018-03-08 20:28:32 -05003952bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003953{
3954 if (!context->getExtensions().robustClientMemory)
3955 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003956 context->handleError(InvalidOperation()
3957 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003958 return false;
3959 }
3960
3961 if (bufSize < 0)
3962 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003963 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003964 return false;
3965 }
3966
3967 return true;
3968}
3969
Jamie Madill5b772312018-03-08 20:28:32 -05003970bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003971{
3972 if (bufSize < numParams)
3973 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003974 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3975 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003976 return false;
3977 }
3978
3979 return true;
3980}
3981
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003982bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04003983 GLenum target,
3984 GLenum attachment,
3985 GLenum pname,
3986 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003987{
Geoff Lange8afa902017-09-27 15:00:43 -04003988 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003989 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003990 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003991 return false;
3992 }
3993
3994 int clientVersion = context->getClientMajorVersion();
3995
3996 switch (pname)
3997 {
3998 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3999 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4000 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4001 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4002 break;
4003
Martin Radeve5285d22017-07-14 16:23:53 +03004004 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4005 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4006 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4007 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4008 if (clientVersion < 3 || !context->getExtensions().multiview)
4009 {
4010 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4011 return false;
4012 }
4013 break;
4014
Geoff Langff5b2d52016-09-07 11:32:23 -04004015 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4016 if (clientVersion < 3 && !context->getExtensions().sRGB)
4017 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004018 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004019 return false;
4020 }
4021 break;
4022
4023 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4024 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4025 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4026 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4027 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4028 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4029 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4030 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4031 if (clientVersion < 3)
4032 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004033 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004034 return false;
4035 }
4036 break;
4037
4038 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004039 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004040 return false;
4041 }
4042
4043 // Determine if the attachment is a valid enum
4044 switch (attachment)
4045 {
4046 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004047 case GL_DEPTH:
4048 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004049 if (clientVersion < 3)
4050 {
Geoff Langfa125c92017-10-24 13:01:46 -04004051 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004052 return false;
4053 }
4054 break;
4055
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004056 case GL_DEPTH_STENCIL_ATTACHMENT:
4057 if (clientVersion < 3 && !context->isWebGL1())
4058 {
4059 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4060 return false;
4061 }
4062 break;
4063
Geoff Langfa125c92017-10-24 13:01:46 -04004064 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004065 case GL_DEPTH_ATTACHMENT:
4066 case GL_STENCIL_ATTACHMENT:
4067 break;
4068
4069 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004070 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4071 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004072 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4073 {
Geoff Langfa125c92017-10-24 13:01:46 -04004074 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004075 return false;
4076 }
4077 break;
4078 }
4079
4080 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4081 ASSERT(framebuffer);
4082
4083 if (framebuffer->id() == 0)
4084 {
4085 if (clientVersion < 3)
4086 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004087 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004088 return false;
4089 }
4090
4091 switch (attachment)
4092 {
4093 case GL_BACK:
4094 case GL_DEPTH:
4095 case GL_STENCIL:
4096 break;
4097
4098 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004099 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004100 return false;
4101 }
4102 }
4103 else
4104 {
4105 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4106 {
4107 // Valid attachment query
4108 }
4109 else
4110 {
4111 switch (attachment)
4112 {
4113 case GL_DEPTH_ATTACHMENT:
4114 case GL_STENCIL_ATTACHMENT:
4115 break;
4116
4117 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004118 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004119 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004120 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004121 return false;
4122 }
4123 break;
4124
4125 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004126 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004127 return false;
4128 }
4129 }
4130 }
4131
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004132 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004133 if (attachmentObject)
4134 {
4135 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4136 attachmentObject->type() == GL_TEXTURE ||
4137 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4138
4139 switch (pname)
4140 {
4141 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4142 if (attachmentObject->type() != GL_RENDERBUFFER &&
4143 attachmentObject->type() != GL_TEXTURE)
4144 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004145 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004146 return false;
4147 }
4148 break;
4149
4150 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4151 if (attachmentObject->type() != GL_TEXTURE)
4152 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004153 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004154 return false;
4155 }
4156 break;
4157
4158 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4159 if (attachmentObject->type() != GL_TEXTURE)
4160 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004161 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004162 return false;
4163 }
4164 break;
4165
4166 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4167 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4168 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004169 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004170 return false;
4171 }
4172 break;
4173
4174 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4175 if (attachmentObject->type() != GL_TEXTURE)
4176 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004177 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004178 return false;
4179 }
4180 break;
4181
4182 default:
4183 break;
4184 }
4185 }
4186 else
4187 {
4188 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4189 // is NONE, then querying any other pname will generate INVALID_ENUM.
4190
4191 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4192 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4193 // INVALID_OPERATION for all other pnames
4194
4195 switch (pname)
4196 {
4197 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4198 break;
4199
4200 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4201 if (clientVersion < 3)
4202 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004203 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004204 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004205 return false;
4206 }
4207 break;
4208
4209 default:
4210 if (clientVersion < 3)
4211 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004212 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004213 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004214 return false;
4215 }
4216 else
4217 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004218 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004219 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004220 return false;
4221 }
4222 }
4223 }
4224
Martin Radeve5285d22017-07-14 16:23:53 +03004225 if (numParams)
4226 {
4227 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4228 {
4229 // Only when the viewport offsets are queried we can have a varying number of output
4230 // parameters.
4231 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4232 *numParams = numViews * 2;
4233 }
4234 else
4235 {
4236 // For all other queries we can have only one output parameter.
4237 *numParams = 1;
4238 }
4239 }
4240
Geoff Langff5b2d52016-09-07 11:32:23 -04004241 return true;
4242}
4243
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004244bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004245 GLenum target,
4246 GLenum attachment,
4247 GLenum pname,
4248 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004249 GLsizei *length,
4250 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004251{
4252 if (!ValidateRobustEntryPoint(context, bufSize))
4253 {
4254 return false;
4255 }
4256
Brandon Jonesd1049182018-03-28 10:02:20 -07004257 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004258 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004259 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004260 {
4261 return false;
4262 }
4263
Brandon Jonesd1049182018-03-28 10:02:20 -07004264 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004265 {
4266 return false;
4267 }
4268
Brandon Jonesd1049182018-03-28 10:02:20 -07004269 SetRobustLengthParam(length, numParams);
4270
Geoff Langff5b2d52016-09-07 11:32:23 -04004271 return true;
4272}
4273
Jamie Madill5b772312018-03-08 20:28:32 -05004274bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004275 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004276 GLenum pname,
4277 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004278 GLsizei *length,
4279 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004280{
4281 if (!ValidateRobustEntryPoint(context, bufSize))
4282 {
4283 return false;
4284 }
4285
Brandon Jonesd1049182018-03-28 10:02:20 -07004286 GLsizei numParams = 0;
4287
4288 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004289 {
4290 return false;
4291 }
4292
Brandon Jonesd1049182018-03-28 10:02:20 -07004293 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004294 {
4295 return false;
4296 }
4297
Brandon Jonesd1049182018-03-28 10:02:20 -07004298 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004299 return true;
4300}
4301
Jamie Madill5b772312018-03-08 20:28:32 -05004302bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004303 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004304 GLenum pname,
4305 GLsizei bufSize,
4306 GLsizei *length,
4307 GLint64 *params)
4308{
Brandon Jonesd1049182018-03-28 10:02:20 -07004309 GLsizei numParams = 0;
4310
Geoff Langebebe1c2016-10-14 12:01:31 -04004311 if (!ValidateRobustEntryPoint(context, bufSize))
4312 {
4313 return false;
4314 }
4315
Brandon Jonesd1049182018-03-28 10:02:20 -07004316 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004317 {
4318 return false;
4319 }
4320
Brandon Jonesd1049182018-03-28 10:02:20 -07004321 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004322 {
4323 return false;
4324 }
4325
Brandon Jonesd1049182018-03-28 10:02:20 -07004326 SetRobustLengthParam(length, numParams);
4327
Geoff Langff5b2d52016-09-07 11:32:23 -04004328 return true;
4329}
4330
Jamie Madill5b772312018-03-08 20:28:32 -05004331bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004332{
4333 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004334 if (numParams)
4335 {
4336 *numParams = 1;
4337 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004338
4339 Program *programObject = GetValidProgram(context, program);
4340 if (!programObject)
4341 {
4342 return false;
4343 }
4344
4345 switch (pname)
4346 {
4347 case GL_DELETE_STATUS:
4348 case GL_LINK_STATUS:
4349 case GL_VALIDATE_STATUS:
4350 case GL_INFO_LOG_LENGTH:
4351 case GL_ATTACHED_SHADERS:
4352 case GL_ACTIVE_ATTRIBUTES:
4353 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4354 case GL_ACTIVE_UNIFORMS:
4355 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4356 break;
4357
4358 case GL_PROGRAM_BINARY_LENGTH:
4359 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4360 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004361 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4362 "requires GL_OES_get_program_binary or "
4363 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004364 return false;
4365 }
4366 break;
4367
4368 case GL_ACTIVE_UNIFORM_BLOCKS:
4369 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4370 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4371 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4372 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4373 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4374 if (context->getClientMajorVersion() < 3)
4375 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004376 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004377 return false;
4378 }
4379 break;
4380
Yunchao He61afff12017-03-14 15:34:03 +08004381 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004382 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004383 if (context->getClientVersion() < Version(3, 1))
4384 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004385 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004386 return false;
4387 }
4388 break;
4389
Jiawei Shao6ae51612018-02-23 14:03:25 +08004390 case GL_COMPUTE_WORK_GROUP_SIZE:
4391 if (context->getClientVersion() < Version(3, 1))
4392 {
4393 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4394 return false;
4395 }
4396
4397 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4398 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4399 // program which has not been linked successfully, or which does not contain objects to
4400 // form a compute shader.
4401 if (!programObject->isLinked())
4402 {
4403 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4404 return false;
4405 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004406 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004407 {
4408 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4409 return false;
4410 }
4411 break;
4412
Jiawei Shao447bfac2018-03-14 14:23:40 +08004413 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4414 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4415 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4416 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4417 if (!context->getExtensions().geometryShader)
4418 {
4419 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4420 return false;
4421 }
4422
4423 // [EXT_geometry_shader] Chapter 7.12
4424 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4425 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4426 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4427 // successfully, or which does not contain objects to form a geometry shader.
4428 if (!programObject->isLinked())
4429 {
4430 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4431 return false;
4432 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004433 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004434 {
4435 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4436 return false;
4437 }
4438 break;
4439
Geoff Langff5b2d52016-09-07 11:32:23 -04004440 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004441 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004442 return false;
4443 }
4444
4445 return true;
4446}
4447
4448bool ValidateGetProgramivRobustANGLE(Context *context,
4449 GLuint program,
4450 GLenum pname,
4451 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004452 GLsizei *length,
4453 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004454{
4455 if (!ValidateRobustEntryPoint(context, bufSize))
4456 {
4457 return false;
4458 }
4459
Brandon Jonesd1049182018-03-28 10:02:20 -07004460 GLsizei numParams = 0;
4461
4462 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004463 {
4464 return false;
4465 }
4466
Brandon Jonesd1049182018-03-28 10:02:20 -07004467 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004468 {
4469 return false;
4470 }
4471
Brandon Jonesd1049182018-03-28 10:02:20 -07004472 SetRobustLengthParam(length, numParams);
4473
Geoff Langff5b2d52016-09-07 11:32:23 -04004474 return true;
4475}
4476
Geoff Lang740d9022016-10-07 11:20:52 -04004477bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4478 GLenum target,
4479 GLenum pname,
4480 GLsizei bufSize,
4481 GLsizei *length,
4482 GLint *params)
4483{
4484 if (!ValidateRobustEntryPoint(context, bufSize))
4485 {
4486 return false;
4487 }
4488
Brandon Jonesd1049182018-03-28 10:02:20 -07004489 GLsizei numParams = 0;
4490
4491 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004492 {
4493 return false;
4494 }
4495
Brandon Jonesd1049182018-03-28 10:02:20 -07004496 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004497 {
4498 return false;
4499 }
4500
Brandon Jonesd1049182018-03-28 10:02:20 -07004501 SetRobustLengthParam(length, numParams);
4502
Geoff Lang740d9022016-10-07 11:20:52 -04004503 return true;
4504}
4505
Geoff Langd7d0ed32016-10-07 11:33:51 -04004506bool ValidateGetShaderivRobustANGLE(Context *context,
4507 GLuint shader,
4508 GLenum pname,
4509 GLsizei bufSize,
4510 GLsizei *length,
4511 GLint *params)
4512{
4513 if (!ValidateRobustEntryPoint(context, bufSize))
4514 {
4515 return false;
4516 }
4517
Brandon Jonesd1049182018-03-28 10:02:20 -07004518 GLsizei numParams = 0;
4519
4520 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004521 {
4522 return false;
4523 }
4524
Brandon Jonesd1049182018-03-28 10:02:20 -07004525 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004526 {
4527 return false;
4528 }
4529
Brandon Jonesd1049182018-03-28 10:02:20 -07004530 SetRobustLengthParam(length, numParams);
4531
Geoff Langd7d0ed32016-10-07 11:33:51 -04004532 return true;
4533}
4534
Geoff Langc1984ed2016-10-07 12:41:00 -04004535bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004536 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004537 GLenum pname,
4538 GLsizei bufSize,
4539 GLsizei *length,
4540 GLfloat *params)
4541{
4542 if (!ValidateRobustEntryPoint(context, bufSize))
4543 {
4544 return false;
4545 }
4546
Brandon Jonesd1049182018-03-28 10:02:20 -07004547 GLsizei numParams = 0;
4548
4549 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004550 {
4551 return false;
4552 }
4553
Brandon Jonesd1049182018-03-28 10:02:20 -07004554 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004555 {
4556 return false;
4557 }
4558
Brandon Jonesd1049182018-03-28 10:02:20 -07004559 SetRobustLengthParam(length, numParams);
4560
Geoff Langc1984ed2016-10-07 12:41:00 -04004561 return true;
4562}
4563
Geoff Langc1984ed2016-10-07 12:41:00 -04004564bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004565 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004566 GLenum pname,
4567 GLsizei bufSize,
4568 GLsizei *length,
4569 GLint *params)
4570{
Brandon Jonesd1049182018-03-28 10:02:20 -07004571
Geoff Langc1984ed2016-10-07 12:41:00 -04004572 if (!ValidateRobustEntryPoint(context, bufSize))
4573 {
4574 return false;
4575 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004576 GLsizei numParams = 0;
4577 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004578 {
4579 return false;
4580 }
4581
Brandon Jonesd1049182018-03-28 10:02:20 -07004582 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004583 {
4584 return false;
4585 }
4586
Brandon Jonesd1049182018-03-28 10:02:20 -07004587 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004588 return true;
4589}
4590
Geoff Langc1984ed2016-10-07 12:41:00 -04004591bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004592 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004593 GLenum pname,
4594 GLsizei bufSize,
4595 const GLfloat *params)
4596{
4597 if (!ValidateRobustEntryPoint(context, bufSize))
4598 {
4599 return false;
4600 }
4601
4602 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4603}
4604
Geoff Langc1984ed2016-10-07 12:41:00 -04004605bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004606 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004607 GLenum pname,
4608 GLsizei bufSize,
4609 const GLint *params)
4610{
4611 if (!ValidateRobustEntryPoint(context, bufSize))
4612 {
4613 return false;
4614 }
4615
4616 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4617}
4618
Geoff Langc1984ed2016-10-07 12:41:00 -04004619bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4620 GLuint sampler,
4621 GLenum pname,
4622 GLuint bufSize,
4623 GLsizei *length,
4624 GLfloat *params)
4625{
4626 if (!ValidateRobustEntryPoint(context, bufSize))
4627 {
4628 return false;
4629 }
4630
Brandon Jonesd1049182018-03-28 10:02:20 -07004631 GLsizei numParams = 0;
4632
4633 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004634 {
4635 return false;
4636 }
4637
Brandon Jonesd1049182018-03-28 10:02:20 -07004638 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004639 {
4640 return false;
4641 }
4642
Brandon Jonesd1049182018-03-28 10:02:20 -07004643 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004644 return true;
4645}
4646
Geoff Langc1984ed2016-10-07 12:41:00 -04004647bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4648 GLuint sampler,
4649 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004650 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004651 GLsizei *length,
4652 GLint *params)
4653{
4654 if (!ValidateRobustEntryPoint(context, bufSize))
4655 {
4656 return false;
4657 }
4658
Brandon Jonesd1049182018-03-28 10:02:20 -07004659 GLsizei numParams = 0;
4660
4661 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004662 {
4663 return false;
4664 }
4665
Brandon Jonesd1049182018-03-28 10:02:20 -07004666 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004667 {
4668 return false;
4669 }
4670
Brandon Jonesd1049182018-03-28 10:02:20 -07004671 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004672 return true;
4673}
4674
Geoff Langc1984ed2016-10-07 12:41:00 -04004675bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4676 GLuint sampler,
4677 GLenum pname,
4678 GLsizei bufSize,
4679 const GLfloat *params)
4680{
4681 if (!ValidateRobustEntryPoint(context, bufSize))
4682 {
4683 return false;
4684 }
4685
4686 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4687}
4688
Geoff Langc1984ed2016-10-07 12:41:00 -04004689bool ValidateSamplerParameterivRobustANGLE(Context *context,
4690 GLuint sampler,
4691 GLenum pname,
4692 GLsizei bufSize,
4693 const GLint *params)
4694{
4695 if (!ValidateRobustEntryPoint(context, bufSize))
4696 {
4697 return false;
4698 }
4699
4700 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4701}
4702
Geoff Lang0b031062016-10-13 14:30:04 -04004703bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4704 GLuint index,
4705 GLenum pname,
4706 GLsizei bufSize,
4707 GLsizei *length,
4708 GLfloat *params)
4709{
4710 if (!ValidateRobustEntryPoint(context, bufSize))
4711 {
4712 return false;
4713 }
4714
Brandon Jonesd1049182018-03-28 10:02:20 -07004715 GLsizei writeLength = 0;
4716
4717 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004718 {
4719 return false;
4720 }
4721
Brandon Jonesd1049182018-03-28 10:02:20 -07004722 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004723 {
4724 return false;
4725 }
4726
Brandon Jonesd1049182018-03-28 10:02:20 -07004727 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004728 return true;
4729}
4730
Geoff Lang0b031062016-10-13 14:30:04 -04004731bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4732 GLuint index,
4733 GLenum pname,
4734 GLsizei bufSize,
4735 GLsizei *length,
4736 GLint *params)
4737{
4738 if (!ValidateRobustEntryPoint(context, bufSize))
4739 {
4740 return false;
4741 }
4742
Brandon Jonesd1049182018-03-28 10:02:20 -07004743 GLsizei writeLength = 0;
4744
4745 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004746 {
4747 return false;
4748 }
4749
Brandon Jonesd1049182018-03-28 10:02:20 -07004750 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004751 {
4752 return false;
4753 }
4754
Brandon Jonesd1049182018-03-28 10:02:20 -07004755 SetRobustLengthParam(length, writeLength);
4756
Geoff Lang0b031062016-10-13 14:30:04 -04004757 return true;
4758}
4759
Geoff Lang0b031062016-10-13 14:30:04 -04004760bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4761 GLuint index,
4762 GLenum pname,
4763 GLsizei bufSize,
4764 GLsizei *length,
4765 void **pointer)
4766{
4767 if (!ValidateRobustEntryPoint(context, bufSize))
4768 {
4769 return false;
4770 }
4771
Brandon Jonesd1049182018-03-28 10:02:20 -07004772 GLsizei writeLength = 0;
4773
4774 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004775 {
4776 return false;
4777 }
4778
Brandon Jonesd1049182018-03-28 10:02:20 -07004779 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004780 {
4781 return false;
4782 }
4783
Brandon Jonesd1049182018-03-28 10:02:20 -07004784 SetRobustLengthParam(length, writeLength);
4785
Geoff Lang0b031062016-10-13 14:30:04 -04004786 return true;
4787}
4788
Geoff Lang0b031062016-10-13 14:30:04 -04004789bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4790 GLuint index,
4791 GLenum pname,
4792 GLsizei bufSize,
4793 GLsizei *length,
4794 GLint *params)
4795{
4796 if (!ValidateRobustEntryPoint(context, bufSize))
4797 {
4798 return false;
4799 }
4800
Brandon Jonesd1049182018-03-28 10:02:20 -07004801 GLsizei writeLength = 0;
4802
4803 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004804 {
4805 return false;
4806 }
4807
Brandon Jonesd1049182018-03-28 10:02:20 -07004808 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004809 {
4810 return false;
4811 }
4812
Brandon Jonesd1049182018-03-28 10:02:20 -07004813 SetRobustLengthParam(length, writeLength);
4814
Geoff Lang0b031062016-10-13 14:30:04 -04004815 return true;
4816}
4817
Geoff Lang0b031062016-10-13 14:30:04 -04004818bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4819 GLuint index,
4820 GLenum pname,
4821 GLsizei bufSize,
4822 GLsizei *length,
4823 GLuint *params)
4824{
4825 if (!ValidateRobustEntryPoint(context, bufSize))
4826 {
4827 return false;
4828 }
4829
Brandon Jonesd1049182018-03-28 10:02:20 -07004830 GLsizei writeLength = 0;
4831
4832 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004833 {
4834 return false;
4835 }
4836
Brandon Jonesd1049182018-03-28 10:02:20 -07004837 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004838 {
4839 return false;
4840 }
4841
Brandon Jonesd1049182018-03-28 10:02:20 -07004842 SetRobustLengthParam(length, writeLength);
4843
Geoff Lang0b031062016-10-13 14:30:04 -04004844 return true;
4845}
4846
Geoff Lang6899b872016-10-14 11:30:13 -04004847bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4848 GLuint program,
4849 GLuint uniformBlockIndex,
4850 GLenum pname,
4851 GLsizei bufSize,
4852 GLsizei *length,
4853 GLint *params)
4854{
4855 if (!ValidateRobustEntryPoint(context, bufSize))
4856 {
4857 return false;
4858 }
4859
Brandon Jonesd1049182018-03-28 10:02:20 -07004860 GLsizei writeLength = 0;
4861
4862 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
4863 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004864 {
4865 return false;
4866 }
4867
Brandon Jonesd1049182018-03-28 10:02:20 -07004868 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004869 {
4870 return false;
4871 }
4872
Brandon Jonesd1049182018-03-28 10:02:20 -07004873 SetRobustLengthParam(length, writeLength);
4874
Geoff Lang6899b872016-10-14 11:30:13 -04004875 return true;
4876}
4877
Geoff Lang0a9661f2016-10-20 10:59:20 -07004878bool ValidateGetInternalFormativRobustANGLE(Context *context,
4879 GLenum target,
4880 GLenum internalformat,
4881 GLenum pname,
4882 GLsizei bufSize,
4883 GLsizei *length,
4884 GLint *params)
4885{
4886 if (!ValidateRobustEntryPoint(context, bufSize))
4887 {
4888 return false;
4889 }
4890
Brandon Jonesd1049182018-03-28 10:02:20 -07004891 GLsizei numParams = 0;
4892
4893 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4894 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07004895 {
4896 return false;
4897 }
4898
Brandon Jonesd1049182018-03-28 10:02:20 -07004899 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07004900 {
4901 return false;
4902 }
4903
Brandon Jonesd1049182018-03-28 10:02:20 -07004904 SetRobustLengthParam(length, numParams);
4905
Geoff Lang0a9661f2016-10-20 10:59:20 -07004906 return true;
4907}
4908
Jamie Madill5b772312018-03-08 20:28:32 -05004909bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08004910 GLuint attribIndex,
4911 GLint size,
4912 GLenum type,
4913 GLboolean pureInteger)
4914{
4915 const Caps &caps = context->getCaps();
4916 if (attribIndex >= caps.maxVertexAttributes)
4917 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004918 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004919 return false;
4920 }
4921
4922 if (size < 1 || size > 4)
4923 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004924 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004925 return false;
Shao80957d92017-02-20 21:25:59 +08004926 }
4927
4928 switch (type)
4929 {
4930 case GL_BYTE:
4931 case GL_UNSIGNED_BYTE:
4932 case GL_SHORT:
4933 case GL_UNSIGNED_SHORT:
4934 break;
4935
4936 case GL_INT:
4937 case GL_UNSIGNED_INT:
4938 if (context->getClientMajorVersion() < 3)
4939 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004940 context->handleError(InvalidEnum()
4941 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004942 return false;
4943 }
4944 break;
4945
4946 case GL_FIXED:
4947 case GL_FLOAT:
4948 if (pureInteger)
4949 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004950 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004951 return false;
4952 }
4953 break;
4954
4955 case GL_HALF_FLOAT:
4956 if (context->getClientMajorVersion() < 3)
4957 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004958 context->handleError(InvalidEnum()
4959 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004960 return false;
4961 }
4962 if (pureInteger)
4963 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004964 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004965 return false;
4966 }
4967 break;
4968
4969 case GL_INT_2_10_10_10_REV:
4970 case GL_UNSIGNED_INT_2_10_10_10_REV:
4971 if (context->getClientMajorVersion() < 3)
4972 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004973 context->handleError(InvalidEnum()
4974 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004975 return false;
4976 }
4977 if (pureInteger)
4978 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004979 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004980 return false;
4981 }
4982 if (size != 4)
4983 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004984 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4985 "UNSIGNED_INT_2_10_10_10_REV and "
4986 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004987 return false;
4988 }
4989 break;
4990
4991 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004992 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004993 return false;
4994 }
4995
4996 return true;
4997}
4998
Geoff Lang76e65652017-03-27 14:58:02 -04004999// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5000// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5001// specified clear value and the type of a buffer that is being cleared generates an
5002// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005003bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005004 GLint drawbuffer,
5005 const GLenum *validComponentTypes,
5006 size_t validComponentTypeCount)
5007{
5008 const FramebufferAttachment *attachment =
5009 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5010 if (attachment)
5011 {
5012 GLenum componentType = attachment->getFormat().info->componentType;
5013 const GLenum *end = validComponentTypes + validComponentTypeCount;
5014 if (std::find(validComponentTypes, end, componentType) == end)
5015 {
5016 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005017 InvalidOperation()
5018 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005019 return false;
5020 }
5021 }
5022
5023 return true;
5024}
5025
Jamie Madill5b772312018-03-08 20:28:32 -05005026bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005027{
5028 if (!ValidateRobustEntryPoint(context, dataSize))
5029 {
5030 return false;
5031 }
5032
Corentin Wallez336129f2017-10-17 15:55:40 -04005033 gl::Buffer *pixelUnpackBuffer =
5034 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005035 if (pixelUnpackBuffer == nullptr)
5036 {
5037 if (dataSize < imageSize)
5038 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005039 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005040 }
5041 }
5042 return true;
5043}
5044
Jamie Madill5b772312018-03-08 20:28:32 -05005045bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005046 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005047 GLenum pname,
5048 bool pointerVersion,
5049 GLsizei *numParams)
5050{
5051 if (numParams)
5052 {
5053 *numParams = 0;
5054 }
5055
Corentin Walleze4477002017-12-01 14:39:58 -05005056 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005057 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005058 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005059 return false;
5060 }
5061
5062 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5063 if (!buffer)
5064 {
5065 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005066 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005067 return false;
5068 }
5069
5070 const Extensions &extensions = context->getExtensions();
5071
5072 switch (pname)
5073 {
5074 case GL_BUFFER_USAGE:
5075 case GL_BUFFER_SIZE:
5076 break;
5077
5078 case GL_BUFFER_ACCESS_OES:
5079 if (!extensions.mapBuffer)
5080 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005081 context->handleError(InvalidEnum()
5082 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005083 return false;
5084 }
5085 break;
5086
5087 case GL_BUFFER_MAPPED:
5088 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5089 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5090 !extensions.mapBufferRange)
5091 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005092 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5093 "GL_OES_mapbuffer or "
5094 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005095 return false;
5096 }
5097 break;
5098
5099 case GL_BUFFER_MAP_POINTER:
5100 if (!pointerVersion)
5101 {
5102 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005103 InvalidEnum()
5104 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005105 return false;
5106 }
5107 break;
5108
5109 case GL_BUFFER_ACCESS_FLAGS:
5110 case GL_BUFFER_MAP_OFFSET:
5111 case GL_BUFFER_MAP_LENGTH:
5112 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5113 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005114 context->handleError(InvalidEnum()
5115 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005116 return false;
5117 }
5118 break;
5119
5120 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005121 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005122 return false;
5123 }
5124
5125 // All buffer parameter queries return one value.
5126 if (numParams)
5127 {
5128 *numParams = 1;
5129 }
5130
5131 return true;
5132}
5133
5134bool ValidateGetRenderbufferParameterivBase(Context *context,
5135 GLenum target,
5136 GLenum pname,
5137 GLsizei *length)
5138{
5139 if (length)
5140 {
5141 *length = 0;
5142 }
5143
5144 if (target != GL_RENDERBUFFER)
5145 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005146 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005147 return false;
5148 }
5149
5150 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5151 if (renderbuffer == nullptr)
5152 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005153 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005154 return false;
5155 }
5156
5157 switch (pname)
5158 {
5159 case GL_RENDERBUFFER_WIDTH:
5160 case GL_RENDERBUFFER_HEIGHT:
5161 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5162 case GL_RENDERBUFFER_RED_SIZE:
5163 case GL_RENDERBUFFER_GREEN_SIZE:
5164 case GL_RENDERBUFFER_BLUE_SIZE:
5165 case GL_RENDERBUFFER_ALPHA_SIZE:
5166 case GL_RENDERBUFFER_DEPTH_SIZE:
5167 case GL_RENDERBUFFER_STENCIL_SIZE:
5168 break;
5169
5170 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5171 if (!context->getExtensions().framebufferMultisample)
5172 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005173 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005174 return false;
5175 }
5176 break;
5177
5178 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005179 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005180 return false;
5181 }
5182
5183 if (length)
5184 {
5185 *length = 1;
5186 }
5187 return true;
5188}
5189
5190bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5191{
5192 if (length)
5193 {
5194 *length = 0;
5195 }
5196
5197 if (GetValidShader(context, shader) == nullptr)
5198 {
5199 return false;
5200 }
5201
5202 switch (pname)
5203 {
5204 case GL_SHADER_TYPE:
5205 case GL_DELETE_STATUS:
5206 case GL_COMPILE_STATUS:
5207 case GL_INFO_LOG_LENGTH:
5208 case GL_SHADER_SOURCE_LENGTH:
5209 break;
5210
5211 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5212 if (!context->getExtensions().translatedShaderSource)
5213 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005214 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005215 return false;
5216 }
5217 break;
5218
5219 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005220 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005221 return false;
5222 }
5223
5224 if (length)
5225 {
5226 *length = 1;
5227 }
5228 return true;
5229}
5230
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005231bool ValidateGetTexParameterBase(Context *context,
5232 TextureType target,
5233 GLenum pname,
5234 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005235{
5236 if (length)
5237 {
5238 *length = 0;
5239 }
5240
5241 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5242 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005243 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005244 return false;
5245 }
5246
5247 if (context->getTargetTexture(target) == nullptr)
5248 {
5249 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005250 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005251 return false;
5252 }
5253
5254 switch (pname)
5255 {
5256 case GL_TEXTURE_MAG_FILTER:
5257 case GL_TEXTURE_MIN_FILTER:
5258 case GL_TEXTURE_WRAP_S:
5259 case GL_TEXTURE_WRAP_T:
5260 break;
5261
5262 case GL_TEXTURE_USAGE_ANGLE:
5263 if (!context->getExtensions().textureUsage)
5264 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005265 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005266 return false;
5267 }
5268 break;
5269
5270 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005271 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005272 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005273 return false;
5274 }
5275 break;
5276
5277 case GL_TEXTURE_IMMUTABLE_FORMAT:
5278 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5279 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005280 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005281 return false;
5282 }
5283 break;
5284
5285 case GL_TEXTURE_WRAP_R:
5286 case GL_TEXTURE_IMMUTABLE_LEVELS:
5287 case GL_TEXTURE_SWIZZLE_R:
5288 case GL_TEXTURE_SWIZZLE_G:
5289 case GL_TEXTURE_SWIZZLE_B:
5290 case GL_TEXTURE_SWIZZLE_A:
5291 case GL_TEXTURE_BASE_LEVEL:
5292 case GL_TEXTURE_MAX_LEVEL:
5293 case GL_TEXTURE_MIN_LOD:
5294 case GL_TEXTURE_MAX_LOD:
5295 case GL_TEXTURE_COMPARE_MODE:
5296 case GL_TEXTURE_COMPARE_FUNC:
5297 if (context->getClientMajorVersion() < 3)
5298 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005299 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005300 return false;
5301 }
5302 break;
5303
5304 case GL_TEXTURE_SRGB_DECODE_EXT:
5305 if (!context->getExtensions().textureSRGBDecode)
5306 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005307 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005308 return false;
5309 }
5310 break;
5311
Yunchao Hebacaa712018-01-30 14:01:39 +08005312 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5313 if (context->getClientVersion() < Version(3, 1))
5314 {
5315 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5316 return false;
5317 }
5318 break;
5319
Jamie Madillbe849e42017-05-02 15:49:00 -04005320 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005321 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005322 return false;
5323 }
5324
5325 if (length)
5326 {
5327 *length = 1;
5328 }
5329 return true;
5330}
5331
5332bool ValidateGetVertexAttribBase(Context *context,
5333 GLuint index,
5334 GLenum pname,
5335 GLsizei *length,
5336 bool pointer,
5337 bool pureIntegerEntryPoint)
5338{
5339 if (length)
5340 {
5341 *length = 0;
5342 }
5343
5344 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5345 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005346 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005347 return false;
5348 }
5349
5350 if (index >= context->getCaps().maxVertexAttributes)
5351 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005352 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005353 return false;
5354 }
5355
5356 if (pointer)
5357 {
5358 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5359 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005360 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005361 return false;
5362 }
5363 }
5364 else
5365 {
5366 switch (pname)
5367 {
5368 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5369 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5370 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5371 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5372 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5373 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5374 case GL_CURRENT_VERTEX_ATTRIB:
5375 break;
5376
5377 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5378 static_assert(
5379 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5380 "ANGLE extension enums not equal to GL enums.");
5381 if (context->getClientMajorVersion() < 3 &&
5382 !context->getExtensions().instancedArrays)
5383 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005384 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5385 "requires OpenGL ES 3.0 or "
5386 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005387 return false;
5388 }
5389 break;
5390
5391 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5392 if (context->getClientMajorVersion() < 3)
5393 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005394 context->handleError(
5395 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005396 return false;
5397 }
5398 break;
5399
5400 case GL_VERTEX_ATTRIB_BINDING:
5401 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5402 if (context->getClientVersion() < ES_3_1)
5403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005404 context->handleError(InvalidEnum()
5405 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005406 return false;
5407 }
5408 break;
5409
5410 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005411 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005412 return false;
5413 }
5414 }
5415
5416 if (length)
5417 {
5418 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5419 {
5420 *length = 4;
5421 }
5422 else
5423 {
5424 *length = 1;
5425 }
5426 }
5427
5428 return true;
5429}
5430
Jamie Madill4928b7c2017-06-20 12:57:39 -04005431bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005432 GLint x,
5433 GLint y,
5434 GLsizei width,
5435 GLsizei height,
5436 GLenum format,
5437 GLenum type,
5438 GLsizei bufSize,
5439 GLsizei *length,
5440 GLsizei *columns,
5441 GLsizei *rows,
5442 void *pixels)
5443{
5444 if (length != nullptr)
5445 {
5446 *length = 0;
5447 }
5448 if (rows != nullptr)
5449 {
5450 *rows = 0;
5451 }
5452 if (columns != nullptr)
5453 {
5454 *columns = 0;
5455 }
5456
5457 if (width < 0 || height < 0)
5458 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005459 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005460 return false;
5461 }
5462
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005463 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005464
Jamie Madille98b1b52018-03-08 09:47:23 -05005465 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madillbe849e42017-05-02 15:49:00 -04005466 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005467 return false;
5468 }
5469
Jamie Madille98b1b52018-03-08 09:47:23 -05005470 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005471 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005472 return false;
5473 }
5474
Jamie Madill690c8eb2018-03-12 15:20:03 -04005475 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005476 ASSERT(framebuffer);
5477
5478 if (framebuffer->getReadBufferState() == GL_NONE)
5479 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005480 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005481 return false;
5482 }
5483
5484 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5485 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5486 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5487 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5488 // situation is an application error that would lead to a crash in ANGLE.
5489 if (readBuffer == nullptr)
5490 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005491 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005492 return false;
5493 }
5494
Martin Radev28031682017-07-28 14:47:56 +03005495 // ANGLE_multiview, Revision 1:
5496 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5497 // current read framebuffer is not NONE.
5498 if (readBuffer->getMultiviewLayout() != GL_NONE)
5499 {
5500 context->handleError(InvalidFramebufferOperation()
5501 << "Attempting to read from a multi-view framebuffer.");
5502 return false;
5503 }
5504
Geoff Lang280ba992017-04-18 16:30:58 -04005505 if (context->getExtensions().webglCompatibility)
5506 {
5507 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5508 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5509 // and type before validating the combination of format and type. However, the
5510 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5511 // verifies that GL_INVALID_OPERATION is generated.
5512 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5513 // dEQP/WebGL.
5514 if (!ValidReadPixelsFormatEnum(context, format))
5515 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005516 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005517 return false;
5518 }
5519
5520 if (!ValidReadPixelsTypeEnum(context, type))
5521 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005522 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005523 return false;
5524 }
5525 }
5526
Jamie Madill690c8eb2018-03-12 15:20:03 -04005527 GLenum currentFormat = GL_NONE;
5528 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5529
5530 GLenum currentType = GL_NONE;
5531 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5532
Jamie Madillbe849e42017-05-02 15:49:00 -04005533 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5534
5535 bool validFormatTypeCombination =
5536 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5537
5538 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5539 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005540 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005541 return false;
5542 }
5543
5544 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005545 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005546 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5547 {
5548 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005549 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005550 return false;
5551 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005552 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5553 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5554 {
5555 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5556 return false;
5557 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005558
5559 // .. the data would be packed to the buffer object such that the memory writes required
5560 // would exceed the data store size.
5561 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5562 const gl::Extents size(width, height, 1);
5563 const auto &pack = context->getGLState().getPackState();
5564
5565 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5566 if (endByteOrErr.isError())
5567 {
5568 context->handleError(endByteOrErr.getError());
5569 return false;
5570 }
5571
5572 size_t endByte = endByteOrErr.getResult();
5573 if (bufSize >= 0)
5574 {
5575 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5576 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005577 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005578 return false;
5579 }
5580 }
5581
5582 if (pixelPackBuffer != nullptr)
5583 {
5584 CheckedNumeric<size_t> checkedEndByte(endByte);
5585 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5586 checkedEndByte += checkedOffset;
5587
5588 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5589 {
5590 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005591 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005592 return false;
5593 }
5594 }
5595
5596 if (pixelPackBuffer == nullptr && length != nullptr)
5597 {
5598 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5599 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005600 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005601 return false;
5602 }
5603
5604 *length = static_cast<GLsizei>(endByte);
5605 }
5606
Geoff Langa953b522018-02-21 16:56:23 -05005607 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005608 angle::CheckedNumeric<int> clippedExtent(length);
5609 if (start < 0)
5610 {
5611 // "subtract" the area that is less than 0
5612 clippedExtent += start;
5613 }
5614
Geoff Langa953b522018-02-21 16:56:23 -05005615 angle::CheckedNumeric<int> readExtent = start;
5616 readExtent += length;
5617 if (!readExtent.IsValid())
5618 {
5619 return false;
5620 }
5621
5622 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005623 {
5624 // Subtract the region to the right of the read buffer
5625 clippedExtent -= (readExtent - bufferSize);
5626 }
5627
5628 if (!clippedExtent.IsValid())
5629 {
Geoff Langa953b522018-02-21 16:56:23 -05005630 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005631 }
5632
Geoff Langa953b522018-02-21 16:56:23 -05005633 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5634 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005635 };
5636
Geoff Langa953b522018-02-21 16:56:23 -05005637 GLsizei writtenColumns = 0;
5638 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5639 {
5640 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5641 return false;
5642 }
5643
5644 GLsizei writtenRows = 0;
5645 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5646 {
5647 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5648 return false;
5649 }
5650
Jamie Madillbe849e42017-05-02 15:49:00 -04005651 if (columns != nullptr)
5652 {
Geoff Langa953b522018-02-21 16:56:23 -05005653 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005654 }
5655
5656 if (rows != nullptr)
5657 {
Geoff Langa953b522018-02-21 16:56:23 -05005658 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005659 }
5660
5661 return true;
5662}
5663
5664template <typename ParamType>
5665bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005666 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005667 GLenum pname,
5668 GLsizei bufSize,
5669 const ParamType *params)
5670{
5671 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5672 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005673 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005674 return false;
5675 }
5676
5677 if (context->getTargetTexture(target) == nullptr)
5678 {
5679 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005680 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005681 return false;
5682 }
5683
5684 const GLsizei minBufSize = 1;
5685 if (bufSize >= 0 && bufSize < minBufSize)
5686 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005687 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005688 return false;
5689 }
5690
5691 switch (pname)
5692 {
5693 case GL_TEXTURE_WRAP_R:
5694 case GL_TEXTURE_SWIZZLE_R:
5695 case GL_TEXTURE_SWIZZLE_G:
5696 case GL_TEXTURE_SWIZZLE_B:
5697 case GL_TEXTURE_SWIZZLE_A:
5698 case GL_TEXTURE_BASE_LEVEL:
5699 case GL_TEXTURE_MAX_LEVEL:
5700 case GL_TEXTURE_COMPARE_MODE:
5701 case GL_TEXTURE_COMPARE_FUNC:
5702 case GL_TEXTURE_MIN_LOD:
5703 case GL_TEXTURE_MAX_LOD:
5704 if (context->getClientMajorVersion() < 3)
5705 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005706 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005707 return false;
5708 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005709 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005710 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005711 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5712 "available without "
5713 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005714 return false;
5715 }
5716 break;
5717
5718 default:
5719 break;
5720 }
5721
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005722 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005723 {
5724 switch (pname)
5725 {
5726 case GL_TEXTURE_MIN_FILTER:
5727 case GL_TEXTURE_MAG_FILTER:
5728 case GL_TEXTURE_WRAP_S:
5729 case GL_TEXTURE_WRAP_T:
5730 case GL_TEXTURE_WRAP_R:
5731 case GL_TEXTURE_MIN_LOD:
5732 case GL_TEXTURE_MAX_LOD:
5733 case GL_TEXTURE_COMPARE_MODE:
5734 case GL_TEXTURE_COMPARE_FUNC:
5735 context->handleError(InvalidEnum()
5736 << "Invalid parameter for 2D multisampled textures.");
5737 return false;
5738 }
5739 }
5740
Jamie Madillbe849e42017-05-02 15:49:00 -04005741 switch (pname)
5742 {
5743 case GL_TEXTURE_WRAP_S:
5744 case GL_TEXTURE_WRAP_T:
5745 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005746 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005747 bool restrictedWrapModes =
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005748 target == TextureType::External || target == TextureType::Rectangle;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005749 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5750 {
5751 return false;
5752 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005753 }
5754 break;
5755
5756 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005757 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005758 bool restrictedMinFilter =
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005759 target == TextureType::External || target == TextureType::Rectangle;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005760 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5761 {
5762 return false;
5763 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005764 }
5765 break;
5766
5767 case GL_TEXTURE_MAG_FILTER:
5768 if (!ValidateTextureMagFilterValue(context, params))
5769 {
5770 return false;
5771 }
5772 break;
5773
5774 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005775 if (!context->getExtensions().textureUsage)
5776 {
5777 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5778 return false;
5779 }
5780
Jamie Madillbe849e42017-05-02 15:49:00 -04005781 switch (ConvertToGLenum(params[0]))
5782 {
5783 case GL_NONE:
5784 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5785 break;
5786
5787 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005788 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005789 return false;
5790 }
5791 break;
5792
5793 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Jamie Madillbe849e42017-05-02 15:49:00 -04005794 {
Luc Ferron1b1a8642018-01-23 15:12:01 -05005795 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5796 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5797 {
5798 return false;
5799 }
5800 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
Jamie Madillbe849e42017-05-02 15:49:00 -04005801 }
5802 break;
5803
5804 case GL_TEXTURE_MIN_LOD:
5805 case GL_TEXTURE_MAX_LOD:
5806 // any value is permissible
5807 break;
5808
5809 case GL_TEXTURE_COMPARE_MODE:
5810 if (!ValidateTextureCompareModeValue(context, params))
5811 {
5812 return false;
5813 }
5814 break;
5815
5816 case GL_TEXTURE_COMPARE_FUNC:
5817 if (!ValidateTextureCompareFuncValue(context, params))
5818 {
5819 return false;
5820 }
5821 break;
5822
5823 case GL_TEXTURE_SWIZZLE_R:
5824 case GL_TEXTURE_SWIZZLE_G:
5825 case GL_TEXTURE_SWIZZLE_B:
5826 case GL_TEXTURE_SWIZZLE_A:
5827 switch (ConvertToGLenum(params[0]))
5828 {
5829 case GL_RED:
5830 case GL_GREEN:
5831 case GL_BLUE:
5832 case GL_ALPHA:
5833 case GL_ZERO:
5834 case GL_ONE:
5835 break;
5836
5837 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005838 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005839 return false;
5840 }
5841 break;
5842
5843 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005844 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005845 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005846 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005847 return false;
5848 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005849 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005850 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005851 context->handleError(InvalidOperation()
5852 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005853 return false;
5854 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005855 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005856 {
5857 context->handleError(InvalidOperation()
5858 << "Base level must be 0 for multisampled textures.");
5859 return false;
5860 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005861 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005862 {
5863 context->handleError(InvalidOperation()
5864 << "Base level must be 0 for rectangle textures.");
5865 return false;
5866 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005867 break;
5868
5869 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005870 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005871 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005872 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005873 return false;
5874 }
5875 break;
5876
5877 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5878 if (context->getClientVersion() < Version(3, 1))
5879 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005880 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005881 return false;
5882 }
5883 switch (ConvertToGLenum(params[0]))
5884 {
5885 case GL_DEPTH_COMPONENT:
5886 case GL_STENCIL_INDEX:
5887 break;
5888
5889 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005890 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005891 return false;
5892 }
5893 break;
5894
5895 case GL_TEXTURE_SRGB_DECODE_EXT:
5896 if (!ValidateTextureSRGBDecodeValue(context, params))
5897 {
5898 return false;
5899 }
5900 break;
5901
5902 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005903 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005904 return false;
5905 }
5906
5907 return true;
5908}
5909
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005910template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
5911template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04005912
Jamie Madill5b772312018-03-08 20:28:32 -05005913bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04005914{
5915 if (index >= MAX_VERTEX_ATTRIBS)
5916 {
5917 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5918 return false;
5919 }
5920
5921 return true;
5922}
5923
5924bool ValidateGetActiveUniformBlockivBase(Context *context,
5925 GLuint program,
5926 GLuint uniformBlockIndex,
5927 GLenum pname,
5928 GLsizei *length)
5929{
5930 if (length)
5931 {
5932 *length = 0;
5933 }
5934
5935 if (context->getClientMajorVersion() < 3)
5936 {
5937 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5938 return false;
5939 }
5940
5941 Program *programObject = GetValidProgram(context, program);
5942 if (!programObject)
5943 {
5944 return false;
5945 }
5946
5947 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5948 {
5949 context->handleError(InvalidValue()
5950 << "uniformBlockIndex exceeds active uniform block count.");
5951 return false;
5952 }
5953
5954 switch (pname)
5955 {
5956 case GL_UNIFORM_BLOCK_BINDING:
5957 case GL_UNIFORM_BLOCK_DATA_SIZE:
5958 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5959 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5960 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5961 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5962 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5963 break;
5964
5965 default:
5966 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5967 return false;
5968 }
5969
5970 if (length)
5971 {
5972 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5973 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005974 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005975 programObject->getUniformBlockByIndex(uniformBlockIndex);
5976 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5977 }
5978 else
5979 {
5980 *length = 1;
5981 }
5982 }
5983
5984 return true;
5985}
5986
Jamie Madill9696d072017-08-26 23:19:57 -04005987template <typename ParamType>
5988bool ValidateSamplerParameterBase(Context *context,
5989 GLuint sampler,
5990 GLenum pname,
5991 GLsizei bufSize,
5992 ParamType *params)
5993{
5994 if (context->getClientMajorVersion() < 3)
5995 {
5996 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5997 return false;
5998 }
5999
6000 if (!context->isSampler(sampler))
6001 {
6002 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6003 return false;
6004 }
6005
6006 const GLsizei minBufSize = 1;
6007 if (bufSize >= 0 && bufSize < minBufSize)
6008 {
6009 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6010 return false;
6011 }
6012
6013 switch (pname)
6014 {
6015 case GL_TEXTURE_WRAP_S:
6016 case GL_TEXTURE_WRAP_T:
6017 case GL_TEXTURE_WRAP_R:
6018 if (!ValidateTextureWrapModeValue(context, params, false))
6019 {
6020 return false;
6021 }
6022 break;
6023
6024 case GL_TEXTURE_MIN_FILTER:
6025 if (!ValidateTextureMinFilterValue(context, params, false))
6026 {
6027 return false;
6028 }
6029 break;
6030
6031 case GL_TEXTURE_MAG_FILTER:
6032 if (!ValidateTextureMagFilterValue(context, params))
6033 {
6034 return false;
6035 }
6036 break;
6037
6038 case GL_TEXTURE_MIN_LOD:
6039 case GL_TEXTURE_MAX_LOD:
6040 // any value is permissible
6041 break;
6042
6043 case GL_TEXTURE_COMPARE_MODE:
6044 if (!ValidateTextureCompareModeValue(context, params))
6045 {
6046 return false;
6047 }
6048 break;
6049
6050 case GL_TEXTURE_COMPARE_FUNC:
6051 if (!ValidateTextureCompareFuncValue(context, params))
6052 {
6053 return false;
6054 }
6055 break;
6056
6057 case GL_TEXTURE_SRGB_DECODE_EXT:
6058 if (!ValidateTextureSRGBDecodeValue(context, params))
6059 {
6060 return false;
6061 }
6062 break;
6063
Luc Ferron1b1a8642018-01-23 15:12:01 -05006064 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6065 {
6066 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6067 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6068 {
6069 return false;
6070 }
6071 }
6072 break;
6073
Jamie Madill9696d072017-08-26 23:19:57 -04006074 default:
6075 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6076 return false;
6077 }
6078
6079 return true;
6080}
6081
6082template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6083template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6084
6085bool ValidateGetSamplerParameterBase(Context *context,
6086 GLuint sampler,
6087 GLenum pname,
6088 GLsizei *length)
6089{
6090 if (length)
6091 {
6092 *length = 0;
6093 }
6094
6095 if (context->getClientMajorVersion() < 3)
6096 {
6097 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6098 return false;
6099 }
6100
6101 if (!context->isSampler(sampler))
6102 {
6103 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6104 return false;
6105 }
6106
6107 switch (pname)
6108 {
6109 case GL_TEXTURE_WRAP_S:
6110 case GL_TEXTURE_WRAP_T:
6111 case GL_TEXTURE_WRAP_R:
6112 case GL_TEXTURE_MIN_FILTER:
6113 case GL_TEXTURE_MAG_FILTER:
6114 case GL_TEXTURE_MIN_LOD:
6115 case GL_TEXTURE_MAX_LOD:
6116 case GL_TEXTURE_COMPARE_MODE:
6117 case GL_TEXTURE_COMPARE_FUNC:
6118 break;
6119
Luc Ferron1b1a8642018-01-23 15:12:01 -05006120 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6121 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6122 {
6123 return false;
6124 }
6125 break;
6126
Jamie Madill9696d072017-08-26 23:19:57 -04006127 case GL_TEXTURE_SRGB_DECODE_EXT:
6128 if (!context->getExtensions().textureSRGBDecode)
6129 {
6130 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6131 return false;
6132 }
6133 break;
6134
6135 default:
6136 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6137 return false;
6138 }
6139
6140 if (length)
6141 {
6142 *length = 1;
6143 }
6144 return true;
6145}
6146
6147bool ValidateGetInternalFormativBase(Context *context,
6148 GLenum target,
6149 GLenum internalformat,
6150 GLenum pname,
6151 GLsizei bufSize,
6152 GLsizei *numParams)
6153{
6154 if (numParams)
6155 {
6156 *numParams = 0;
6157 }
6158
6159 if (context->getClientMajorVersion() < 3)
6160 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006161 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006162 return false;
6163 }
6164
6165 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
6166 if (!formatCaps.renderable)
6167 {
6168 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6169 return false;
6170 }
6171
6172 switch (target)
6173 {
6174 case GL_RENDERBUFFER:
6175 break;
6176
6177 case GL_TEXTURE_2D_MULTISAMPLE:
6178 if (context->getClientVersion() < ES_3_1)
6179 {
6180 context->handleError(InvalidOperation()
6181 << "Texture target requires at least OpenGL ES 3.1.");
6182 return false;
6183 }
6184 break;
6185
6186 default:
6187 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6188 return false;
6189 }
6190
6191 if (bufSize < 0)
6192 {
6193 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6194 return false;
6195 }
6196
6197 GLsizei maxWriteParams = 0;
6198 switch (pname)
6199 {
6200 case GL_NUM_SAMPLE_COUNTS:
6201 maxWriteParams = 1;
6202 break;
6203
6204 case GL_SAMPLES:
6205 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6206 break;
6207
6208 default:
6209 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6210 return false;
6211 }
6212
6213 if (numParams)
6214 {
6215 // glGetInternalFormativ will not overflow bufSize
6216 *numParams = std::min(bufSize, maxWriteParams);
6217 }
6218
6219 return true;
6220}
6221
Jamie Madille98b1b52018-03-08 09:47:23 -05006222// We should check with Khronos if returning INVALID_FRAMEBUFFER_OPERATION is OK when querying
6223// implementation format info for incomplete framebuffers. It seems like these queries are
6224// incongruent with the other errors.
6225bool ValidateFramebufferComplete(Context *context, Framebuffer *framebuffer, bool isFramebufferOp)
6226{
6227 bool complete = false;
6228 ANGLE_VALIDATION_TRY(framebuffer->isComplete(context, &complete));
6229 if (!complete)
6230 {
6231 if (isFramebufferOp)
6232 {
6233 context->handleError(InvalidFramebufferOperation());
6234 }
6235 else
6236 {
6237 context->handleError(InvalidOperation());
6238 }
6239 return false;
6240 }
6241 return true;
6242}
6243
6244bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6245{
6246 GLint samples = 0;
6247 ANGLE_VALIDATION_TRY(framebuffer->getSamples(context, &samples));
6248 if (samples != 0)
6249 {
6250 context->handleError(InvalidOperation());
6251 return false;
6252 }
6253 return true;
6254}
6255
Jamie Madillc29968b2016-01-20 11:17:23 -05006256} // namespace gl