blob: 1e53415c167ae5bc43bad768360125284e9e0edc [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.
Lingfeng Yang038dd532018-03-29 17:31:52 -070093 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{
Lingfeng Yang038dd532018-03-29 17:31:52 -0700480 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);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001336 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001337 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);
Lingfeng Yang038dd532018-03-29 17:31:52 -07002756 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
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003269bool ValidateGetnUniformfvRobustANGLE(Context *context,
3270 GLuint program,
3271 GLint location,
3272 GLsizei bufSize,
3273 GLsizei *length,
3274 GLfloat *params)
3275{
3276 UNIMPLEMENTED();
3277 return false;
3278}
3279
He Yunchaoced53ae2016-11-29 15:00:51 +08003280bool ValidateGetnUniformivEXT(Context *context,
3281 GLuint program,
3282 GLint location,
3283 GLsizei bufSize,
3284 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003285{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003286 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3287}
3288
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003289bool ValidateGetnUniformivRobustANGLE(Context *context,
3290 GLuint program,
3291 GLint location,
3292 GLsizei bufSize,
3293 GLsizei *length,
3294 GLint *params)
3295{
3296 UNIMPLEMENTED();
3297 return false;
3298}
3299
3300bool ValidateGetnUniformuivRobustANGLE(Context *context,
3301 GLuint program,
3302 GLint location,
3303 GLsizei bufSize,
3304 GLsizei *length,
3305 GLuint *params)
3306{
3307 UNIMPLEMENTED();
3308 return false;
3309}
3310
Geoff Langf41d0ee2016-10-07 13:04:23 -04003311bool ValidateGetUniformfvRobustANGLE(Context *context,
3312 GLuint program,
3313 GLint location,
3314 GLsizei bufSize,
3315 GLsizei *length,
3316 GLfloat *params)
3317{
3318 if (!ValidateRobustEntryPoint(context, bufSize))
3319 {
3320 return false;
3321 }
3322
Brandon Jonesd1049182018-03-28 10:02:20 -07003323 GLsizei writeLength = 0;
3324
Geoff Langf41d0ee2016-10-07 13:04:23 -04003325 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003326 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3327 {
3328 return false;
3329 }
3330
3331 SetRobustLengthParam(length, writeLength);
3332
3333 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003334}
3335
3336bool ValidateGetUniformivRobustANGLE(Context *context,
3337 GLuint program,
3338 GLint location,
3339 GLsizei bufSize,
3340 GLsizei *length,
3341 GLint *params)
3342{
3343 if (!ValidateRobustEntryPoint(context, bufSize))
3344 {
3345 return false;
3346 }
3347
Brandon Jonesd1049182018-03-28 10:02:20 -07003348 GLsizei writeLength = 0;
3349
Geoff Langf41d0ee2016-10-07 13:04:23 -04003350 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003351 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3352 {
3353 return false;
3354 }
3355
3356 SetRobustLengthParam(length, writeLength);
3357
3358 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003359}
3360
3361bool ValidateGetUniformuivRobustANGLE(Context *context,
3362 GLuint program,
3363 GLint location,
3364 GLsizei bufSize,
3365 GLsizei *length,
3366 GLuint *params)
3367{
3368 if (!ValidateRobustEntryPoint(context, bufSize))
3369 {
3370 return false;
3371 }
3372
3373 if (context->getClientMajorVersion() < 3)
3374 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003375 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003376 return false;
3377 }
3378
Brandon Jonesd1049182018-03-28 10:02:20 -07003379 GLsizei writeLength = 0;
3380
Geoff Langf41d0ee2016-10-07 13:04:23 -04003381 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003382 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3383 {
3384 return false;
3385 }
3386
3387 SetRobustLengthParam(length, writeLength);
3388
3389 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003390}
3391
He Yunchaoced53ae2016-11-29 15:00:51 +08003392bool ValidateDiscardFramebufferBase(Context *context,
3393 GLenum target,
3394 GLsizei numAttachments,
3395 const GLenum *attachments,
3396 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003397{
3398 if (numAttachments < 0)
3399 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003400 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003401 return false;
3402 }
3403
3404 for (GLsizei i = 0; i < numAttachments; ++i)
3405 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003406 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003407 {
3408 if (defaultFramebuffer)
3409 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003410 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003411 return false;
3412 }
3413
3414 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3415 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003416 context->handleError(InvalidOperation() << "Requested color attachment is "
3417 "greater than the maximum supported "
3418 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003419 return false;
3420 }
3421 }
3422 else
3423 {
3424 switch (attachments[i])
3425 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003426 case GL_DEPTH_ATTACHMENT:
3427 case GL_STENCIL_ATTACHMENT:
3428 case GL_DEPTH_STENCIL_ATTACHMENT:
3429 if (defaultFramebuffer)
3430 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003431 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3432 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003433 return false;
3434 }
3435 break;
3436 case GL_COLOR:
3437 case GL_DEPTH:
3438 case GL_STENCIL:
3439 if (!defaultFramebuffer)
3440 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003441 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3442 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003443 return false;
3444 }
3445 break;
3446 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003447 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003448 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003449 }
3450 }
3451 }
3452
3453 return true;
3454}
3455
Austin Kinross6ee1e782015-05-29 17:05:37 -07003456bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3457{
Jamie Madill007530e2017-12-28 14:27:04 -05003458 if (!context->getExtensions().debugMarker)
3459 {
3460 // The debug marker calls should not set error state
3461 // However, it seems reasonable to set an error state if the extension is not enabled
3462 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3463 return false;
3464 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003465
Jamie Madill007530e2017-12-28 14:27:04 -05003466 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003467 if (length < 0)
3468 {
3469 return false;
3470 }
3471
3472 if (marker == nullptr)
3473 {
3474 return false;
3475 }
3476
3477 return true;
3478}
3479
3480bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3481{
Jamie Madill007530e2017-12-28 14:27:04 -05003482 if (!context->getExtensions().debugMarker)
3483 {
3484 // The debug marker calls should not set error state
3485 // However, it seems reasonable to set an error state if the extension is not enabled
3486 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3487 return false;
3488 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003489
Jamie Madill007530e2017-12-28 14:27:04 -05003490 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003491 if (length < 0)
3492 {
3493 return false;
3494 }
3495
3496 if (length > 0 && marker == nullptr)
3497 {
3498 return false;
3499 }
3500
3501 return true;
3502}
3503
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003504bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003505{
Geoff Langa8406172015-07-21 16:53:39 -04003506 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3507 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003508 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003509 return false;
3510 }
3511
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003512 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003513 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003514 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003515 if (!context->getExtensions().eglImage)
3516 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003517 context->handleError(InvalidEnum()
3518 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003519 }
3520 break;
3521
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003522 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003523 if (!context->getExtensions().eglImageExternal)
3524 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003525 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3526 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003527 }
Geoff Langa8406172015-07-21 16:53:39 -04003528 break;
3529
3530 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003531 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003532 return false;
3533 }
3534
Jamie Madill007530e2017-12-28 14:27:04 -05003535 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3536
Jamie Madill61e16b42017-06-19 11:13:23 -04003537 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003538 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003539 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003540 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003541 return false;
3542 }
3543
Jamie Madill007530e2017-12-28 14:27:04 -05003544 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003545 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003546 context->handleError(InvalidOperation()
3547 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003548 return false;
3549 }
3550
Geoff Langca271392017-04-05 12:30:00 -04003551 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003552 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003553 if (!textureCaps.texturable)
3554 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003555 context->handleError(InvalidOperation()
3556 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003557 return false;
3558 }
3559
Geoff Langdcab33b2015-07-21 13:03:16 -04003560 return true;
3561}
3562
3563bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003564 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003565 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003566{
Geoff Langa8406172015-07-21 16:53:39 -04003567 if (!context->getExtensions().eglImage)
3568 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003569 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003570 return false;
3571 }
3572
3573 switch (target)
3574 {
3575 case GL_RENDERBUFFER:
3576 break;
3577
3578 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003579 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003580 return false;
3581 }
3582
Jamie Madill007530e2017-12-28 14:27:04 -05003583 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3584
Jamie Madill61e16b42017-06-19 11:13:23 -04003585 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003586 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003587 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003588 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003589 return false;
3590 }
3591
Geoff Langca271392017-04-05 12:30:00 -04003592 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003593 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003594 if (!textureCaps.renderable)
3595 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003596 context->handleError(InvalidOperation()
3597 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003598 return false;
3599 }
3600
Geoff Langdcab33b2015-07-21 13:03:16 -04003601 return true;
3602}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003603
3604bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3605{
Geoff Lang36167ab2015-12-07 10:27:14 -05003606 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003607 {
3608 // The default VAO should always exist
3609 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003610 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003611 return false;
3612 }
3613
3614 return true;
3615}
3616
Geoff Langc5629752015-12-07 16:29:04 -05003617bool ValidateProgramBinaryBase(Context *context,
3618 GLuint program,
3619 GLenum binaryFormat,
3620 const void *binary,
3621 GLint length)
3622{
3623 Program *programObject = GetValidProgram(context, program);
3624 if (programObject == nullptr)
3625 {
3626 return false;
3627 }
3628
3629 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3630 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3631 programBinaryFormats.end())
3632 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003633 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003634 return false;
3635 }
3636
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003637 if (context->hasActiveTransformFeedback(program))
3638 {
3639 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003640 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3641 "is associated with an active transform "
3642 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003643 return false;
3644 }
3645
Geoff Langc5629752015-12-07 16:29:04 -05003646 return true;
3647}
3648
3649bool ValidateGetProgramBinaryBase(Context *context,
3650 GLuint program,
3651 GLsizei bufSize,
3652 GLsizei *length,
3653 GLenum *binaryFormat,
3654 void *binary)
3655{
3656 Program *programObject = GetValidProgram(context, program);
3657 if (programObject == nullptr)
3658 {
3659 return false;
3660 }
3661
3662 if (!programObject->isLinked())
3663 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003664 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003665 return false;
3666 }
3667
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003668 if (context->getCaps().programBinaryFormats.empty())
3669 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003670 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003671 return false;
3672 }
3673
Geoff Langc5629752015-12-07 16:29:04 -05003674 return true;
3675}
Jamie Madillc29968b2016-01-20 11:17:23 -05003676
Jamie Madill5b772312018-03-08 20:28:32 -05003677bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003678{
3679 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003680 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003681 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003682 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3683 return false;
3684 }
3685 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3686 {
3687 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003688 return false;
3689 }
3690
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003691 ASSERT(context->getGLState().getDrawFramebuffer());
3692 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003693 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3694
3695 // This should come first before the check for the default frame buffer
3696 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3697 // rather than INVALID_OPERATION
3698 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3699 {
3700 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3701
3702 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003703 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3704 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003705 {
3706 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003707 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3708 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3709 // 3.1 is still a bit ambiguous about the error, but future specs are
3710 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003711 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003712 return false;
3713 }
3714 else if (bufs[colorAttachment] >= maxColorAttachment)
3715 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003716 context->handleError(InvalidOperation()
3717 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003718 return false;
3719 }
3720 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3721 frameBufferId != 0)
3722 {
3723 // INVALID_OPERATION-GL is bound to buffer and ith argument
3724 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003725 context->handleError(InvalidOperation()
3726 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003727 return false;
3728 }
3729 }
3730
3731 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3732 // and n is not 1 or bufs is bound to value other than BACK and NONE
3733 if (frameBufferId == 0)
3734 {
3735 if (n != 1)
3736 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003737 context->handleError(InvalidOperation()
3738 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003739 return false;
3740 }
3741
3742 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3743 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003744 context->handleError(
3745 InvalidOperation()
3746 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003747 return false;
3748 }
3749 }
3750
3751 return true;
3752}
3753
Geoff Lang496c02d2016-10-20 11:38:11 -07003754bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003755 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003756 GLenum pname,
3757 GLsizei *length,
3758 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003759{
Geoff Lang496c02d2016-10-20 11:38:11 -07003760 if (length)
3761 {
3762 *length = 0;
3763 }
3764
3765 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3766 {
3767 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003768 InvalidOperation()
3769 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003770 return false;
3771 }
3772
Corentin Walleze4477002017-12-01 14:39:58 -05003773 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003774 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003775 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003776 return false;
3777 }
3778
Geoff Lang496c02d2016-10-20 11:38:11 -07003779 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003780 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003781 case GL_BUFFER_MAP_POINTER:
3782 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003783
Geoff Lang496c02d2016-10-20 11:38:11 -07003784 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003785 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003786 return false;
3787 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003788
3789 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3790 // target bound to zero generate an INVALID_OPERATION error."
3791 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003792 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003793 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003794 context->handleError(InvalidOperation()
3795 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003796 return false;
3797 }
3798
Geoff Lang496c02d2016-10-20 11:38:11 -07003799 if (length)
3800 {
3801 *length = 1;
3802 }
3803
Olli Etuaho4f667482016-03-30 15:56:35 +03003804 return true;
3805}
3806
Corentin Wallez336129f2017-10-17 15:55:40 -04003807bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003808{
Corentin Walleze4477002017-12-01 14:39:58 -05003809 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003810 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003811 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003812 return false;
3813 }
3814
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003815 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003816
3817 if (buffer == nullptr || !buffer->isMapped())
3818 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003819 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003820 return false;
3821 }
3822
3823 return true;
3824}
3825
3826bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003827 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003828 GLintptr offset,
3829 GLsizeiptr length,
3830 GLbitfield access)
3831{
Corentin Walleze4477002017-12-01 14:39:58 -05003832 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003833 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003834 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003835 return false;
3836 }
3837
Brandon Jones6cad5662017-06-14 13:25:13 -07003838 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003839 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003840 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3841 return false;
3842 }
3843
3844 if (length < 0)
3845 {
3846 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003847 return false;
3848 }
3849
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003850 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003851
3852 if (!buffer)
3853 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003854 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003855 return false;
3856 }
3857
3858 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003859 CheckedNumeric<size_t> checkedOffset(offset);
3860 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003861
Jamie Madille2e406c2016-06-02 13:04:10 -04003862 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003863 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003864 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003865 return false;
3866 }
3867
3868 // Check for invalid bits in the mask
3869 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3870 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3871 GL_MAP_UNSYNCHRONIZED_BIT;
3872
3873 if (access & ~(allAccessBits))
3874 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003875 context->handleError(InvalidValue()
3876 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003877 return false;
3878 }
3879
3880 if (length == 0)
3881 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003882 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003883 return false;
3884 }
3885
3886 if (buffer->isMapped())
3887 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003888 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003889 return false;
3890 }
3891
3892 // Check for invalid bit combinations
3893 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3894 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003895 context->handleError(InvalidOperation()
3896 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003897 return false;
3898 }
3899
3900 GLbitfield writeOnlyBits =
3901 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3902
3903 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3904 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003905 context->handleError(InvalidOperation()
3906 << "Invalid access bits when mapping buffer for reading: 0x"
3907 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003908 return false;
3909 }
3910
3911 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3912 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003913 context->handleError(
3914 InvalidOperation()
3915 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003916 return false;
3917 }
Geoff Lang79f71042017-08-14 16:43:43 -04003918
3919 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003920}
3921
3922bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003923 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003924 GLintptr offset,
3925 GLsizeiptr length)
3926{
Brandon Jones6cad5662017-06-14 13:25:13 -07003927 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003928 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003929 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3930 return false;
3931 }
3932
3933 if (length < 0)
3934 {
3935 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003936 return false;
3937 }
3938
Corentin Walleze4477002017-12-01 14:39:58 -05003939 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003940 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003941 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003942 return false;
3943 }
3944
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003945 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003946
3947 if (buffer == nullptr)
3948 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003949 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003950 return false;
3951 }
3952
3953 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3954 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003955 context->handleError(InvalidOperation()
3956 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003957 return false;
3958 }
3959
3960 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003961 CheckedNumeric<size_t> checkedOffset(offset);
3962 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003963
Jamie Madille2e406c2016-06-02 13:04:10 -04003964 if (!checkedSize.IsValid() ||
3965 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003966 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003967 context->handleError(InvalidValue()
3968 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003969 return false;
3970 }
3971
3972 return true;
3973}
3974
Olli Etuaho41997e72016-03-10 13:38:39 +02003975bool ValidateGenOrDelete(Context *context, GLint n)
3976{
3977 if (n < 0)
3978 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003979 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003980 return false;
3981 }
3982 return true;
3983}
3984
Jamie Madill5b772312018-03-08 20:28:32 -05003985bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04003986{
3987 if (!context->getExtensions().robustClientMemory)
3988 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003989 context->handleError(InvalidOperation()
3990 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003991 return false;
3992 }
3993
3994 if (bufSize < 0)
3995 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003996 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003997 return false;
3998 }
3999
4000 return true;
4001}
4002
Jamie Madill5b772312018-03-08 20:28:32 -05004003bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004004{
4005 if (bufSize < numParams)
4006 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004007 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4008 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004009 return false;
4010 }
4011
4012 return true;
4013}
4014
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004015bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004016 GLenum target,
4017 GLenum attachment,
4018 GLenum pname,
4019 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004020{
Geoff Lange8afa902017-09-27 15:00:43 -04004021 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004022 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004023 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004024 return false;
4025 }
4026
4027 int clientVersion = context->getClientMajorVersion();
4028
4029 switch (pname)
4030 {
4031 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4032 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4033 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4034 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4035 break;
4036
Martin Radeve5285d22017-07-14 16:23:53 +03004037 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4038 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4039 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4040 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4041 if (clientVersion < 3 || !context->getExtensions().multiview)
4042 {
4043 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4044 return false;
4045 }
4046 break;
4047
Geoff Langff5b2d52016-09-07 11:32:23 -04004048 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4049 if (clientVersion < 3 && !context->getExtensions().sRGB)
4050 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004051 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004052 return false;
4053 }
4054 break;
4055
4056 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4057 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4058 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4059 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4060 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4061 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4062 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4063 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4064 if (clientVersion < 3)
4065 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004066 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004067 return false;
4068 }
4069 break;
4070
4071 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004072 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004073 return false;
4074 }
4075
4076 // Determine if the attachment is a valid enum
4077 switch (attachment)
4078 {
4079 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004080 case GL_DEPTH:
4081 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004082 if (clientVersion < 3)
4083 {
Geoff Langfa125c92017-10-24 13:01:46 -04004084 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004085 return false;
4086 }
4087 break;
4088
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004089 case GL_DEPTH_STENCIL_ATTACHMENT:
4090 if (clientVersion < 3 && !context->isWebGL1())
4091 {
4092 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4093 return false;
4094 }
4095 break;
4096
Geoff Langfa125c92017-10-24 13:01:46 -04004097 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004098 case GL_DEPTH_ATTACHMENT:
4099 case GL_STENCIL_ATTACHMENT:
4100 break;
4101
4102 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004103 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4104 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004105 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4106 {
Geoff Langfa125c92017-10-24 13:01:46 -04004107 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004108 return false;
4109 }
4110 break;
4111 }
4112
4113 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4114 ASSERT(framebuffer);
4115
4116 if (framebuffer->id() == 0)
4117 {
4118 if (clientVersion < 3)
4119 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004120 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004121 return false;
4122 }
4123
4124 switch (attachment)
4125 {
4126 case GL_BACK:
4127 case GL_DEPTH:
4128 case GL_STENCIL:
4129 break;
4130
4131 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004132 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004133 return false;
4134 }
4135 }
4136 else
4137 {
4138 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4139 {
4140 // Valid attachment query
4141 }
4142 else
4143 {
4144 switch (attachment)
4145 {
4146 case GL_DEPTH_ATTACHMENT:
4147 case GL_STENCIL_ATTACHMENT:
4148 break;
4149
4150 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004151 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004152 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004153 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004154 return false;
4155 }
4156 break;
4157
4158 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004159 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004160 return false;
4161 }
4162 }
4163 }
4164
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004165 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004166 if (attachmentObject)
4167 {
4168 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4169 attachmentObject->type() == GL_TEXTURE ||
4170 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4171
4172 switch (pname)
4173 {
4174 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4175 if (attachmentObject->type() != GL_RENDERBUFFER &&
4176 attachmentObject->type() != GL_TEXTURE)
4177 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004178 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004179 return false;
4180 }
4181 break;
4182
4183 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4184 if (attachmentObject->type() != GL_TEXTURE)
4185 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004186 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004187 return false;
4188 }
4189 break;
4190
4191 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4192 if (attachmentObject->type() != GL_TEXTURE)
4193 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004194 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004195 return false;
4196 }
4197 break;
4198
4199 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4200 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4201 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004202 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004203 return false;
4204 }
4205 break;
4206
4207 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4208 if (attachmentObject->type() != GL_TEXTURE)
4209 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004210 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004211 return false;
4212 }
4213 break;
4214
4215 default:
4216 break;
4217 }
4218 }
4219 else
4220 {
4221 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4222 // is NONE, then querying any other pname will generate INVALID_ENUM.
4223
4224 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4225 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4226 // INVALID_OPERATION for all other pnames
4227
4228 switch (pname)
4229 {
4230 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4231 break;
4232
4233 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4234 if (clientVersion < 3)
4235 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004236 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004237 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004238 return false;
4239 }
4240 break;
4241
4242 default:
4243 if (clientVersion < 3)
4244 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004245 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004246 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004247 return false;
4248 }
4249 else
4250 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004251 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004252 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004253 return false;
4254 }
4255 }
4256 }
4257
Martin Radeve5285d22017-07-14 16:23:53 +03004258 if (numParams)
4259 {
4260 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4261 {
4262 // Only when the viewport offsets are queried we can have a varying number of output
4263 // parameters.
4264 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4265 *numParams = numViews * 2;
4266 }
4267 else
4268 {
4269 // For all other queries we can have only one output parameter.
4270 *numParams = 1;
4271 }
4272 }
4273
Geoff Langff5b2d52016-09-07 11:32:23 -04004274 return true;
4275}
4276
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004277bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004278 GLenum target,
4279 GLenum attachment,
4280 GLenum pname,
4281 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004282 GLsizei *length,
4283 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004284{
4285 if (!ValidateRobustEntryPoint(context, bufSize))
4286 {
4287 return false;
4288 }
4289
Brandon Jonesd1049182018-03-28 10:02:20 -07004290 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004291 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004292 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004293 {
4294 return false;
4295 }
4296
Brandon Jonesd1049182018-03-28 10:02:20 -07004297 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004298 {
4299 return false;
4300 }
4301
Brandon Jonesd1049182018-03-28 10:02:20 -07004302 SetRobustLengthParam(length, numParams);
4303
Geoff Langff5b2d52016-09-07 11:32:23 -04004304 return true;
4305}
4306
Jamie Madill5b772312018-03-08 20:28:32 -05004307bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004308 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004309 GLenum pname,
4310 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004311 GLsizei *length,
4312 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004313{
4314 if (!ValidateRobustEntryPoint(context, bufSize))
4315 {
4316 return false;
4317 }
4318
Brandon Jonesd1049182018-03-28 10:02:20 -07004319 GLsizei numParams = 0;
4320
4321 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004322 {
4323 return false;
4324 }
4325
Brandon Jonesd1049182018-03-28 10:02:20 -07004326 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004327 {
4328 return false;
4329 }
4330
Brandon Jonesd1049182018-03-28 10:02:20 -07004331 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004332 return true;
4333}
4334
Jamie Madill5b772312018-03-08 20:28:32 -05004335bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004336 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004337 GLenum pname,
4338 GLsizei bufSize,
4339 GLsizei *length,
4340 GLint64 *params)
4341{
Brandon Jonesd1049182018-03-28 10:02:20 -07004342 GLsizei numParams = 0;
4343
Geoff Langebebe1c2016-10-14 12:01:31 -04004344 if (!ValidateRobustEntryPoint(context, bufSize))
4345 {
4346 return false;
4347 }
4348
Brandon Jonesd1049182018-03-28 10:02:20 -07004349 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004350 {
4351 return false;
4352 }
4353
Brandon Jonesd1049182018-03-28 10:02:20 -07004354 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004355 {
4356 return false;
4357 }
4358
Brandon Jonesd1049182018-03-28 10:02:20 -07004359 SetRobustLengthParam(length, numParams);
4360
Geoff Langff5b2d52016-09-07 11:32:23 -04004361 return true;
4362}
4363
Jamie Madill5b772312018-03-08 20:28:32 -05004364bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004365{
4366 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004367 if (numParams)
4368 {
4369 *numParams = 1;
4370 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004371
4372 Program *programObject = GetValidProgram(context, program);
4373 if (!programObject)
4374 {
4375 return false;
4376 }
4377
4378 switch (pname)
4379 {
4380 case GL_DELETE_STATUS:
4381 case GL_LINK_STATUS:
4382 case GL_VALIDATE_STATUS:
4383 case GL_INFO_LOG_LENGTH:
4384 case GL_ATTACHED_SHADERS:
4385 case GL_ACTIVE_ATTRIBUTES:
4386 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4387 case GL_ACTIVE_UNIFORMS:
4388 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4389 break;
4390
4391 case GL_PROGRAM_BINARY_LENGTH:
4392 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4393 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004394 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4395 "requires GL_OES_get_program_binary or "
4396 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004397 return false;
4398 }
4399 break;
4400
4401 case GL_ACTIVE_UNIFORM_BLOCKS:
4402 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4403 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4404 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4405 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4406 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4407 if (context->getClientMajorVersion() < 3)
4408 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004409 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004410 return false;
4411 }
4412 break;
4413
Yunchao He61afff12017-03-14 15:34:03 +08004414 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004415 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004416 if (context->getClientVersion() < Version(3, 1))
4417 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004418 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004419 return false;
4420 }
4421 break;
4422
Jiawei Shao6ae51612018-02-23 14:03:25 +08004423 case GL_COMPUTE_WORK_GROUP_SIZE:
4424 if (context->getClientVersion() < Version(3, 1))
4425 {
4426 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4427 return false;
4428 }
4429
4430 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4431 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4432 // program which has not been linked successfully, or which does not contain objects to
4433 // form a compute shader.
4434 if (!programObject->isLinked())
4435 {
4436 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4437 return false;
4438 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004439 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004440 {
4441 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4442 return false;
4443 }
4444 break;
4445
Jiawei Shao447bfac2018-03-14 14:23:40 +08004446 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4447 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4448 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4449 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4450 if (!context->getExtensions().geometryShader)
4451 {
4452 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4453 return false;
4454 }
4455
4456 // [EXT_geometry_shader] Chapter 7.12
4457 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4458 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4459 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4460 // successfully, or which does not contain objects to form a geometry shader.
4461 if (!programObject->isLinked())
4462 {
4463 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4464 return false;
4465 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004466 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004467 {
4468 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4469 return false;
4470 }
4471 break;
4472
Geoff Langff5b2d52016-09-07 11:32:23 -04004473 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004474 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004475 return false;
4476 }
4477
4478 return true;
4479}
4480
4481bool ValidateGetProgramivRobustANGLE(Context *context,
4482 GLuint program,
4483 GLenum pname,
4484 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004485 GLsizei *length,
4486 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004487{
4488 if (!ValidateRobustEntryPoint(context, bufSize))
4489 {
4490 return false;
4491 }
4492
Brandon Jonesd1049182018-03-28 10:02:20 -07004493 GLsizei numParams = 0;
4494
4495 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004496 {
4497 return false;
4498 }
4499
Brandon Jonesd1049182018-03-28 10:02:20 -07004500 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004501 {
4502 return false;
4503 }
4504
Brandon Jonesd1049182018-03-28 10:02:20 -07004505 SetRobustLengthParam(length, numParams);
4506
Geoff Langff5b2d52016-09-07 11:32:23 -04004507 return true;
4508}
4509
Geoff Lang740d9022016-10-07 11:20:52 -04004510bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4511 GLenum target,
4512 GLenum pname,
4513 GLsizei bufSize,
4514 GLsizei *length,
4515 GLint *params)
4516{
4517 if (!ValidateRobustEntryPoint(context, bufSize))
4518 {
4519 return false;
4520 }
4521
Brandon Jonesd1049182018-03-28 10:02:20 -07004522 GLsizei numParams = 0;
4523
4524 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004525 {
4526 return false;
4527 }
4528
Brandon Jonesd1049182018-03-28 10:02:20 -07004529 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004530 {
4531 return false;
4532 }
4533
Brandon Jonesd1049182018-03-28 10:02:20 -07004534 SetRobustLengthParam(length, numParams);
4535
Geoff Lang740d9022016-10-07 11:20:52 -04004536 return true;
4537}
4538
Geoff Langd7d0ed32016-10-07 11:33:51 -04004539bool ValidateGetShaderivRobustANGLE(Context *context,
4540 GLuint shader,
4541 GLenum pname,
4542 GLsizei bufSize,
4543 GLsizei *length,
4544 GLint *params)
4545{
4546 if (!ValidateRobustEntryPoint(context, bufSize))
4547 {
4548 return false;
4549 }
4550
Brandon Jonesd1049182018-03-28 10:02:20 -07004551 GLsizei numParams = 0;
4552
4553 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004554 {
4555 return false;
4556 }
4557
Brandon Jonesd1049182018-03-28 10:02:20 -07004558 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004559 {
4560 return false;
4561 }
4562
Brandon Jonesd1049182018-03-28 10:02:20 -07004563 SetRobustLengthParam(length, numParams);
4564
Geoff Langd7d0ed32016-10-07 11:33:51 -04004565 return true;
4566}
4567
Geoff Langc1984ed2016-10-07 12:41:00 -04004568bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004569 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004570 GLenum pname,
4571 GLsizei bufSize,
4572 GLsizei *length,
4573 GLfloat *params)
4574{
4575 if (!ValidateRobustEntryPoint(context, bufSize))
4576 {
4577 return false;
4578 }
4579
Brandon Jonesd1049182018-03-28 10:02:20 -07004580 GLsizei numParams = 0;
4581
4582 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004583 {
4584 return false;
4585 }
4586
Brandon Jonesd1049182018-03-28 10:02:20 -07004587 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004588 {
4589 return false;
4590 }
4591
Brandon Jonesd1049182018-03-28 10:02:20 -07004592 SetRobustLengthParam(length, numParams);
4593
Geoff Langc1984ed2016-10-07 12:41:00 -04004594 return true;
4595}
4596
Geoff Langc1984ed2016-10-07 12:41:00 -04004597bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004598 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004599 GLenum pname,
4600 GLsizei bufSize,
4601 GLsizei *length,
4602 GLint *params)
4603{
Brandon Jonesd1049182018-03-28 10:02:20 -07004604
Geoff Langc1984ed2016-10-07 12:41:00 -04004605 if (!ValidateRobustEntryPoint(context, bufSize))
4606 {
4607 return false;
4608 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004609 GLsizei numParams = 0;
4610 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004611 {
4612 return false;
4613 }
4614
Brandon Jonesd1049182018-03-28 10:02:20 -07004615 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004616 {
4617 return false;
4618 }
4619
Brandon Jonesd1049182018-03-28 10:02:20 -07004620 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004621 return true;
4622}
4623
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004624bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4625 TextureType target,
4626 GLenum pname,
4627 GLsizei bufSize,
4628 GLsizei *length,
4629 GLint *params)
4630{
4631 UNIMPLEMENTED();
4632 return false;
4633}
4634
4635bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4636 TextureType target,
4637 GLenum pname,
4638 GLsizei bufSize,
4639 GLsizei *length,
4640 GLuint *params)
4641{
4642 UNIMPLEMENTED();
4643 return false;
4644}
4645
Geoff Langc1984ed2016-10-07 12:41:00 -04004646bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004647 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004648 GLenum pname,
4649 GLsizei bufSize,
4650 const GLfloat *params)
4651{
4652 if (!ValidateRobustEntryPoint(context, bufSize))
4653 {
4654 return false;
4655 }
4656
4657 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4658}
4659
Geoff Langc1984ed2016-10-07 12:41:00 -04004660bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004661 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004662 GLenum pname,
4663 GLsizei bufSize,
4664 const GLint *params)
4665{
4666 if (!ValidateRobustEntryPoint(context, bufSize))
4667 {
4668 return false;
4669 }
4670
4671 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4672}
4673
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004674bool ValidateTexParameterIivRobustANGLE(Context *context,
4675 TextureType target,
4676 GLenum pname,
4677 GLsizei bufSize,
4678 const GLint *params)
4679{
4680 UNIMPLEMENTED();
4681 return false;
4682}
4683
4684bool ValidateTexParameterIuivRobustANGLE(Context *context,
4685 TextureType target,
4686 GLenum pname,
4687 GLsizei bufSize,
4688 const GLuint *params)
4689{
4690 UNIMPLEMENTED();
4691 return false;
4692}
4693
Geoff Langc1984ed2016-10-07 12:41:00 -04004694bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4695 GLuint sampler,
4696 GLenum pname,
4697 GLuint bufSize,
4698 GLsizei *length,
4699 GLfloat *params)
4700{
4701 if (!ValidateRobustEntryPoint(context, bufSize))
4702 {
4703 return false;
4704 }
4705
Brandon Jonesd1049182018-03-28 10:02:20 -07004706 GLsizei numParams = 0;
4707
4708 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004709 {
4710 return false;
4711 }
4712
Brandon Jonesd1049182018-03-28 10:02:20 -07004713 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004714 {
4715 return false;
4716 }
4717
Brandon Jonesd1049182018-03-28 10:02:20 -07004718 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004719 return true;
4720}
4721
Geoff Langc1984ed2016-10-07 12:41:00 -04004722bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4723 GLuint sampler,
4724 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004725 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004726 GLsizei *length,
4727 GLint *params)
4728{
4729 if (!ValidateRobustEntryPoint(context, bufSize))
4730 {
4731 return false;
4732 }
4733
Brandon Jonesd1049182018-03-28 10:02:20 -07004734 GLsizei numParams = 0;
4735
4736 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004737 {
4738 return false;
4739 }
4740
Brandon Jonesd1049182018-03-28 10:02:20 -07004741 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004742 {
4743 return false;
4744 }
4745
Brandon Jonesd1049182018-03-28 10:02:20 -07004746 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004747 return true;
4748}
4749
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004750bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4751 GLuint sampler,
4752 GLenum pname,
4753 GLsizei bufSize,
4754 GLsizei *length,
4755 GLint *params)
4756{
4757 UNIMPLEMENTED();
4758 return false;
4759}
4760
4761bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4762 GLuint sampler,
4763 GLenum pname,
4764 GLsizei bufSize,
4765 GLsizei *length,
4766 GLuint *params)
4767{
4768 UNIMPLEMENTED();
4769 return false;
4770}
4771
Geoff Langc1984ed2016-10-07 12:41:00 -04004772bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4773 GLuint sampler,
4774 GLenum pname,
4775 GLsizei bufSize,
4776 const GLfloat *params)
4777{
4778 if (!ValidateRobustEntryPoint(context, bufSize))
4779 {
4780 return false;
4781 }
4782
4783 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4784}
4785
Geoff Langc1984ed2016-10-07 12:41:00 -04004786bool ValidateSamplerParameterivRobustANGLE(Context *context,
4787 GLuint sampler,
4788 GLenum pname,
4789 GLsizei bufSize,
4790 const GLint *params)
4791{
4792 if (!ValidateRobustEntryPoint(context, bufSize))
4793 {
4794 return false;
4795 }
4796
4797 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4798}
4799
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004800bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4801 GLuint sampler,
4802 GLenum pname,
4803 GLsizei bufSize,
4804 const GLint *param)
4805{
4806 UNIMPLEMENTED();
4807 return false;
4808}
4809
4810bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4811 GLuint sampler,
4812 GLenum pname,
4813 GLsizei bufSize,
4814 const GLuint *param)
4815{
4816 UNIMPLEMENTED();
4817 return false;
4818}
4819
Geoff Lang0b031062016-10-13 14:30:04 -04004820bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4821 GLuint index,
4822 GLenum pname,
4823 GLsizei bufSize,
4824 GLsizei *length,
4825 GLfloat *params)
4826{
4827 if (!ValidateRobustEntryPoint(context, bufSize))
4828 {
4829 return false;
4830 }
4831
Brandon Jonesd1049182018-03-28 10:02:20 -07004832 GLsizei writeLength = 0;
4833
4834 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004835 {
4836 return false;
4837 }
4838
Brandon Jonesd1049182018-03-28 10:02:20 -07004839 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004840 {
4841 return false;
4842 }
4843
Brandon Jonesd1049182018-03-28 10:02:20 -07004844 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004845 return true;
4846}
4847
Geoff Lang0b031062016-10-13 14:30:04 -04004848bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4849 GLuint index,
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 (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004863 {
4864 return false;
4865 }
4866
Brandon Jonesd1049182018-03-28 10:02:20 -07004867 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004868 {
4869 return false;
4870 }
4871
Brandon Jonesd1049182018-03-28 10:02:20 -07004872 SetRobustLengthParam(length, writeLength);
4873
Geoff Lang0b031062016-10-13 14:30:04 -04004874 return true;
4875}
4876
Geoff Lang0b031062016-10-13 14:30:04 -04004877bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4878 GLuint index,
4879 GLenum pname,
4880 GLsizei bufSize,
4881 GLsizei *length,
4882 void **pointer)
4883{
4884 if (!ValidateRobustEntryPoint(context, bufSize))
4885 {
4886 return false;
4887 }
4888
Brandon Jonesd1049182018-03-28 10:02:20 -07004889 GLsizei writeLength = 0;
4890
4891 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004892 {
4893 return false;
4894 }
4895
Brandon Jonesd1049182018-03-28 10:02:20 -07004896 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004897 {
4898 return false;
4899 }
4900
Brandon Jonesd1049182018-03-28 10:02:20 -07004901 SetRobustLengthParam(length, writeLength);
4902
Geoff Lang0b031062016-10-13 14:30:04 -04004903 return true;
4904}
4905
Geoff Lang0b031062016-10-13 14:30:04 -04004906bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4907 GLuint index,
4908 GLenum pname,
4909 GLsizei bufSize,
4910 GLsizei *length,
4911 GLint *params)
4912{
4913 if (!ValidateRobustEntryPoint(context, bufSize))
4914 {
4915 return false;
4916 }
4917
Brandon Jonesd1049182018-03-28 10:02:20 -07004918 GLsizei writeLength = 0;
4919
4920 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004921 {
4922 return false;
4923 }
4924
Brandon Jonesd1049182018-03-28 10:02:20 -07004925 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004926 {
4927 return false;
4928 }
4929
Brandon Jonesd1049182018-03-28 10:02:20 -07004930 SetRobustLengthParam(length, writeLength);
4931
Geoff Lang0b031062016-10-13 14:30:04 -04004932 return true;
4933}
4934
Geoff Lang0b031062016-10-13 14:30:04 -04004935bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4936 GLuint index,
4937 GLenum pname,
4938 GLsizei bufSize,
4939 GLsizei *length,
4940 GLuint *params)
4941{
4942 if (!ValidateRobustEntryPoint(context, bufSize))
4943 {
4944 return false;
4945 }
4946
Brandon Jonesd1049182018-03-28 10:02:20 -07004947 GLsizei writeLength = 0;
4948
4949 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04004950 {
4951 return false;
4952 }
4953
Brandon Jonesd1049182018-03-28 10:02:20 -07004954 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004955 {
4956 return false;
4957 }
4958
Brandon Jonesd1049182018-03-28 10:02:20 -07004959 SetRobustLengthParam(length, writeLength);
4960
Geoff Lang0b031062016-10-13 14:30:04 -04004961 return true;
4962}
4963
Geoff Lang6899b872016-10-14 11:30:13 -04004964bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4965 GLuint program,
4966 GLuint uniformBlockIndex,
4967 GLenum pname,
4968 GLsizei bufSize,
4969 GLsizei *length,
4970 GLint *params)
4971{
4972 if (!ValidateRobustEntryPoint(context, bufSize))
4973 {
4974 return false;
4975 }
4976
Brandon Jonesd1049182018-03-28 10:02:20 -07004977 GLsizei writeLength = 0;
4978
4979 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
4980 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004981 {
4982 return false;
4983 }
4984
Brandon Jonesd1049182018-03-28 10:02:20 -07004985 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04004986 {
4987 return false;
4988 }
4989
Brandon Jonesd1049182018-03-28 10:02:20 -07004990 SetRobustLengthParam(length, writeLength);
4991
Geoff Lang6899b872016-10-14 11:30:13 -04004992 return true;
4993}
4994
Geoff Lang0a9661f2016-10-20 10:59:20 -07004995bool ValidateGetInternalFormativRobustANGLE(Context *context,
4996 GLenum target,
4997 GLenum internalformat,
4998 GLenum pname,
4999 GLsizei bufSize,
5000 GLsizei *length,
5001 GLint *params)
5002{
5003 if (!ValidateRobustEntryPoint(context, bufSize))
5004 {
5005 return false;
5006 }
5007
Brandon Jonesd1049182018-03-28 10:02:20 -07005008 GLsizei numParams = 0;
5009
5010 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5011 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005012 {
5013 return false;
5014 }
5015
Brandon Jonesd1049182018-03-28 10:02:20 -07005016 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005017 {
5018 return false;
5019 }
5020
Brandon Jonesd1049182018-03-28 10:02:20 -07005021 SetRobustLengthParam(length, numParams);
5022
Geoff Lang0a9661f2016-10-20 10:59:20 -07005023 return true;
5024}
5025
Jamie Madill5b772312018-03-08 20:28:32 -05005026bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005027 GLuint attribIndex,
5028 GLint size,
5029 GLenum type,
5030 GLboolean pureInteger)
5031{
5032 const Caps &caps = context->getCaps();
5033 if (attribIndex >= caps.maxVertexAttributes)
5034 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005035 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005036 return false;
5037 }
5038
5039 if (size < 1 || size > 4)
5040 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005041 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005042 return false;
Shao80957d92017-02-20 21:25:59 +08005043 }
5044
5045 switch (type)
5046 {
5047 case GL_BYTE:
5048 case GL_UNSIGNED_BYTE:
5049 case GL_SHORT:
5050 case GL_UNSIGNED_SHORT:
5051 break;
5052
5053 case GL_INT:
5054 case GL_UNSIGNED_INT:
5055 if (context->getClientMajorVersion() < 3)
5056 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005057 context->handleError(InvalidEnum()
5058 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005059 return false;
5060 }
5061 break;
5062
5063 case GL_FIXED:
5064 case GL_FLOAT:
5065 if (pureInteger)
5066 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005067 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005068 return false;
5069 }
5070 break;
5071
5072 case GL_HALF_FLOAT:
5073 if (context->getClientMajorVersion() < 3)
5074 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005075 context->handleError(InvalidEnum()
5076 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005077 return false;
5078 }
5079 if (pureInteger)
5080 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005081 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005082 return false;
5083 }
5084 break;
5085
5086 case GL_INT_2_10_10_10_REV:
5087 case GL_UNSIGNED_INT_2_10_10_10_REV:
5088 if (context->getClientMajorVersion() < 3)
5089 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005090 context->handleError(InvalidEnum()
5091 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005092 return false;
5093 }
5094 if (pureInteger)
5095 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005096 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005097 return false;
5098 }
5099 if (size != 4)
5100 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005101 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5102 "UNSIGNED_INT_2_10_10_10_REV and "
5103 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005104 return false;
5105 }
5106 break;
5107
5108 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005109 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005110 return false;
5111 }
5112
5113 return true;
5114}
5115
Geoff Lang76e65652017-03-27 14:58:02 -04005116// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5117// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5118// specified clear value and the type of a buffer that is being cleared generates an
5119// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005120bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005121 GLint drawbuffer,
5122 const GLenum *validComponentTypes,
5123 size_t validComponentTypeCount)
5124{
5125 const FramebufferAttachment *attachment =
5126 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5127 if (attachment)
5128 {
5129 GLenum componentType = attachment->getFormat().info->componentType;
5130 const GLenum *end = validComponentTypes + validComponentTypeCount;
5131 if (std::find(validComponentTypes, end, componentType) == end)
5132 {
5133 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005134 InvalidOperation()
5135 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005136 return false;
5137 }
5138 }
5139
5140 return true;
5141}
5142
Jamie Madill5b772312018-03-08 20:28:32 -05005143bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005144{
5145 if (!ValidateRobustEntryPoint(context, dataSize))
5146 {
5147 return false;
5148 }
5149
Corentin Wallez336129f2017-10-17 15:55:40 -04005150 gl::Buffer *pixelUnpackBuffer =
5151 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005152 if (pixelUnpackBuffer == nullptr)
5153 {
5154 if (dataSize < imageSize)
5155 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005156 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005157 }
5158 }
5159 return true;
5160}
5161
Jamie Madill5b772312018-03-08 20:28:32 -05005162bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005163 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005164 GLenum pname,
5165 bool pointerVersion,
5166 GLsizei *numParams)
5167{
5168 if (numParams)
5169 {
5170 *numParams = 0;
5171 }
5172
Corentin Walleze4477002017-12-01 14:39:58 -05005173 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005174 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005175 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005176 return false;
5177 }
5178
5179 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5180 if (!buffer)
5181 {
5182 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005183 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005184 return false;
5185 }
5186
5187 const Extensions &extensions = context->getExtensions();
5188
5189 switch (pname)
5190 {
5191 case GL_BUFFER_USAGE:
5192 case GL_BUFFER_SIZE:
5193 break;
5194
5195 case GL_BUFFER_ACCESS_OES:
5196 if (!extensions.mapBuffer)
5197 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005198 context->handleError(InvalidEnum()
5199 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005200 return false;
5201 }
5202 break;
5203
5204 case GL_BUFFER_MAPPED:
5205 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5206 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5207 !extensions.mapBufferRange)
5208 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005209 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5210 "GL_OES_mapbuffer or "
5211 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005212 return false;
5213 }
5214 break;
5215
5216 case GL_BUFFER_MAP_POINTER:
5217 if (!pointerVersion)
5218 {
5219 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005220 InvalidEnum()
5221 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005222 return false;
5223 }
5224 break;
5225
5226 case GL_BUFFER_ACCESS_FLAGS:
5227 case GL_BUFFER_MAP_OFFSET:
5228 case GL_BUFFER_MAP_LENGTH:
5229 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5230 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005231 context->handleError(InvalidEnum()
5232 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005233 return false;
5234 }
5235 break;
5236
5237 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005238 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005239 return false;
5240 }
5241
5242 // All buffer parameter queries return one value.
5243 if (numParams)
5244 {
5245 *numParams = 1;
5246 }
5247
5248 return true;
5249}
5250
5251bool ValidateGetRenderbufferParameterivBase(Context *context,
5252 GLenum target,
5253 GLenum pname,
5254 GLsizei *length)
5255{
5256 if (length)
5257 {
5258 *length = 0;
5259 }
5260
5261 if (target != GL_RENDERBUFFER)
5262 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005263 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005264 return false;
5265 }
5266
5267 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5268 if (renderbuffer == nullptr)
5269 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005270 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005271 return false;
5272 }
5273
5274 switch (pname)
5275 {
5276 case GL_RENDERBUFFER_WIDTH:
5277 case GL_RENDERBUFFER_HEIGHT:
5278 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5279 case GL_RENDERBUFFER_RED_SIZE:
5280 case GL_RENDERBUFFER_GREEN_SIZE:
5281 case GL_RENDERBUFFER_BLUE_SIZE:
5282 case GL_RENDERBUFFER_ALPHA_SIZE:
5283 case GL_RENDERBUFFER_DEPTH_SIZE:
5284 case GL_RENDERBUFFER_STENCIL_SIZE:
5285 break;
5286
5287 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5288 if (!context->getExtensions().framebufferMultisample)
5289 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005290 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005291 return false;
5292 }
5293 break;
5294
5295 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005296 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005297 return false;
5298 }
5299
5300 if (length)
5301 {
5302 *length = 1;
5303 }
5304 return true;
5305}
5306
5307bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5308{
5309 if (length)
5310 {
5311 *length = 0;
5312 }
5313
5314 if (GetValidShader(context, shader) == nullptr)
5315 {
5316 return false;
5317 }
5318
5319 switch (pname)
5320 {
5321 case GL_SHADER_TYPE:
5322 case GL_DELETE_STATUS:
5323 case GL_COMPILE_STATUS:
5324 case GL_INFO_LOG_LENGTH:
5325 case GL_SHADER_SOURCE_LENGTH:
5326 break;
5327
5328 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5329 if (!context->getExtensions().translatedShaderSource)
5330 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005331 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005332 return false;
5333 }
5334 break;
5335
5336 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005337 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005338 return false;
5339 }
5340
5341 if (length)
5342 {
5343 *length = 1;
5344 }
5345 return true;
5346}
5347
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005348bool ValidateGetTexParameterBase(Context *context,
5349 TextureType target,
5350 GLenum pname,
5351 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005352{
5353 if (length)
5354 {
5355 *length = 0;
5356 }
5357
5358 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5359 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005360 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005361 return false;
5362 }
5363
5364 if (context->getTargetTexture(target) == nullptr)
5365 {
5366 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005367 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005368 return false;
5369 }
5370
5371 switch (pname)
5372 {
5373 case GL_TEXTURE_MAG_FILTER:
5374 case GL_TEXTURE_MIN_FILTER:
5375 case GL_TEXTURE_WRAP_S:
5376 case GL_TEXTURE_WRAP_T:
5377 break;
5378
5379 case GL_TEXTURE_USAGE_ANGLE:
5380 if (!context->getExtensions().textureUsage)
5381 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005382 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005383 return false;
5384 }
5385 break;
5386
5387 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005388 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005389 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005390 return false;
5391 }
5392 break;
5393
5394 case GL_TEXTURE_IMMUTABLE_FORMAT:
5395 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5396 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005397 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005398 return false;
5399 }
5400 break;
5401
5402 case GL_TEXTURE_WRAP_R:
5403 case GL_TEXTURE_IMMUTABLE_LEVELS:
5404 case GL_TEXTURE_SWIZZLE_R:
5405 case GL_TEXTURE_SWIZZLE_G:
5406 case GL_TEXTURE_SWIZZLE_B:
5407 case GL_TEXTURE_SWIZZLE_A:
5408 case GL_TEXTURE_BASE_LEVEL:
5409 case GL_TEXTURE_MAX_LEVEL:
5410 case GL_TEXTURE_MIN_LOD:
5411 case GL_TEXTURE_MAX_LOD:
5412 case GL_TEXTURE_COMPARE_MODE:
5413 case GL_TEXTURE_COMPARE_FUNC:
5414 if (context->getClientMajorVersion() < 3)
5415 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005416 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005417 return false;
5418 }
5419 break;
5420
5421 case GL_TEXTURE_SRGB_DECODE_EXT:
5422 if (!context->getExtensions().textureSRGBDecode)
5423 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005424 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005425 return false;
5426 }
5427 break;
5428
Yunchao Hebacaa712018-01-30 14:01:39 +08005429 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5430 if (context->getClientVersion() < Version(3, 1))
5431 {
5432 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5433 return false;
5434 }
5435 break;
5436
Jamie Madillbe849e42017-05-02 15:49:00 -04005437 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005438 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005439 return false;
5440 }
5441
5442 if (length)
5443 {
5444 *length = 1;
5445 }
5446 return true;
5447}
5448
5449bool ValidateGetVertexAttribBase(Context *context,
5450 GLuint index,
5451 GLenum pname,
5452 GLsizei *length,
5453 bool pointer,
5454 bool pureIntegerEntryPoint)
5455{
5456 if (length)
5457 {
5458 *length = 0;
5459 }
5460
5461 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005463 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005464 return false;
5465 }
5466
5467 if (index >= context->getCaps().maxVertexAttributes)
5468 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005469 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005470 return false;
5471 }
5472
5473 if (pointer)
5474 {
5475 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5476 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005477 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005478 return false;
5479 }
5480 }
5481 else
5482 {
5483 switch (pname)
5484 {
5485 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5486 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5487 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5488 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5489 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5490 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5491 case GL_CURRENT_VERTEX_ATTRIB:
5492 break;
5493
5494 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5495 static_assert(
5496 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5497 "ANGLE extension enums not equal to GL enums.");
5498 if (context->getClientMajorVersion() < 3 &&
5499 !context->getExtensions().instancedArrays)
5500 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005501 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5502 "requires OpenGL ES 3.0 or "
5503 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005504 return false;
5505 }
5506 break;
5507
5508 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5509 if (context->getClientMajorVersion() < 3)
5510 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005511 context->handleError(
5512 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005513 return false;
5514 }
5515 break;
5516
5517 case GL_VERTEX_ATTRIB_BINDING:
5518 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5519 if (context->getClientVersion() < ES_3_1)
5520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005521 context->handleError(InvalidEnum()
5522 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005523 return false;
5524 }
5525 break;
5526
5527 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005528 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005529 return false;
5530 }
5531 }
5532
5533 if (length)
5534 {
5535 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5536 {
5537 *length = 4;
5538 }
5539 else
5540 {
5541 *length = 1;
5542 }
5543 }
5544
5545 return true;
5546}
5547
Jamie Madill4928b7c2017-06-20 12:57:39 -04005548bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005549 GLint x,
5550 GLint y,
5551 GLsizei width,
5552 GLsizei height,
5553 GLenum format,
5554 GLenum type,
5555 GLsizei bufSize,
5556 GLsizei *length,
5557 GLsizei *columns,
5558 GLsizei *rows,
5559 void *pixels)
5560{
5561 if (length != nullptr)
5562 {
5563 *length = 0;
5564 }
5565 if (rows != nullptr)
5566 {
5567 *rows = 0;
5568 }
5569 if (columns != nullptr)
5570 {
5571 *columns = 0;
5572 }
5573
5574 if (width < 0 || height < 0)
5575 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005576 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005577 return false;
5578 }
5579
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005580 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005581
Jamie Madille98b1b52018-03-08 09:47:23 -05005582 if (!ValidateFramebufferComplete(context, readFramebuffer, true))
Jamie Madillbe849e42017-05-02 15:49:00 -04005583 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005584 return false;
5585 }
5586
Jamie Madille98b1b52018-03-08 09:47:23 -05005587 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005588 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005589 return false;
5590 }
5591
Jamie Madill690c8eb2018-03-12 15:20:03 -04005592 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005593 ASSERT(framebuffer);
5594
5595 if (framebuffer->getReadBufferState() == GL_NONE)
5596 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005597 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005598 return false;
5599 }
5600
5601 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5602 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5603 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5604 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5605 // situation is an application error that would lead to a crash in ANGLE.
5606 if (readBuffer == nullptr)
5607 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005608 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005609 return false;
5610 }
5611
Martin Radev28031682017-07-28 14:47:56 +03005612 // ANGLE_multiview, Revision 1:
5613 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5614 // current read framebuffer is not NONE.
5615 if (readBuffer->getMultiviewLayout() != GL_NONE)
5616 {
5617 context->handleError(InvalidFramebufferOperation()
5618 << "Attempting to read from a multi-view framebuffer.");
5619 return false;
5620 }
5621
Geoff Lang280ba992017-04-18 16:30:58 -04005622 if (context->getExtensions().webglCompatibility)
5623 {
5624 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5625 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5626 // and type before validating the combination of format and type. However, the
5627 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5628 // verifies that GL_INVALID_OPERATION is generated.
5629 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5630 // dEQP/WebGL.
5631 if (!ValidReadPixelsFormatEnum(context, format))
5632 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005633 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005634 return false;
5635 }
5636
5637 if (!ValidReadPixelsTypeEnum(context, type))
5638 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005639 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005640 return false;
5641 }
5642 }
5643
Jamie Madill690c8eb2018-03-12 15:20:03 -04005644 GLenum currentFormat = GL_NONE;
5645 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5646
5647 GLenum currentType = GL_NONE;
5648 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5649
Jamie Madillbe849e42017-05-02 15:49:00 -04005650 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5651
5652 bool validFormatTypeCombination =
5653 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5654
5655 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5656 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005657 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005658 return false;
5659 }
5660
5661 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005662 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005663 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5664 {
5665 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005666 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005667 return false;
5668 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005669 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5670 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5671 {
5672 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5673 return false;
5674 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005675
5676 // .. the data would be packed to the buffer object such that the memory writes required
5677 // would exceed the data store size.
5678 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5679 const gl::Extents size(width, height, 1);
5680 const auto &pack = context->getGLState().getPackState();
5681
5682 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5683 if (endByteOrErr.isError())
5684 {
5685 context->handleError(endByteOrErr.getError());
5686 return false;
5687 }
5688
5689 size_t endByte = endByteOrErr.getResult();
5690 if (bufSize >= 0)
5691 {
5692 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5693 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005694 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005695 return false;
5696 }
5697 }
5698
5699 if (pixelPackBuffer != nullptr)
5700 {
5701 CheckedNumeric<size_t> checkedEndByte(endByte);
5702 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5703 checkedEndByte += checkedOffset;
5704
5705 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5706 {
5707 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005708 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005709 return false;
5710 }
5711 }
5712
5713 if (pixelPackBuffer == nullptr && length != nullptr)
5714 {
5715 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5716 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005717 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005718 return false;
5719 }
5720
5721 *length = static_cast<GLsizei>(endByte);
5722 }
5723
Geoff Langa953b522018-02-21 16:56:23 -05005724 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005725 angle::CheckedNumeric<int> clippedExtent(length);
5726 if (start < 0)
5727 {
5728 // "subtract" the area that is less than 0
5729 clippedExtent += start;
5730 }
5731
Geoff Langa953b522018-02-21 16:56:23 -05005732 angle::CheckedNumeric<int> readExtent = start;
5733 readExtent += length;
5734 if (!readExtent.IsValid())
5735 {
5736 return false;
5737 }
5738
5739 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005740 {
5741 // Subtract the region to the right of the read buffer
5742 clippedExtent -= (readExtent - bufferSize);
5743 }
5744
5745 if (!clippedExtent.IsValid())
5746 {
Geoff Langa953b522018-02-21 16:56:23 -05005747 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005748 }
5749
Geoff Langa953b522018-02-21 16:56:23 -05005750 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5751 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005752 };
5753
Geoff Langa953b522018-02-21 16:56:23 -05005754 GLsizei writtenColumns = 0;
5755 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5756 {
5757 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5758 return false;
5759 }
5760
5761 GLsizei writtenRows = 0;
5762 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5763 {
5764 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5765 return false;
5766 }
5767
Jamie Madillbe849e42017-05-02 15:49:00 -04005768 if (columns != nullptr)
5769 {
Geoff Langa953b522018-02-21 16:56:23 -05005770 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005771 }
5772
5773 if (rows != nullptr)
5774 {
Geoff Langa953b522018-02-21 16:56:23 -05005775 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005776 }
5777
5778 return true;
5779}
5780
5781template <typename ParamType>
5782bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005783 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005784 GLenum pname,
5785 GLsizei bufSize,
5786 const ParamType *params)
5787{
5788 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5789 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005790 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005791 return false;
5792 }
5793
5794 if (context->getTargetTexture(target) == nullptr)
5795 {
5796 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005797 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005798 return false;
5799 }
5800
5801 const GLsizei minBufSize = 1;
5802 if (bufSize >= 0 && bufSize < minBufSize)
5803 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005804 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005805 return false;
5806 }
5807
5808 switch (pname)
5809 {
5810 case GL_TEXTURE_WRAP_R:
5811 case GL_TEXTURE_SWIZZLE_R:
5812 case GL_TEXTURE_SWIZZLE_G:
5813 case GL_TEXTURE_SWIZZLE_B:
5814 case GL_TEXTURE_SWIZZLE_A:
5815 case GL_TEXTURE_BASE_LEVEL:
5816 case GL_TEXTURE_MAX_LEVEL:
5817 case GL_TEXTURE_COMPARE_MODE:
5818 case GL_TEXTURE_COMPARE_FUNC:
5819 case GL_TEXTURE_MIN_LOD:
5820 case GL_TEXTURE_MAX_LOD:
5821 if (context->getClientMajorVersion() < 3)
5822 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005823 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005824 return false;
5825 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005826 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005827 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005828 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5829 "available without "
5830 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005831 return false;
5832 }
5833 break;
5834
5835 default:
5836 break;
5837 }
5838
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005839 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005840 {
5841 switch (pname)
5842 {
5843 case GL_TEXTURE_MIN_FILTER:
5844 case GL_TEXTURE_MAG_FILTER:
5845 case GL_TEXTURE_WRAP_S:
5846 case GL_TEXTURE_WRAP_T:
5847 case GL_TEXTURE_WRAP_R:
5848 case GL_TEXTURE_MIN_LOD:
5849 case GL_TEXTURE_MAX_LOD:
5850 case GL_TEXTURE_COMPARE_MODE:
5851 case GL_TEXTURE_COMPARE_FUNC:
5852 context->handleError(InvalidEnum()
5853 << "Invalid parameter for 2D multisampled textures.");
5854 return false;
5855 }
5856 }
5857
Jamie Madillbe849e42017-05-02 15:49:00 -04005858 switch (pname)
5859 {
5860 case GL_TEXTURE_WRAP_S:
5861 case GL_TEXTURE_WRAP_T:
5862 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005863 {
5864 bool restrictedWrapModes =
5865 target == TextureType::External || target == TextureType::Rectangle;
5866 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005867 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005868 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005869 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005870 }
5871 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005872
5873 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005874 {
5875 bool restrictedMinFilter =
5876 target == TextureType::External || target == TextureType::Rectangle;
5877 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005878 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005879 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005880 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005881 }
5882 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005883
5884 case GL_TEXTURE_MAG_FILTER:
5885 if (!ValidateTextureMagFilterValue(context, params))
5886 {
5887 return false;
5888 }
5889 break;
5890
5891 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005892 if (!context->getExtensions().textureUsage)
5893 {
5894 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5895 return false;
5896 }
5897
Jamie Madillbe849e42017-05-02 15:49:00 -04005898 switch (ConvertToGLenum(params[0]))
5899 {
5900 case GL_NONE:
5901 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5902 break;
5903
5904 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005905 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005906 return false;
5907 }
5908 break;
5909
5910 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005911 {
5912 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5913 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04005914 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005915 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005916 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005917 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
5918 }
5919 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005920
5921 case GL_TEXTURE_MIN_LOD:
5922 case GL_TEXTURE_MAX_LOD:
5923 // any value is permissible
5924 break;
5925
5926 case GL_TEXTURE_COMPARE_MODE:
5927 if (!ValidateTextureCompareModeValue(context, params))
5928 {
5929 return false;
5930 }
5931 break;
5932
5933 case GL_TEXTURE_COMPARE_FUNC:
5934 if (!ValidateTextureCompareFuncValue(context, params))
5935 {
5936 return false;
5937 }
5938 break;
5939
5940 case GL_TEXTURE_SWIZZLE_R:
5941 case GL_TEXTURE_SWIZZLE_G:
5942 case GL_TEXTURE_SWIZZLE_B:
5943 case GL_TEXTURE_SWIZZLE_A:
5944 switch (ConvertToGLenum(params[0]))
5945 {
5946 case GL_RED:
5947 case GL_GREEN:
5948 case GL_BLUE:
5949 case GL_ALPHA:
5950 case GL_ZERO:
5951 case GL_ONE:
5952 break;
5953
5954 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005955 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005956 return false;
5957 }
5958 break;
5959
5960 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005961 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005962 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005963 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005964 return false;
5965 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005966 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005967 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005968 context->handleError(InvalidOperation()
5969 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005970 return false;
5971 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005972 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005973 {
5974 context->handleError(InvalidOperation()
5975 << "Base level must be 0 for multisampled textures.");
5976 return false;
5977 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005978 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005979 {
5980 context->handleError(InvalidOperation()
5981 << "Base level must be 0 for rectangle textures.");
5982 return false;
5983 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005984 break;
5985
5986 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005987 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005988 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005989 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005990 return false;
5991 }
5992 break;
5993
5994 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5995 if (context->getClientVersion() < Version(3, 1))
5996 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005997 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005998 return false;
5999 }
6000 switch (ConvertToGLenum(params[0]))
6001 {
6002 case GL_DEPTH_COMPONENT:
6003 case GL_STENCIL_INDEX:
6004 break;
6005
6006 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006007 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006008 return false;
6009 }
6010 break;
6011
6012 case GL_TEXTURE_SRGB_DECODE_EXT:
6013 if (!ValidateTextureSRGBDecodeValue(context, params))
6014 {
6015 return false;
6016 }
6017 break;
6018
6019 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006020 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006021 return false;
6022 }
6023
6024 return true;
6025}
6026
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006027template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6028template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006029
Jamie Madill5b772312018-03-08 20:28:32 -05006030bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006031{
6032 if (index >= MAX_VERTEX_ATTRIBS)
6033 {
6034 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6035 return false;
6036 }
6037
6038 return true;
6039}
6040
6041bool ValidateGetActiveUniformBlockivBase(Context *context,
6042 GLuint program,
6043 GLuint uniformBlockIndex,
6044 GLenum pname,
6045 GLsizei *length)
6046{
6047 if (length)
6048 {
6049 *length = 0;
6050 }
6051
6052 if (context->getClientMajorVersion() < 3)
6053 {
6054 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6055 return false;
6056 }
6057
6058 Program *programObject = GetValidProgram(context, program);
6059 if (!programObject)
6060 {
6061 return false;
6062 }
6063
6064 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6065 {
6066 context->handleError(InvalidValue()
6067 << "uniformBlockIndex exceeds active uniform block count.");
6068 return false;
6069 }
6070
6071 switch (pname)
6072 {
6073 case GL_UNIFORM_BLOCK_BINDING:
6074 case GL_UNIFORM_BLOCK_DATA_SIZE:
6075 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6076 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6077 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6078 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6079 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6080 break;
6081
6082 default:
6083 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6084 return false;
6085 }
6086
6087 if (length)
6088 {
6089 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6090 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006091 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006092 programObject->getUniformBlockByIndex(uniformBlockIndex);
6093 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6094 }
6095 else
6096 {
6097 *length = 1;
6098 }
6099 }
6100
6101 return true;
6102}
6103
Jamie Madill9696d072017-08-26 23:19:57 -04006104template <typename ParamType>
6105bool ValidateSamplerParameterBase(Context *context,
6106 GLuint sampler,
6107 GLenum pname,
6108 GLsizei bufSize,
6109 ParamType *params)
6110{
6111 if (context->getClientMajorVersion() < 3)
6112 {
6113 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6114 return false;
6115 }
6116
6117 if (!context->isSampler(sampler))
6118 {
6119 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6120 return false;
6121 }
6122
6123 const GLsizei minBufSize = 1;
6124 if (bufSize >= 0 && bufSize < minBufSize)
6125 {
6126 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6127 return false;
6128 }
6129
6130 switch (pname)
6131 {
6132 case GL_TEXTURE_WRAP_S:
6133 case GL_TEXTURE_WRAP_T:
6134 case GL_TEXTURE_WRAP_R:
6135 if (!ValidateTextureWrapModeValue(context, params, false))
6136 {
6137 return false;
6138 }
6139 break;
6140
6141 case GL_TEXTURE_MIN_FILTER:
6142 if (!ValidateTextureMinFilterValue(context, params, false))
6143 {
6144 return false;
6145 }
6146 break;
6147
6148 case GL_TEXTURE_MAG_FILTER:
6149 if (!ValidateTextureMagFilterValue(context, params))
6150 {
6151 return false;
6152 }
6153 break;
6154
6155 case GL_TEXTURE_MIN_LOD:
6156 case GL_TEXTURE_MAX_LOD:
6157 // any value is permissible
6158 break;
6159
6160 case GL_TEXTURE_COMPARE_MODE:
6161 if (!ValidateTextureCompareModeValue(context, params))
6162 {
6163 return false;
6164 }
6165 break;
6166
6167 case GL_TEXTURE_COMPARE_FUNC:
6168 if (!ValidateTextureCompareFuncValue(context, params))
6169 {
6170 return false;
6171 }
6172 break;
6173
6174 case GL_TEXTURE_SRGB_DECODE_EXT:
6175 if (!ValidateTextureSRGBDecodeValue(context, params))
6176 {
6177 return false;
6178 }
6179 break;
6180
Luc Ferron1b1a8642018-01-23 15:12:01 -05006181 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6182 {
6183 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6184 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6185 {
6186 return false;
6187 }
6188 }
6189 break;
6190
Jamie Madill9696d072017-08-26 23:19:57 -04006191 default:
6192 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6193 return false;
6194 }
6195
6196 return true;
6197}
6198
6199template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6200template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6201
6202bool ValidateGetSamplerParameterBase(Context *context,
6203 GLuint sampler,
6204 GLenum pname,
6205 GLsizei *length)
6206{
6207 if (length)
6208 {
6209 *length = 0;
6210 }
6211
6212 if (context->getClientMajorVersion() < 3)
6213 {
6214 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6215 return false;
6216 }
6217
6218 if (!context->isSampler(sampler))
6219 {
6220 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6221 return false;
6222 }
6223
6224 switch (pname)
6225 {
6226 case GL_TEXTURE_WRAP_S:
6227 case GL_TEXTURE_WRAP_T:
6228 case GL_TEXTURE_WRAP_R:
6229 case GL_TEXTURE_MIN_FILTER:
6230 case GL_TEXTURE_MAG_FILTER:
6231 case GL_TEXTURE_MIN_LOD:
6232 case GL_TEXTURE_MAX_LOD:
6233 case GL_TEXTURE_COMPARE_MODE:
6234 case GL_TEXTURE_COMPARE_FUNC:
6235 break;
6236
Luc Ferron1b1a8642018-01-23 15:12:01 -05006237 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6238 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6239 {
6240 return false;
6241 }
6242 break;
6243
Jamie Madill9696d072017-08-26 23:19:57 -04006244 case GL_TEXTURE_SRGB_DECODE_EXT:
6245 if (!context->getExtensions().textureSRGBDecode)
6246 {
6247 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6248 return false;
6249 }
6250 break;
6251
6252 default:
6253 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6254 return false;
6255 }
6256
6257 if (length)
6258 {
6259 *length = 1;
6260 }
6261 return true;
6262}
6263
6264bool ValidateGetInternalFormativBase(Context *context,
6265 GLenum target,
6266 GLenum internalformat,
6267 GLenum pname,
6268 GLsizei bufSize,
6269 GLsizei *numParams)
6270{
6271 if (numParams)
6272 {
6273 *numParams = 0;
6274 }
6275
6276 if (context->getClientMajorVersion() < 3)
6277 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006278 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006279 return false;
6280 }
6281
6282 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
6283 if (!formatCaps.renderable)
6284 {
6285 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6286 return false;
6287 }
6288
6289 switch (target)
6290 {
6291 case GL_RENDERBUFFER:
6292 break;
6293
6294 case GL_TEXTURE_2D_MULTISAMPLE:
6295 if (context->getClientVersion() < ES_3_1)
6296 {
6297 context->handleError(InvalidOperation()
6298 << "Texture target requires at least OpenGL ES 3.1.");
6299 return false;
6300 }
6301 break;
6302
6303 default:
6304 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6305 return false;
6306 }
6307
6308 if (bufSize < 0)
6309 {
6310 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6311 return false;
6312 }
6313
6314 GLsizei maxWriteParams = 0;
6315 switch (pname)
6316 {
6317 case GL_NUM_SAMPLE_COUNTS:
6318 maxWriteParams = 1;
6319 break;
6320
6321 case GL_SAMPLES:
6322 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6323 break;
6324
6325 default:
6326 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6327 return false;
6328 }
6329
6330 if (numParams)
6331 {
6332 // glGetInternalFormativ will not overflow bufSize
6333 *numParams = std::min(bufSize, maxWriteParams);
6334 }
6335
6336 return true;
6337}
6338
Jamie Madille98b1b52018-03-08 09:47:23 -05006339// We should check with Khronos if returning INVALID_FRAMEBUFFER_OPERATION is OK when querying
6340// implementation format info for incomplete framebuffers. It seems like these queries are
6341// incongruent with the other errors.
6342bool ValidateFramebufferComplete(Context *context, Framebuffer *framebuffer, bool isFramebufferOp)
6343{
6344 bool complete = false;
6345 ANGLE_VALIDATION_TRY(framebuffer->isComplete(context, &complete));
6346 if (!complete)
6347 {
6348 if (isFramebufferOp)
6349 {
6350 context->handleError(InvalidFramebufferOperation());
6351 }
6352 else
6353 {
6354 context->handleError(InvalidOperation());
6355 }
6356 return false;
6357 }
6358 return true;
6359}
6360
6361bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6362{
6363 GLint samples = 0;
6364 ANGLE_VALIDATION_TRY(framebuffer->getSamples(context, &samples));
6365 if (samples != 0)
6366 {
6367 context->handleError(InvalidOperation());
6368 return false;
6369 }
6370 return true;
6371}
6372
Lingfeng Yang038dd532018-03-29 17:31:52 -07006373bool ValidateMultitextureUnit(Context *context, GLenum texture)
6374{
6375 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6376 {
6377 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6378 return false;
6379 }
6380 return true;
6381}
6382
Jamie Madillc29968b2016-01-20 11:17:23 -05006383} // namespace gl