blob: 603a930fe03558cf96c3215c67e4fe821883e0b7 [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"
Lingfeng Yangf97641c2018-06-21 19:22:45 -070025#include "libANGLE/queryutils.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040026#include "libANGLE/validationES2.h"
27#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040028
29#include "common/mathutil.h"
30#include "common/utilities.h"
31
Jamie Madille2e406c2016-06-02 13:04:10 -040032using namespace angle;
33
Geoff Lange8ebe7f2013-08-05 15:03:13 -040034namespace gl
35{
Jamie Madill1ca74672015-07-21 15:14:11 -040036namespace
37{
Luc Ferron9dbaeba2018-02-01 07:26:59 -050038bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
39{
40 // List of compressed format that require that the texture size is smaller than or a multiple of
41 // the compressed block size.
42 switch (internalFormat)
43 {
44 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
45 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
46 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
47 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
48 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
49 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
50 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
51 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
52 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
53 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
54 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
55 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
56 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
57 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
58 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
59 return true;
jchen10a99ed552017-09-22 08:10:32 +080060
Luc Ferron9dbaeba2018-02-01 07:26:59 -050061 default:
62 return false;
63 }
64}
65bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
66{
67 // Compressed sub textures have additional formats that requires exact size.
68 // ES 3.1, Section 8.7, Page 171
69 return CompressedTextureFormatRequiresExactSize(internalFormat) ||
70 IsETC2EACFormat(internalFormat);
71}
Olli Etuaho8d5571a2018-04-23 12:29:31 +030072
73bool DifferenceCanOverflow(GLint a, GLint b)
74{
75 CheckedNumeric<GLint> checkedA(a);
76 checkedA -= b;
77 // Use negation to make sure that the difference can't overflow regardless of the order.
78 checkedA = -checkedA;
79 return !checkedA.IsValid();
80}
81
Jamie Madill5b772312018-03-08 20:28:32 -050082bool ValidateDrawAttribs(Context *context, GLint primcount, GLint maxVertex, GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040083{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070084 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040085 const gl::Program *program = state.getProgram();
86
Corentin Wallez327411e2016-12-09 11:09:17 -050087 bool webglCompatibility = context->getExtensions().webglCompatibility;
88
Jamie Madill51af38b2018-04-15 08:50:56 -040089 const VertexArray *vao = state.getVertexArray();
90 const AttributesMask &clientAttribs = vao->getEnabledClientMemoryAttribsMask();
91
92 if (clientAttribs.any())
93 {
94 if (webglCompatibility || !state.areClientArraysEnabled())
95 {
96 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
97 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
98 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
99 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
100 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
101 return false;
102 }
103 else if (vao->hasEnabledNullPointerClientArray())
104 {
105 // This is an application error that would normally result in a crash, but we catch it
106 // and return an error
107 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
108 return false;
109 }
110 }
111
112 // If we're drawing zero vertices, we have enough data.
113 if (vertexCount <= 0 || primcount <= 0)
114 {
115 return true;
116 }
117
Jamie Madill231c7f52017-04-26 13:45:37 -0400118 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800119 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madill51af38b2018-04-15 08:50:56 -0400120
Lingfeng Yang461b09a2018-04-23 09:02:09 -0700121 bool isGLES1 = context->getClientVersion() < Version(2, 0);
122
123 const AttributesMask &activeAttribs = ((isGLES1 ? context->getVertexArraysAttributeMask()
124 : program->getActiveAttribLocationsMask()) &
Jamie Madill02c9c042018-04-17 13:43:48 -0400125 vao->getEnabledAttributesMask() & ~clientAttribs);
Jamie Madill51af38b2018-04-15 08:50:56 -0400126
127 for (size_t attributeIndex : activeAttribs)
Jamie Madill1ca74672015-07-21 15:14:11 -0400128 {
129 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Jamie Madill51af38b2018-04-15 08:50:56 -0400130 ASSERT(attrib.enabled);
Corentin Wallez672f7f32017-06-15 17:42:17 -0400131
Lingfeng Yang038dd532018-03-29 17:31:52 -0700132 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
Lingfeng Yang461b09a2018-04-23 09:02:09 -0700133 ASSERT(isGLES1 || program->isAttribLocationActive(attributeIndex));
Corentin Wallezfd456442016-12-21 17:57:00 -0500134
Jamie Madill02c9c042018-04-17 13:43:48 -0400135 GLint maxVertexElement = maxVertex;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300136 GLuint divisor = binding.getDivisor();
Jamie Madill02c9c042018-04-17 13:43:48 -0400137 if (divisor != 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500138 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300139 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500140 }
141
142 // We do manual overflow checks here instead of using safe_math.h because it was
143 // a bottleneck. Thanks to some properties of GL we know inequalities that can
144 // help us make the overflow checks faster.
145
146 // The max possible attribSize is 16 for a vector of 4 32 bit values.
147 constexpr uint64_t kMaxAttribSize = 16;
148 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
149 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
150
151 // We know attribStride is given as a GLsizei which is typedefed to int.
152 // We also know an upper bound for attribSize.
Jamie Madill02c9c042018-04-17 13:43:48 -0400153 static_assert(std::is_same<int, GLsizei>::value, "Unexpected type");
154 ASSERT(ComputeVertexAttributeStride(attrib, binding) == binding.getStride());
155 uint64_t attribStride = binding.getStride();
156 ASSERT(attribStride <= kIntMax && ComputeVertexAttributeTypeSize(attrib) <= kMaxAttribSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500157
Jamie Madill02c9c042018-04-17 13:43:48 -0400158 // Computing the product of two 32-bit ints will fit in 64 bits without overflow.
159 static_assert(kIntMax * kIntMax < kUint64Max, "Unexpected overflow");
160 uint64_t attribDataSizeMinusAttribSize = maxVertexElement * attribStride;
Corentin Wallezfd456442016-12-21 17:57:00 -0500161
162 // An overflow can happen when adding the offset, check for it.
Jamie Madill02c9c042018-04-17 13:43:48 -0400163 if (attribDataSizeMinusAttribSize > kUint64Max - attrib.cachedSizePlusRelativeOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500164 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700165 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500166 return false;
167 }
Corentin Wallezfd456442016-12-21 17:57:00 -0500168
169 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
Jamie Madill02c9c042018-04-17 13:43:48 -0400170 // We can return INVALID_OPERATION if our array buffer does not have enough backing data.
171 if (attribDataSizeMinusAttribSize + attrib.cachedSizePlusRelativeOffset >
172 binding.getCachedBufferSizeMinusOffset())
Corentin Wallezfd456442016-12-21 17:57:00 -0500173 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700174 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500175 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400176 }
Jamie Madill02c9c042018-04-17 13:43:48 -0400177 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800178
Jamie Madill7267aa62018-04-17 15:28:21 -0400179 if (webglCompatibility && vao->hasTransformFeedbackBindingConflict(activeAttribs))
Jamie Madill02c9c042018-04-17 13:43:48 -0400180 {
Jamie Madill7267aa62018-04-17 15:28:21 -0400181 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexBufferBoundForTransformFeedback);
182 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400183 }
184
185 return true;
186}
187
Jamie Madill5b772312018-03-08 20:28:32 -0500188bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400189{
190 switch (type)
191 {
192 // Types referenced in Table 3.4 of the ES 2.0.25 spec
193 case GL_UNSIGNED_BYTE:
194 case GL_UNSIGNED_SHORT_4_4_4_4:
195 case GL_UNSIGNED_SHORT_5_5_5_1:
196 case GL_UNSIGNED_SHORT_5_6_5:
197 return context->getClientVersion() >= ES_2_0;
198
199 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
200 case GL_BYTE:
201 case GL_INT:
202 case GL_SHORT:
203 case GL_UNSIGNED_INT:
204 case GL_UNSIGNED_INT_10F_11F_11F_REV:
205 case GL_UNSIGNED_INT_24_8:
206 case GL_UNSIGNED_INT_2_10_10_10_REV:
207 case GL_UNSIGNED_INT_5_9_9_9_REV:
208 case GL_UNSIGNED_SHORT:
209 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
210 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
211 return context->getClientVersion() >= ES_3_0;
212
213 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400214 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
215 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400216
217 case GL_HALF_FLOAT:
218 return context->getClientVersion() >= ES_3_0 ||
219 context->getExtensions().textureHalfFloat;
220
221 case GL_HALF_FLOAT_OES:
222 return context->getExtensions().colorBufferHalfFloat;
223
224 default:
225 return false;
226 }
227}
228
Jamie Madill5b772312018-03-08 20:28:32 -0500229bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400230{
231 switch (format)
232 {
233 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
234 case GL_RGBA:
235 case GL_RGB:
236 case GL_ALPHA:
237 return context->getClientVersion() >= ES_2_0;
238
239 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
240 case GL_RG:
241 case GL_RED:
242 case GL_RGBA_INTEGER:
243 case GL_RGB_INTEGER:
244 case GL_RG_INTEGER:
245 case GL_RED_INTEGER:
246 return context->getClientVersion() >= ES_3_0;
247
248 case GL_SRGB_ALPHA_EXT:
249 case GL_SRGB_EXT:
250 return context->getExtensions().sRGB;
251
252 case GL_BGRA_EXT:
253 return context->getExtensions().readFormatBGRA;
254
255 default:
256 return false;
257 }
258}
259
Jamie Madill5b772312018-03-08 20:28:32 -0500260bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400261 GLenum framebufferComponentType,
262 GLenum format,
263 GLenum type)
264{
265 switch (framebufferComponentType)
266 {
267 case GL_UNSIGNED_NORMALIZED:
268 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
269 // ReadPixels with BGRA even if the extension is not present
270 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
271 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
272 type == GL_UNSIGNED_BYTE);
273
274 case GL_SIGNED_NORMALIZED:
275 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
276
277 case GL_INT:
278 return (format == GL_RGBA_INTEGER && type == GL_INT);
279
280 case GL_UNSIGNED_INT:
281 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
282
283 case GL_FLOAT:
284 return (format == GL_RGBA && type == GL_FLOAT);
285
286 default:
287 UNREACHABLE();
288 return false;
289 }
290}
291
Geoff Langc1984ed2016-10-07 12:41:00 -0400292template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400293bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400294{
295 switch (ConvertToGLenum(params[0]))
296 {
297 case GL_CLAMP_TO_EDGE:
298 break;
299
300 case GL_REPEAT:
301 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400302 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400303 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400304 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700305 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400306 return false;
307 }
308 break;
309
310 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700311 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400312 return false;
313 }
314
315 return true;
316}
317
318template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400319bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400320{
321 switch (ConvertToGLenum(params[0]))
322 {
323 case GL_NEAREST:
324 case GL_LINEAR:
325 break;
326
327 case GL_NEAREST_MIPMAP_NEAREST:
328 case GL_LINEAR_MIPMAP_NEAREST:
329 case GL_NEAREST_MIPMAP_LINEAR:
330 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400331 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400332 {
333 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700334 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400335 return false;
336 }
337 break;
338
339 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700340 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400341 return false;
342 }
343
344 return true;
345}
346
347template <typename ParamType>
348bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
349{
350 switch (ConvertToGLenum(params[0]))
351 {
352 case GL_NEAREST:
353 case GL_LINEAR:
354 break;
355
356 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700357 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400358 return false;
359 }
360
361 return true;
362}
363
364template <typename ParamType>
365bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
366{
367 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
368 switch (ConvertToGLenum(params[0]))
369 {
370 case GL_NONE:
371 case GL_COMPARE_REF_TO_TEXTURE:
372 break;
373
374 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700375 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400376 return false;
377 }
378
379 return true;
380}
381
382template <typename ParamType>
383bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
384{
385 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
386 switch (ConvertToGLenum(params[0]))
387 {
388 case GL_LEQUAL:
389 case GL_GEQUAL:
390 case GL_LESS:
391 case GL_GREATER:
392 case GL_EQUAL:
393 case GL_NOTEQUAL:
394 case GL_ALWAYS:
395 case GL_NEVER:
396 break;
397
398 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700399 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400400 return false;
401 }
402
403 return true;
404}
405
406template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700407bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
408{
409 if (!context->getExtensions().textureSRGBDecode)
410 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700411 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700412 return false;
413 }
414
415 switch (ConvertToGLenum(params[0]))
416 {
417 case GL_DECODE_EXT:
418 case GL_SKIP_DECODE_EXT:
419 break;
420
421 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700422 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700423 return false;
424 }
425
426 return true;
427}
428
Luc Ferron1b1a8642018-01-23 15:12:01 -0500429bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
430{
431 if (!context->getExtensions().textureFilterAnisotropic)
432 {
433 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
434 return false;
435 }
436
437 return true;
438}
439
440bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
441{
442 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
443 {
444 return false;
445 }
446
447 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
448
449 if (paramValue < 1 || paramValue > largest)
450 {
451 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
452 return false;
453 }
454
455 return true;
456}
457
Jamie Madill5b772312018-03-08 20:28:32 -0500458bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400459{
460 const Program *program = context->getGLState().getProgram();
461 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
462
Brandon Jonesc405ae72017-12-06 14:15:03 -0800463 if (!ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
464 framebuffer->getDrawBufferTypeMask().to_ulong(),
465 program->getActiveOutputVariables().to_ulong(),
466 framebuffer->getDrawBufferMask().to_ulong()))
Geoff Lange0cff192017-05-30 13:04:56 -0400467 {
Brandon Jones76746f92017-11-22 11:44:41 -0800468 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
469 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400470 }
471
472 return true;
473}
474
Jamie Madill5b772312018-03-08 20:28:32 -0500475bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400476{
Lingfeng Yang038dd532018-03-29 17:31:52 -0700477 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400478 const Program *program = context->getGLState().getProgram();
479 const VertexArray *vao = context->getGLState().getVertexArray();
480
Brandon Jonesc405ae72017-12-06 14:15:03 -0800481 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
482 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
483 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
484
485 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
486 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
487 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
488
489 if (!ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
490 program->getAttributesMask().to_ulong(), 0xFFFF))
Geoff Lang9ab5b822017-05-30 16:19:23 -0400491 {
Brandon Jonesc405ae72017-12-06 14:15:03 -0800492 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexShaderTypeMismatch);
493 return false;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400494 }
Geoff Lang9ab5b822017-05-30 16:19:23 -0400495 return true;
496}
497
Jamie Madill493f9572018-05-24 19:52:15 -0400498bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
499 PrimitiveMode geometryShaderInputPrimitiveType)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800500{
501 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
Jamie Madill493f9572018-05-24 19:52:15 -0400502 switch (drawMode)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800503 {
Jamie Madill493f9572018-05-24 19:52:15 -0400504 case PrimitiveMode::Points:
505 return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
506 case PrimitiveMode::Lines:
507 case PrimitiveMode::LineStrip:
508 case PrimitiveMode::LineLoop:
509 return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
510 case PrimitiveMode::LinesAdjacency:
511 case PrimitiveMode::LineStripAdjacency:
512 return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
513 case PrimitiveMode::Triangles:
514 case PrimitiveMode::TriangleFan:
515 case PrimitiveMode::TriangleStrip:
516 return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
517 case PrimitiveMode::TrianglesAdjacency:
518 case PrimitiveMode::TriangleStripAdjacency:
519 return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
Jiawei Shaofccebff2018-03-08 13:51:02 +0800520 default:
521 UNREACHABLE();
522 return false;
523 }
524}
525
Lingfeng Yangf97641c2018-06-21 19:22:45 -0700526// GLES1 texture parameters are a small subset of the others
527bool IsValidGLES1TextureParameter(GLenum pname)
528{
529 switch (pname)
530 {
531 case GL_TEXTURE_MAG_FILTER:
532 case GL_TEXTURE_MIN_FILTER:
533 case GL_TEXTURE_WRAP_S:
534 case GL_TEXTURE_WRAP_T:
535 case GL_TEXTURE_WRAP_R:
536 case GL_GENERATE_MIPMAP:
537 case GL_TEXTURE_CROP_RECT_OES:
538 return true;
539 default:
540 return false;
541 }
542}
543
Geoff Langf41a7152016-09-19 15:11:17 -0400544} // anonymous namespace
545
Brandon Jonesd1049182018-03-28 10:02:20 -0700546void SetRobustLengthParam(GLsizei *length, GLsizei value)
547{
548 if (length)
549 {
550 *length = value;
551 }
552}
553
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500554bool IsETC2EACFormat(const GLenum format)
555{
556 // ES 3.1, Table 8.19
557 switch (format)
558 {
559 case GL_COMPRESSED_R11_EAC:
560 case GL_COMPRESSED_SIGNED_R11_EAC:
561 case GL_COMPRESSED_RG11_EAC:
562 case GL_COMPRESSED_SIGNED_RG11_EAC:
563 case GL_COMPRESSED_RGB8_ETC2:
564 case GL_COMPRESSED_SRGB8_ETC2:
565 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
566 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
567 case GL_COMPRESSED_RGBA8_ETC2_EAC:
568 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
569 return true;
570
571 default:
572 return false;
573 }
574}
575
Jamie Madill5b772312018-03-08 20:28:32 -0500576bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400577{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800578 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400579 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800580 case TextureType::_2D:
581 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800582 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400583
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800584 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400585 return context->getExtensions().textureRectangle;
586
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800587 case TextureType::_3D:
588 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800589 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500590
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800591 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800592 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400593
He Yunchaoced53ae2016-11-29 15:00:51 +0800594 default:
595 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500596 }
Jamie Madill35d15012013-10-07 10:46:37 -0400597}
598
Jamie Madill5b772312018-03-08 20:28:32 -0500599bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500600{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800601 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500602 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800603 case TextureType::_2D:
604 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500605 return true;
606
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800607 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400608 return context->getExtensions().textureRectangle;
609
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500610 default:
611 return false;
612 }
613}
614
Jamie Madill5b772312018-03-08 20:28:32 -0500615bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500616{
617 switch (target)
618 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800619 case TextureType::_3D:
620 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300621 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500622
623 default:
624 return false;
625 }
626}
627
Ian Ewellbda75592016-04-18 17:25:54 -0400628// Most texture GL calls are not compatible with external textures, so we have a separate validation
629// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500630bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400631{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800632 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400633 (context->getExtensions().eglImageExternal ||
634 context->getExtensions().eglStreamConsumerExternal);
635}
636
Shannon Woods4dfed832014-03-17 20:03:39 -0400637// This function differs from ValidTextureTarget in that the target must be
638// usable as the destination of a 2D operation-- so a cube face is valid, but
639// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400640// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500641bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400642{
643 switch (target)
644 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800645 case TextureTarget::_2D:
646 case TextureTarget::CubeMapNegativeX:
647 case TextureTarget::CubeMapNegativeY:
648 case TextureTarget::CubeMapNegativeZ:
649 case TextureTarget::CubeMapPositiveX:
650 case TextureTarget::CubeMapPositiveY:
651 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800652 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800653 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400654 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800655 default:
656 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500657 }
658}
659
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800660bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400661 PrimitiveMode transformFeedbackPrimitiveMode,
662 PrimitiveMode renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800663{
664 ASSERT(context);
665
666 if (!context->getExtensions().geometryShader)
667 {
668 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
669 // that does not match the current transform feedback object's draw mode (if transform
670 // feedback is active), (3.0.2, section 2.14, pg 86)
671 return transformFeedbackPrimitiveMode == renderPrimitiveMode;
672 }
673
674 // [GL_EXT_geometry_shader] Table 12.1gs
Jamie Madill493f9572018-05-24 19:52:15 -0400675 switch (renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800676 {
Jamie Madill493f9572018-05-24 19:52:15 -0400677 case PrimitiveMode::Points:
678 return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
679 case PrimitiveMode::Lines:
680 case PrimitiveMode::LineStrip:
681 case PrimitiveMode::LineLoop:
682 return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
683 case PrimitiveMode::Triangles:
684 case PrimitiveMode::TriangleFan:
685 case PrimitiveMode::TriangleStrip:
686 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800687 default:
688 UNREACHABLE();
689 return false;
690 }
691}
692
Jamie Madill5b772312018-03-08 20:28:32 -0500693bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400694 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400695 GLsizei count,
696 GLenum type,
697 const GLvoid *indices,
698 GLsizei primcount)
699{
700 if (primcount < 0)
701 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700702 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400703 return false;
704 }
705
706 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
707 {
708 return false;
709 }
710
Jamie Madill9fdaa492018-02-16 10:52:11 -0500711 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400712}
713
714bool ValidateDrawArraysInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400715 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400716 GLint first,
717 GLsizei count,
718 GLsizei primcount)
719{
720 if (primcount < 0)
721 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700722 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400723 return false;
724 }
725
726 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
727 {
728 return false;
729 }
730
Jamie Madill9fdaa492018-02-16 10:52:11 -0500731 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400732}
733
Jamie Madill5b772312018-03-08 20:28:32 -0500734bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400735{
736 // Verify there is at least one active attribute with a divisor of zero
737 const State &state = context->getGLState();
738
739 Program *program = state.getProgram();
740
741 const auto &attribs = state.getVertexArray()->getVertexAttributes();
742 const auto &bindings = state.getVertexArray()->getVertexBindings();
743 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
744 {
745 const VertexAttribute &attrib = attribs[attributeIndex];
746 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300747 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400748 {
749 return true;
750 }
751 }
752
Brandon Jonesafa75152017-07-21 13:11:29 -0700753 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400754 return false;
755}
756
Jamie Madill5b772312018-03-08 20:28:32 -0500757bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500758{
759 switch (target)
760 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800761 case TextureType::_3D:
762 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800763 return true;
764 default:
765 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400766 }
767}
768
Jamie Madill5b772312018-03-08 20:28:32 -0500769bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800770{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800771 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800772 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800773 case TextureType::_2D:
774 case TextureType::_2DArray:
775 case TextureType::_2DMultisample:
776 case TextureType::CubeMap:
777 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800778 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800779 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400780 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800781 default:
782 return false;
783 }
784}
785
Jamie Madill5b772312018-03-08 20:28:32 -0500786bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500787{
He Yunchaoced53ae2016-11-29 15:00:51 +0800788 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
789 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400790 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500791
792 switch (target)
793 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800794 case GL_FRAMEBUFFER:
795 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400796
He Yunchaoced53ae2016-11-29 15:00:51 +0800797 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800798 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400799 return (context->getExtensions().framebufferBlit ||
800 context->getClientMajorVersion() >= 3);
801
He Yunchaoced53ae2016-11-29 15:00:51 +0800802 default:
803 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500804 }
805}
806
Jamie Madill5b772312018-03-08 20:28:32 -0500807bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400808{
Jamie Madillc29968b2016-01-20 11:17:23 -0500809 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400810 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800811 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400812 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800813 case TextureType::_2D:
814 case TextureType::_2DArray:
815 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500816 maxDimension = caps.max2DTextureSize;
817 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800818 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800819 maxDimension = caps.maxCubeMapTextureSize;
820 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800821 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400822 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800823 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800824 maxDimension = caps.max3DTextureSize;
825 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800826 default:
827 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400828 }
829
Brandon Jones6cad5662017-06-14 13:25:13 -0700830 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400831}
832
Jamie Madill5b772312018-03-08 20:28:32 -0500833bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800834 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700835 GLint level,
836 GLsizei width,
837 GLsizei height,
838 GLsizei depth,
839 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400840{
Brandon Jones6cad5662017-06-14 13:25:13 -0700841 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400842 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700843 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400844 return false;
845 }
Austin Kinross08528e12015-10-07 16:24:40 -0700846 // TexSubImage parameters can be NPOT without textureNPOT extension,
847 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500848 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500849 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500850 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400851 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400852 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700853 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400854 return false;
855 }
856
857 if (!ValidMipLevel(context, target, level))
858 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700859 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400860 return false;
861 }
862
863 return true;
864}
865
Geoff Lang966c9402017-04-18 12:38:27 -0400866bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
867{
868 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
869 (size % blockSize == 0);
870}
871
Jamie Madill5b772312018-03-08 20:28:32 -0500872bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500873 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400874 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500875 GLsizei width,
876 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400877{
Geoff Langca271392017-04-05 12:30:00 -0400878 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400879 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400880 {
881 return false;
882 }
883
Geoff Lang966c9402017-04-18 12:38:27 -0400884 if (width < 0 || height < 0)
885 {
886 return false;
887 }
888
889 if (CompressedTextureFormatRequiresExactSize(internalFormat))
890 {
891 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
892 // block size for level 0 but WebGL disallows this.
893 bool smallerThanBlockSizeAllowed =
894 level > 0 || !context->getExtensions().webglCompatibility;
895
896 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
897 smallerThanBlockSizeAllowed) ||
898 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
899 smallerThanBlockSizeAllowed))
900 {
901 return false;
902 }
903 }
904
905 return true;
906}
907
Jamie Madill5b772312018-03-08 20:28:32 -0500908bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400909 GLenum internalFormat,
910 GLint xoffset,
911 GLint yoffset,
912 GLsizei width,
913 GLsizei height,
914 size_t textureWidth,
915 size_t textureHeight)
916{
917 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
918 if (!formatInfo.compressed)
919 {
920 return false;
921 }
922
Geoff Lang44ff5a72017-02-03 15:15:43 -0500923 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400924 {
925 return false;
926 }
927
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500928 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400929 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500930 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400931 yoffset % formatInfo.compressedBlockHeight != 0)
932 {
933 return false;
934 }
935
936 // Allowed to either have data that is a multiple of block size or is smaller than the block
937 // size but fills the entire mip
938 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
939 static_cast<size_t>(width) == textureWidth &&
940 static_cast<size_t>(height) == textureHeight;
941 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
942 (height % formatInfo.compressedBlockHeight) == 0;
943 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400944 {
945 return false;
946 }
947 }
948
Geoff Langd4f180b2013-09-24 13:57:44 -0400949 return true;
950}
951
Jamie Madill5b772312018-03-08 20:28:32 -0500952bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800953 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400954 GLsizei width,
955 GLsizei height,
956 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400957 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400958 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400959 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400960 GLsizei imageSize)
961{
Corentin Wallez336129f2017-10-17 15:55:40 -0400962 gl::Buffer *pixelUnpackBuffer =
963 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400964 if (pixelUnpackBuffer == nullptr && imageSize < 0)
965 {
966 // Checks are not required
967 return true;
968 }
969
970 // ...the data would be unpacked from the buffer object such that the memory reads required
971 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400972 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
973 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400974 const gl::Extents size(width, height, depth);
975 const auto &unpack = context->getGLState().getUnpackState();
976
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800977 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Geoff Langff5b2d52016-09-07 11:32:23 -0400978 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
979 if (endByteOrErr.isError())
980 {
981 context->handleError(endByteOrErr.getError());
982 return false;
983 }
984
985 GLuint endByte = endByteOrErr.getResult();
986
987 if (pixelUnpackBuffer)
988 {
989 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
990 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
991 checkedEndByte += checkedOffset;
992
993 if (!checkedEndByte.IsValid() ||
994 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
995 {
996 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500997 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -0400998 return false;
999 }
James Darpiniane8a93c62018-01-04 18:02:24 -08001000 if (context->getExtensions().webglCompatibility &&
1001 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
1002 {
1003 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1004 PixelUnpackBufferBoundForTransformFeedback);
1005 return false;
1006 }
Geoff Langff5b2d52016-09-07 11:32:23 -04001007 }
1008 else
1009 {
1010 ASSERT(imageSize >= 0);
1011 if (pixels == nullptr && imageSize != 0)
1012 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001013 context->handleError(InvalidOperation()
1014 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001015 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001016 }
1017
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001018 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001019 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001020 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001021 return false;
1022 }
1023 }
1024
1025 return true;
1026}
1027
Corentin Wallezad3ae902018-03-09 13:40:42 -05001028bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -05001029{
Geoff Lang37dde692014-01-31 16:34:54 -05001030 switch (queryType)
1031 {
Corentin Wallezad3ae902018-03-09 13:40:42 -05001032 case QueryType::AnySamples:
1033 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001034 return context->getClientMajorVersion() >= 3 ||
1035 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -05001036 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +08001037 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -05001038 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +08001039 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -05001040 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +08001041 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -05001042 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +08001043 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +08001044 default:
1045 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001046 }
1047}
1048
Jamie Madill5b772312018-03-08 20:28:32 -05001049bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001050 GLenum type,
1051 GLboolean normalized,
1052 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001053 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001054 bool pureInteger)
1055{
1056 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001057 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1058 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1059 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1060 // parameter exceeds 255.
1061 constexpr GLsizei kMaxWebGLStride = 255;
1062 if (stride > kMaxWebGLStride)
1063 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001064 context->handleError(InvalidValue()
1065 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001066 return false;
1067 }
1068
1069 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1070 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1071 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1072 // or an INVALID_OPERATION error is generated.
1073 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1074 size_t typeSize = GetVertexFormatTypeSize(internalType);
1075
1076 ASSERT(isPow2(typeSize) && typeSize > 0);
1077 size_t sizeMask = (typeSize - 1);
1078 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1079 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001080 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001081 return false;
1082 }
1083
1084 if ((stride & sizeMask) != 0)
1085 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001086 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001087 return false;
1088 }
1089
1090 return true;
1091}
1092
Jamie Madill5b772312018-03-08 20:28:32 -05001093Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001094{
He Yunchaoced53ae2016-11-29 15:00:51 +08001095 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1096 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1097 // or program object and INVALID_OPERATION if the provided name identifies an object
1098 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001099
Dian Xiang769769a2015-09-09 15:20:08 -07001100 Program *validProgram = context->getProgram(id);
1101
1102 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001103 {
Dian Xiang769769a2015-09-09 15:20:08 -07001104 if (context->getShader(id))
1105 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001106 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001107 }
1108 else
1109 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001110 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001111 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001112 }
Dian Xiang769769a2015-09-09 15:20:08 -07001113
1114 return validProgram;
1115}
1116
Jamie Madill5b772312018-03-08 20:28:32 -05001117Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001118{
1119 // See ValidProgram for spec details.
1120
1121 Shader *validShader = context->getShader(id);
1122
1123 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001124 {
Dian Xiang769769a2015-09-09 15:20:08 -07001125 if (context->getProgram(id))
1126 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001127 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001128 }
1129 else
1130 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001131 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001132 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001133 }
Dian Xiang769769a2015-09-09 15:20:08 -07001134
1135 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001136}
1137
Geoff Langb1196682014-07-23 13:47:29 -04001138bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001139{
Geoff Langfa125c92017-10-24 13:01:46 -04001140 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001141 {
Geoff Langfa125c92017-10-24 13:01:46 -04001142 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1143 {
1144 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1145 return false;
1146 }
Jamie Madillb4472272014-07-03 10:38:55 -04001147
Geoff Langfa125c92017-10-24 13:01:46 -04001148 // Color attachment 0 is validated below because it is always valid
1149 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001150 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001151 {
Geoff Langfa125c92017-10-24 13:01:46 -04001152 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001153 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001154 }
1155 }
1156 else
1157 {
1158 switch (attachment)
1159 {
Geoff Langfa125c92017-10-24 13:01:46 -04001160 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001161 case GL_DEPTH_ATTACHMENT:
1162 case GL_STENCIL_ATTACHMENT:
1163 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001164
He Yunchaoced53ae2016-11-29 15:00:51 +08001165 case GL_DEPTH_STENCIL_ATTACHMENT:
1166 if (!context->getExtensions().webglCompatibility &&
1167 context->getClientMajorVersion() < 3)
1168 {
Geoff Langfa125c92017-10-24 13:01:46 -04001169 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001170 return false;
1171 }
1172 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001173
He Yunchaoced53ae2016-11-29 15:00:51 +08001174 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001175 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001176 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001177 }
1178 }
1179
1180 return true;
1181}
1182
Jamie Madill5b772312018-03-08 20:28:32 -05001183bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001184 GLenum target,
1185 GLsizei samples,
1186 GLenum internalformat,
1187 GLsizei width,
1188 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001189{
1190 switch (target)
1191 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001192 case GL_RENDERBUFFER:
1193 break;
1194 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001195 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001196 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001197 }
1198
1199 if (width < 0 || height < 0 || samples < 0)
1200 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001201 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001202 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001203 }
1204
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001205 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1206 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1207
1208 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04001209 if (!formatCaps.renderbuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001210 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001211 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001212 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001213 }
1214
1215 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1216 // 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 -08001217 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001218 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1219 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001220 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001221 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001222 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001223 }
1224
Geoff Langaae65a42014-05-26 12:43:44 -04001225 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001226 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001227 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001228 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001229 }
1230
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001231 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001232 if (handle == 0)
1233 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001234 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001235 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001236 }
1237
1238 return true;
1239}
1240
He Yunchaoced53ae2016-11-29 15:00:51 +08001241bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1242 GLenum target,
1243 GLenum attachment,
1244 GLenum renderbuffertarget,
1245 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001246{
Geoff Lange8afa902017-09-27 15:00:43 -04001247 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001248 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001249 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001250 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001251 }
1252
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001253 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001254
Jamie Madill84115c92015-04-23 15:00:07 -04001255 ASSERT(framebuffer);
1256 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001257 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001258 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001259 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001260 }
1261
Jamie Madillb4472272014-07-03 10:38:55 -04001262 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001263 {
Jamie Madillb4472272014-07-03 10:38:55 -04001264 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001265 }
1266
Jamie Madillab9d82c2014-01-21 16:38:14 -05001267 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1268 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1269 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1270 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1271 if (renderbuffer != 0)
1272 {
1273 if (!context->getRenderbuffer(renderbuffer))
1274 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001275 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001276 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001277 }
1278 }
1279
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001280 return true;
1281}
1282
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001283bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001284 GLint srcX0,
1285 GLint srcY0,
1286 GLint srcX1,
1287 GLint srcY1,
1288 GLint dstX0,
1289 GLint dstY0,
1290 GLint dstX1,
1291 GLint dstY1,
1292 GLbitfield mask,
1293 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001294{
1295 switch (filter)
1296 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001297 case GL_NEAREST:
1298 break;
1299 case GL_LINEAR:
1300 break;
1301 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001302 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001303 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001304 }
1305
1306 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1307 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001308 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001309 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001310 }
1311
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001312 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1313 // color buffer, leaving only nearest being unfiltered from above
1314 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1315 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001316 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001317 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001318 }
1319
Jamie Madill51f40ec2016-06-15 14:06:00 -04001320 const auto &glState = context->getGLState();
1321 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1322 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001323
1324 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001325 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001326 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001327 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001328 }
1329
Jamie Madill427064d2018-04-13 16:20:34 -04001330 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001331 {
Jamie Madill48faf802014-11-06 15:27:22 -05001332 return false;
1333 }
1334
Jamie Madill427064d2018-04-13 16:20:34 -04001335 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001336 {
Jamie Madill48faf802014-11-06 15:27:22 -05001337 return false;
1338 }
1339
Qin Jiajiaaef92162018-02-27 13:51:44 +08001340 if (readFramebuffer->id() == drawFramebuffer->id())
1341 {
1342 context->handleError(InvalidOperation());
1343 return false;
1344 }
1345
Jamie Madille98b1b52018-03-08 09:47:23 -05001346 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001347 {
Geoff Langb1196682014-07-23 13:47:29 -04001348 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001349 }
1350
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001351 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1352 // always run it in order to avoid triggering driver bugs.
1353 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1354 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001355 {
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001356 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1357 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001358 }
1359
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001360 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1361
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001362 if (mask & GL_COLOR_BUFFER_BIT)
1363 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001364 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001365 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001366
He Yunchao66a41a22016-12-15 16:45:05 +08001367 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001368 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001369 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001370
Geoff Langa15472a2015-08-11 11:48:03 -04001371 for (size_t drawbufferIdx = 0;
1372 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001373 {
Geoff Langa15472a2015-08-11 11:48:03 -04001374 const FramebufferAttachment *attachment =
1375 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1376 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001377 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001378 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001379
Geoff Langb2f3d052013-08-13 12:49:27 -04001380 // The GL ES 3.0.2 spec (pg 193) states that:
1381 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001382 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1383 // as well
1384 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1385 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001386 // Changes with EXT_color_buffer_float:
1387 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001388 GLenum readComponentType = readFormat.info->componentType;
1389 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001390 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001391 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001392 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001393 drawComponentType == GL_SIGNED_NORMALIZED);
1394
1395 if (extensions.colorBufferFloat)
1396 {
1397 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1398 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1399
1400 if (readFixedOrFloat != drawFixedOrFloat)
1401 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001402 context->handleError(InvalidOperation()
1403 << "If the read buffer contains fixed-point or "
1404 "floating-point values, the draw buffer must "
1405 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001406 return false;
1407 }
1408 }
1409 else if (readFixedPoint != drawFixedPoint)
1410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001411 context->handleError(InvalidOperation()
1412 << "If the read buffer contains fixed-point values, "
1413 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001414 return false;
1415 }
1416
1417 if (readComponentType == GL_UNSIGNED_INT &&
1418 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001419 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001420 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001421 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001422 }
1423
Jamie Madill6163c752015-12-07 16:32:59 -05001424 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001425 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001426 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001427 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001428 }
1429
Jamie Madilla3944d42016-07-22 22:13:26 -04001430 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001431 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001432 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001433 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001434 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001435 }
Geoff Lange4915782017-04-12 15:19:07 -04001436
1437 if (context->getExtensions().webglCompatibility &&
1438 *readColorBuffer == *attachment)
1439 {
1440 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001441 InvalidOperation()
1442 << "Read and write color 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 }
1446 }
1447
Jamie Madilla3944d42016-07-22 22:13:26 -04001448 if ((readFormat.info->componentType == GL_INT ||
1449 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1450 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001451 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001452 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001453 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001454 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001455 }
He Yunchao66a41a22016-12-15 16:45:05 +08001456 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1457 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1458 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1459 // situation is an application error that would lead to a crash in ANGLE.
1460 else if (drawFramebuffer->hasEnabledDrawBuffer())
1461 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001462 context->handleError(
1463 InvalidOperation()
1464 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001465 return false;
1466 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001467 }
1468
He Yunchaoced53ae2016-11-29 15:00:51 +08001469 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001470 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1471 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001472 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001473 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001474 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001475 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001476 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001477 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001478 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001479
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001480 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001481 {
Kenneth Russell69382852017-07-21 16:38:44 -04001482 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001483 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001484 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001485 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001486 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001487
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001488 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001489 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001490 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001491 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001492 }
Geoff Lange4915782017-04-12 15:19:07 -04001493
1494 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1495 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001496 context->handleError(
1497 InvalidOperation()
1498 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001499 return false;
1500 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001501 }
He Yunchao66a41a22016-12-15 16:45:05 +08001502 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1503 else if (drawBuffer)
1504 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001505 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1506 "depth/stencil attachment of a "
1507 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001508 return false;
1509 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001510 }
1511 }
1512
Martin Radeva3ed4572017-07-27 18:29:37 +03001513 // ANGLE_multiview, Revision 1:
1514 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1515 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1516 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1517 {
1518 context->handleError(InvalidFramebufferOperation()
1519 << "Attempt to read from a multi-view framebuffer.");
1520 return false;
1521 }
1522 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1523 {
1524 context->handleError(InvalidFramebufferOperation()
1525 << "Attempt to write to a multi-view framebuffer.");
1526 return false;
1527 }
1528
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001529 return true;
1530}
1531
Jamie Madill4928b7c2017-06-20 12:57:39 -04001532bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001533 GLint x,
1534 GLint y,
1535 GLsizei width,
1536 GLsizei height,
1537 GLenum format,
1538 GLenum type,
1539 GLsizei bufSize,
1540 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001541 GLsizei *columns,
1542 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001543 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001544{
1545 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001546 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001547 return false;
1548 }
1549
Brandon Jonesd1049182018-03-28 10:02:20 -07001550 GLsizei writeLength = 0;
1551 GLsizei writeColumns = 0;
1552 GLsizei writeRows = 0;
1553
1554 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1555 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001556 {
Geoff Langb1196682014-07-23 13:47:29 -04001557 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001558 }
1559
Brandon Jonesd1049182018-03-28 10:02:20 -07001560 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001561 {
Geoff Langb1196682014-07-23 13:47:29 -04001562 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001563 }
1564
Brandon Jonesd1049182018-03-28 10:02:20 -07001565 SetRobustLengthParam(length, writeLength);
1566 SetRobustLengthParam(columns, writeColumns);
1567 SetRobustLengthParam(rows, writeRows);
1568
Jamie Madillc29968b2016-01-20 11:17:23 -05001569 return true;
1570}
1571
1572bool ValidateReadnPixelsEXT(Context *context,
1573 GLint x,
1574 GLint y,
1575 GLsizei width,
1576 GLsizei height,
1577 GLenum format,
1578 GLenum type,
1579 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001580 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001581{
1582 if (bufSize < 0)
1583 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001584 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001585 return false;
1586 }
1587
Geoff Lang62fce5b2016-09-30 10:46:35 -04001588 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001589 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001590}
Jamie Madill26e91952014-03-05 15:01:27 -05001591
Jamie Madill4928b7c2017-06-20 12:57:39 -04001592bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001593 GLint x,
1594 GLint y,
1595 GLsizei width,
1596 GLsizei height,
1597 GLenum format,
1598 GLenum type,
1599 GLsizei bufSize,
1600 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001601 GLsizei *columns,
1602 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001603 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001604{
Brandon Jonesd1049182018-03-28 10:02:20 -07001605 GLsizei writeLength = 0;
1606 GLsizei writeColumns = 0;
1607 GLsizei writeRows = 0;
1608
Geoff Lang62fce5b2016-09-30 10:46:35 -04001609 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001610 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001611 return false;
1612 }
1613
Brandon Jonesd1049182018-03-28 10:02:20 -07001614 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1615 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001616 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001617 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001618 }
1619
Brandon Jonesd1049182018-03-28 10:02:20 -07001620 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001621 {
1622 return false;
1623 }
1624
Brandon Jonesd1049182018-03-28 10:02:20 -07001625 SetRobustLengthParam(length, writeLength);
1626 SetRobustLengthParam(columns, writeColumns);
1627 SetRobustLengthParam(rows, writeRows);
1628
Geoff Lang62fce5b2016-09-30 10:46:35 -04001629 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001630}
1631
Jamie Madillf0e04492017-08-26 15:28:42 -04001632bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001633{
1634 if (!context->getExtensions().occlusionQueryBoolean &&
1635 !context->getExtensions().disjointTimerQuery)
1636 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001637 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001638 return false;
1639 }
1640
Olli Etuaho41997e72016-03-10 13:38:39 +02001641 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001642}
1643
Jamie Madillf0e04492017-08-26 15:28:42 -04001644bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001645{
1646 if (!context->getExtensions().occlusionQueryBoolean &&
1647 !context->getExtensions().disjointTimerQuery)
1648 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001649 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001650 return false;
1651 }
1652
Olli Etuaho41997e72016-03-10 13:38:39 +02001653 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001654}
1655
Jamie Madillf0e04492017-08-26 15:28:42 -04001656bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1657{
1658 if (!context->getExtensions().occlusionQueryBoolean &&
1659 !context->getExtensions().disjointTimerQuery)
1660 {
1661 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1662 return false;
1663 }
1664
1665 return true;
1666}
1667
Corentin Wallezad3ae902018-03-09 13:40:42 -05001668bool ValidateBeginQueryBase(gl::Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001669{
1670 if (!ValidQueryType(context, target))
1671 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001672 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001673 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001674 }
1675
1676 if (id == 0)
1677 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001678 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001679 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001680 }
1681
1682 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1683 // of zero, if the active query object name for <target> is non-zero (for the
1684 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1685 // the active query for either target is non-zero), if <id> is the name of an
1686 // existing query object whose type does not match <target>, or if <id> is the
1687 // active query object name for any query type, the error INVALID_OPERATION is
1688 // generated.
1689
1690 // Ensure no other queries are active
1691 // NOTE: If other queries than occlusion are supported, we will need to check
1692 // separately that:
1693 // a) The query ID passed is not the current active query for any target/type
1694 // b) There are no active queries for the requested target (and in the case
1695 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1696 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001697
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001698 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001699 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001700 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001701 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001702 }
1703
1704 Query *queryObject = context->getQuery(id, true, target);
1705
1706 // check that name was obtained with glGenQueries
1707 if (!queryObject)
1708 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001709 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001710 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001711 }
1712
1713 // check for type mismatch
1714 if (queryObject->getType() != target)
1715 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001716 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001717 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001718 }
1719
1720 return true;
1721}
1722
Corentin Wallezad3ae902018-03-09 13:40:42 -05001723bool ValidateBeginQueryEXT(gl::Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001724{
1725 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001726 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001727 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001728 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001729 return false;
1730 }
1731
1732 return ValidateBeginQueryBase(context, target, id);
1733}
1734
Corentin Wallezad3ae902018-03-09 13:40:42 -05001735bool ValidateEndQueryBase(gl::Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001736{
1737 if (!ValidQueryType(context, target))
1738 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001739 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001740 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001741 }
1742
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001743 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001744
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001745 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001746 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001747 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001748 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001749 }
1750
Jamie Madill45c785d2014-05-13 14:09:34 -04001751 return true;
1752}
1753
Corentin Wallezad3ae902018-03-09 13:40:42 -05001754bool ValidateEndQueryEXT(gl::Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001755{
1756 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001757 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001758 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001759 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001760 return false;
1761 }
1762
1763 return ValidateEndQueryBase(context, target);
1764}
1765
Corentin Wallezad3ae902018-03-09 13:40:42 -05001766bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001767{
1768 if (!context->getExtensions().disjointTimerQuery)
1769 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001770 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001771 return false;
1772 }
1773
Corentin Wallezad3ae902018-03-09 13:40:42 -05001774 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001775 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001776 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001777 return false;
1778 }
1779
1780 Query *queryObject = context->getQuery(id, true, target);
1781 if (queryObject == nullptr)
1782 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001783 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001784 return false;
1785 }
1786
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001787 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001788 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001789 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001790 return false;
1791 }
1792
1793 return true;
1794}
1795
Corentin Wallezad3ae902018-03-09 13:40:42 -05001796bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001797{
Geoff Lang2186c382016-10-14 10:54:54 -04001798 if (numParams)
1799 {
1800 *numParams = 0;
1801 }
1802
Corentin Wallezad3ae902018-03-09 13:40:42 -05001803 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001804 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001805 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001806 return false;
1807 }
1808
1809 switch (pname)
1810 {
1811 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001812 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001813 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001814 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001815 return false;
1816 }
1817 break;
1818 case GL_QUERY_COUNTER_BITS_EXT:
1819 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001820 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001821 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001822 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001823 return false;
1824 }
1825 break;
1826 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001827 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001828 return false;
1829 }
1830
Geoff Lang2186c382016-10-14 10:54:54 -04001831 if (numParams)
1832 {
1833 // All queries return only one value
1834 *numParams = 1;
1835 }
1836
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001837 return true;
1838}
1839
Corentin Wallezad3ae902018-03-09 13:40:42 -05001840bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001841{
1842 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001843 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001844 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001845 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001846 return false;
1847 }
1848
Geoff Lang2186c382016-10-14 10:54:54 -04001849 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001850}
1851
Geoff Lang2186c382016-10-14 10:54:54 -04001852bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001853 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001854 GLenum pname,
1855 GLsizei bufSize,
1856 GLsizei *length,
1857 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001858{
Geoff Lang2186c382016-10-14 10:54:54 -04001859 if (!ValidateRobustEntryPoint(context, bufSize))
1860 {
1861 return false;
1862 }
1863
Brandon Jonesd1049182018-03-28 10:02:20 -07001864 GLsizei numParams = 0;
1865
1866 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001867 {
1868 return false;
1869 }
1870
Brandon Jonesd1049182018-03-28 10:02:20 -07001871 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001872 {
1873 return false;
1874 }
1875
Brandon Jonesd1049182018-03-28 10:02:20 -07001876 SetRobustLengthParam(length, numParams);
1877
Geoff Lang2186c382016-10-14 10:54:54 -04001878 return true;
1879}
1880
1881bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1882{
1883 if (numParams)
1884 {
1885 *numParams = 0;
1886 }
1887
Corentin Wallezad3ae902018-03-09 13:40:42 -05001888 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001889
1890 if (!queryObject)
1891 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001892 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001893 return false;
1894 }
1895
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001896 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001897 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001898 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001899 return false;
1900 }
1901
1902 switch (pname)
1903 {
1904 case GL_QUERY_RESULT_EXT:
1905 case GL_QUERY_RESULT_AVAILABLE_EXT:
1906 break;
1907
1908 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001909 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001910 return false;
1911 }
1912
Geoff Lang2186c382016-10-14 10:54:54 -04001913 if (numParams)
1914 {
1915 *numParams = 1;
1916 }
1917
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001918 return true;
1919}
1920
1921bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1922{
1923 if (!context->getExtensions().disjointTimerQuery)
1924 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001925 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001926 return false;
1927 }
Geoff Lang2186c382016-10-14 10:54:54 -04001928 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1929}
1930
1931bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1932 GLuint id,
1933 GLenum pname,
1934 GLsizei bufSize,
1935 GLsizei *length,
1936 GLint *params)
1937{
1938 if (!context->getExtensions().disjointTimerQuery)
1939 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001940 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001941 return false;
1942 }
1943
1944 if (!ValidateRobustEntryPoint(context, bufSize))
1945 {
1946 return false;
1947 }
1948
Brandon Jonesd1049182018-03-28 10:02:20 -07001949 GLsizei numParams = 0;
1950
1951 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001952 {
1953 return false;
1954 }
1955
Brandon Jonesd1049182018-03-28 10:02:20 -07001956 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001957 {
1958 return false;
1959 }
1960
Brandon Jonesd1049182018-03-28 10:02:20 -07001961 SetRobustLengthParam(length, numParams);
1962
Geoff Lang2186c382016-10-14 10:54:54 -04001963 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001964}
1965
1966bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1967{
1968 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001969 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001970 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001971 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001972 return false;
1973 }
Geoff Lang2186c382016-10-14 10:54:54 -04001974 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1975}
1976
1977bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1978 GLuint id,
1979 GLenum pname,
1980 GLsizei bufSize,
1981 GLsizei *length,
1982 GLuint *params)
1983{
1984 if (!context->getExtensions().disjointTimerQuery &&
1985 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1986 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001987 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001988 return false;
1989 }
1990
1991 if (!ValidateRobustEntryPoint(context, bufSize))
1992 {
1993 return false;
1994 }
1995
Brandon Jonesd1049182018-03-28 10:02:20 -07001996 GLsizei numParams = 0;
1997
1998 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001999 {
2000 return false;
2001 }
2002
Brandon Jonesd1049182018-03-28 10:02:20 -07002003 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002004 {
2005 return false;
2006 }
2007
Brandon Jonesd1049182018-03-28 10:02:20 -07002008 SetRobustLengthParam(length, numParams);
2009
Geoff Lang2186c382016-10-14 10:54:54 -04002010 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002011}
2012
2013bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2014{
2015 if (!context->getExtensions().disjointTimerQuery)
2016 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002017 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002018 return false;
2019 }
Geoff Lang2186c382016-10-14 10:54:54 -04002020 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2021}
2022
2023bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2024 GLuint id,
2025 GLenum pname,
2026 GLsizei bufSize,
2027 GLsizei *length,
2028 GLint64 *params)
2029{
2030 if (!context->getExtensions().disjointTimerQuery)
2031 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002032 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002033 return false;
2034 }
2035
2036 if (!ValidateRobustEntryPoint(context, bufSize))
2037 {
2038 return false;
2039 }
2040
Brandon Jonesd1049182018-03-28 10:02:20 -07002041 GLsizei numParams = 0;
2042
2043 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002044 {
2045 return false;
2046 }
2047
Brandon Jonesd1049182018-03-28 10:02:20 -07002048 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002049 {
2050 return false;
2051 }
2052
Brandon Jonesd1049182018-03-28 10:02:20 -07002053 SetRobustLengthParam(length, numParams);
2054
Geoff Lang2186c382016-10-14 10:54:54 -04002055 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002056}
2057
2058bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2059{
2060 if (!context->getExtensions().disjointTimerQuery)
2061 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002062 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002063 return false;
2064 }
Geoff Lang2186c382016-10-14 10:54:54 -04002065 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2066}
2067
2068bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2069 GLuint id,
2070 GLenum pname,
2071 GLsizei bufSize,
2072 GLsizei *length,
2073 GLuint64 *params)
2074{
2075 if (!context->getExtensions().disjointTimerQuery)
2076 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002077 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002078 return false;
2079 }
2080
2081 if (!ValidateRobustEntryPoint(context, bufSize))
2082 {
2083 return false;
2084 }
2085
Brandon Jonesd1049182018-03-28 10:02:20 -07002086 GLsizei numParams = 0;
2087
2088 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002089 {
2090 return false;
2091 }
2092
Brandon Jonesd1049182018-03-28 10:02:20 -07002093 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002094 {
2095 return false;
2096 }
2097
Brandon Jonesd1049182018-03-28 10:02:20 -07002098 SetRobustLengthParam(length, numParams);
2099
Geoff Lang2186c382016-10-14 10:54:54 -04002100 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002101}
2102
Jamie Madill5b772312018-03-08 20:28:32 -05002103bool ValidateUniformCommonBase(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002104 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002105 GLint location,
2106 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002107 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002108{
Jiajia Qin5451d532017-11-16 17:16:34 +08002109 // TODO(Jiajia): Add image uniform check in future.
2110 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002111 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002112 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002113 return false;
2114 }
2115
Jiajia Qin5451d532017-11-16 17:16:34 +08002116 if (!program)
2117 {
2118 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2119 return false;
2120 }
2121
2122 if (!program->isLinked())
2123 {
2124 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2125 return false;
2126 }
2127
2128 if (location == -1)
2129 {
2130 // Silently ignore the uniform command
2131 return false;
2132 }
2133
2134 const auto &uniformLocations = program->getUniformLocations();
2135 size_t castedLocation = static_cast<size_t>(location);
2136 if (castedLocation >= uniformLocations.size())
2137 {
2138 context->handleError(InvalidOperation() << "Invalid uniform location");
2139 return false;
2140 }
2141
2142 const auto &uniformLocation = uniformLocations[castedLocation];
2143 if (uniformLocation.ignored)
2144 {
2145 // Silently ignore the uniform command
2146 return false;
2147 }
2148
2149 if (!uniformLocation.used())
2150 {
2151 context->handleError(InvalidOperation());
2152 return false;
2153 }
2154
2155 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2156
2157 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002158 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002159 {
2160 context->handleError(InvalidOperation());
2161 return false;
2162 }
2163
2164 *uniformOut = &uniform;
2165 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002166}
2167
Jamie Madill5b772312018-03-08 20:28:32 -05002168bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002169 GLenum uniformType,
2170 GLsizei count,
2171 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002172{
Jiajia Qin5451d532017-11-16 17:16:34 +08002173 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2174 // It is compatible with INT or BOOL.
2175 // Do these cheap tests first, for a little extra speed.
2176 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002177 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002178 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002179 }
2180
Jiajia Qin5451d532017-11-16 17:16:34 +08002181 if (IsSamplerType(uniformType))
2182 {
2183 // Check that the values are in range.
2184 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2185 for (GLsizei i = 0; i < count; ++i)
2186 {
2187 if (value[i] < 0 || value[i] >= max)
2188 {
2189 context->handleError(InvalidValue() << "sampler uniform value out of range");
2190 return false;
2191 }
2192 }
2193 return true;
2194 }
2195
2196 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2197 return false;
2198}
2199
Jamie Madill5b772312018-03-08 20:28:32 -05002200bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002201{
2202 // Check that the value type is compatible with uniform type.
2203 // Do the cheaper test first, for a little extra speed.
2204 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2205 {
2206 return true;
2207 }
2208
2209 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2210 return false;
2211}
2212
Jamie Madill5b772312018-03-08 20:28:32 -05002213bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002214{
2215 // Check that the value type is compatible with uniform type.
2216 if (valueType == uniformType)
2217 {
2218 return true;
2219 }
2220
2221 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2222 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002223}
2224
Jamie Madill5b772312018-03-08 20:28:32 -05002225bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002226{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002227 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002228 gl::Program *programObject = context->getGLState().getProgram();
2229 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2230 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002231}
2232
Jamie Madill5b772312018-03-08 20:28:32 -05002233bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002234{
2235 const LinkedUniform *uniform = nullptr;
2236 gl::Program *programObject = context->getGLState().getProgram();
2237 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2238 ValidateUniform1ivValue(context, uniform->type, count, value);
2239}
2240
Jamie Madill5b772312018-03-08 20:28:32 -05002241bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002242 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002243 GLint location,
2244 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002245 GLboolean transpose)
2246{
Geoff Lang92019432017-11-20 13:09:34 -05002247 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002248 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002249 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002250 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002251 }
2252
Jamie Madill62d31cb2015-09-11 13:25:51 -04002253 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002254 gl::Program *programObject = context->getGLState().getProgram();
2255 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2256 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002257}
2258
Jamie Madill5b772312018-03-08 20:28:32 -05002259bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002260{
2261 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2262 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002263 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002264 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002265 }
2266
Jamie Madill0af26e12015-03-05 19:54:33 -05002267 const Caps &caps = context->getCaps();
2268
Jamie Madill893ab082014-05-16 16:56:10 -04002269 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2270 {
2271 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2272
Jamie Madill0af26e12015-03-05 19:54:33 -05002273 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002274 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002275 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002276 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002277 }
2278 }
2279
2280 switch (pname)
2281 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002282 case GL_TEXTURE_BINDING_2D:
2283 case GL_TEXTURE_BINDING_CUBE_MAP:
2284 case GL_TEXTURE_BINDING_3D:
2285 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002286 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002287 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002288 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2289 if (!context->getExtensions().textureRectangle)
2290 {
2291 context->handleError(InvalidEnum()
2292 << "ANGLE_texture_rectangle extension not present");
2293 return false;
2294 }
2295 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002296 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2297 if (!context->getExtensions().eglStreamConsumerExternal &&
2298 !context->getExtensions().eglImageExternal)
2299 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002300 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2301 "nor GL_OES_EGL_image_external "
2302 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002303 return false;
2304 }
2305 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002306
He Yunchaoced53ae2016-11-29 15:00:51 +08002307 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2308 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002309 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002310 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2311 ASSERT(readFramebuffer);
2312
Jamie Madill427064d2018-04-13 16:20:34 -04002313 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002314 {
Geoff Langb1196682014-07-23 13:47:29 -04002315 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002316 }
2317
Jamie Madille98b1b52018-03-08 09:47:23 -05002318 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002319 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002320 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002321 return false;
2322 }
2323
Jamie Madille98b1b52018-03-08 09:47:23 -05002324 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002325 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002326 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002327 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002328 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002329 }
2330 }
2331 break;
2332
He Yunchaoced53ae2016-11-29 15:00:51 +08002333 default:
2334 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002335 }
2336
2337 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002338 if (*numParams == 0)
2339 {
2340 return false;
2341 }
2342
2343 return true;
2344}
2345
Brandon Jonesd1049182018-03-28 10:02:20 -07002346bool ValidateGetBooleanvRobustANGLE(Context *context,
2347 GLenum pname,
2348 GLsizei bufSize,
2349 GLsizei *length,
2350 GLboolean *params)
2351{
2352 GLenum nativeType;
2353 unsigned int numParams = 0;
2354
2355 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2356 {
2357 return false;
2358 }
2359
2360 SetRobustLengthParam(length, numParams);
2361
2362 return true;
2363}
2364
2365bool ValidateGetFloatvRobustANGLE(Context *context,
2366 GLenum pname,
2367 GLsizei bufSize,
2368 GLsizei *length,
2369 GLfloat *params)
2370{
2371 GLenum nativeType;
2372 unsigned int numParams = 0;
2373
2374 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2375 {
2376 return false;
2377 }
2378
2379 SetRobustLengthParam(length, numParams);
2380
2381 return true;
2382}
2383
2384bool ValidateGetIntegervRobustANGLE(Context *context,
2385 GLenum pname,
2386 GLsizei bufSize,
2387 GLsizei *length,
2388 GLint *data)
2389{
2390 GLenum nativeType;
2391 unsigned int numParams = 0;
2392
2393 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2394 {
2395 return false;
2396 }
2397
2398 SetRobustLengthParam(length, numParams);
2399
2400 return true;
2401}
2402
2403bool ValidateGetInteger64vRobustANGLE(Context *context,
2404 GLenum pname,
2405 GLsizei bufSize,
2406 GLsizei *length,
2407 GLint64 *data)
2408{
2409 GLenum nativeType;
2410 unsigned int numParams = 0;
2411
2412 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2413 {
2414 return false;
2415 }
2416
2417 if (nativeType == GL_INT_64_ANGLEX)
2418 {
2419 CastStateValues(context, nativeType, pname, numParams, data);
2420 return false;
2421 }
2422
2423 SetRobustLengthParam(length, numParams);
2424 return true;
2425}
2426
Jamie Madill5b772312018-03-08 20:28:32 -05002427bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002428 GLenum pname,
2429 GLsizei bufSize,
2430 GLenum *nativeType,
2431 unsigned int *numParams)
2432{
2433 if (!ValidateRobustEntryPoint(context, bufSize))
2434 {
2435 return false;
2436 }
2437
2438 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2439 {
2440 return false;
2441 }
2442
2443 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002444 {
2445 return false;
2446 }
2447
2448 return true;
2449}
2450
Jamie Madill5b772312018-03-08 20:28:32 -05002451bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002452 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002453 GLint level,
2454 GLenum internalformat,
2455 bool isSubImage,
2456 GLint xoffset,
2457 GLint yoffset,
2458 GLint zoffset,
2459 GLint x,
2460 GLint y,
2461 GLsizei width,
2462 GLsizei height,
2463 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002464 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002465{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002466 TextureType texType = TextureTargetToType(target);
2467
Brandon Jones6cad5662017-06-14 13:25:13 -07002468 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002469 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002470 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2471 return false;
2472 }
2473
2474 if (width < 0 || height < 0)
2475 {
2476 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002477 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002478 }
2479
He Yunchaoced53ae2016-11-29 15:00:51 +08002480 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2481 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002482 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002483 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002484 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002485 }
2486
2487 if (border != 0)
2488 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002489 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002490 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002491 }
2492
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002493 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002494 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002495 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002496 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002497 }
2498
Jamie Madille98b1b52018-03-08 09:47:23 -05002499 const gl::State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002500 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002501 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002502 {
Geoff Langb1196682014-07-23 13:47:29 -04002503 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002504 }
2505
Jamie Madille98b1b52018-03-08 09:47:23 -05002506 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002507 {
Geoff Langb1196682014-07-23 13:47:29 -04002508 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002509 }
2510
Martin Radev138064f2016-07-15 12:03:41 +03002511 if (readFramebuffer->getReadBufferState() == GL_NONE)
2512 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002513 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002514 return false;
2515 }
2516
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002517 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2518 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002519 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002520 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002521 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2522 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002523 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002524 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002525 return false;
2526 }
2527
Martin Radev04e2c3b2017-07-27 16:54:35 +03002528 // ANGLE_multiview spec, Revision 1:
2529 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2530 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2531 // is not NONE.
2532 if (source->getMultiviewLayout() != GL_NONE)
2533 {
2534 context->handleError(InvalidFramebufferOperation()
2535 << "The active read framebuffer object has multiview attachments.");
2536 return false;
2537 }
2538
Geoff Langaae65a42014-05-26 12:43:44 -04002539 const gl::Caps &caps = context->getCaps();
2540
Geoff Langaae65a42014-05-26 12:43:44 -04002541 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002542 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002543 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002544 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002545 maxDimension = caps.max2DTextureSize;
2546 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002547
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002548 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002549 maxDimension = caps.maxCubeMapTextureSize;
2550 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002551
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002552 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002553 maxDimension = caps.maxRectangleTextureSize;
2554 break;
2555
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002556 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002557 maxDimension = caps.max2DTextureSize;
2558 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002559
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002560 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002561 maxDimension = caps.max3DTextureSize;
2562 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002563
He Yunchaoced53ae2016-11-29 15:00:51 +08002564 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002565 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002566 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002567 }
2568
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002569 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002570 if (!texture)
2571 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002572 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002573 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002574 }
2575
Geoff Lang69cce582015-09-17 13:20:36 -04002576 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002577 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002578 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002579 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002580 }
2581
Geoff Langca271392017-04-05 12:30:00 -04002582 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002583 isSubImage ? *texture->getFormat(target, level).info
2584 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002585
Geoff Lang966c9402017-04-18 12:38:27 -04002586 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002587 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002588 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002589 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002590 }
2591
2592 if (isSubImage)
2593 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002594 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2595 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2596 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002597 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002598 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002599 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002600 }
2601 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002602 else
2603 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002604 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002605 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002606 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002607 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002608 }
2609
Geoff Langeb66a6e2016-10-31 13:06:12 -04002610 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002611 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002612 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002613 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002614 }
2615
2616 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002617 if (static_cast<int>(width) > maxLevelDimension ||
2618 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002619 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002620 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002621 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002622 }
2623 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002624
Jamie Madill0c8abca2016-07-22 20:21:26 -04002625 if (textureFormatOut)
2626 {
2627 *textureFormatOut = texture->getFormat(target, level);
2628 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002629
2630 // Detect texture copying feedback loops for WebGL.
2631 if (context->getExtensions().webglCompatibility)
2632 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002633 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002634 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002635 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002636 return false;
2637 }
2638 }
2639
Jamie Madill560a8d82014-05-21 13:06:20 -04002640 return true;
2641}
2642
Jamie Madill493f9572018-05-24 19:52:15 -04002643bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002644{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002645 const Extensions &extensions = context->getExtensions();
2646
Jamie Madill1aeb1312014-06-20 13:21:25 -04002647 switch (mode)
2648 {
Jamie Madill493f9572018-05-24 19:52:15 -04002649 case PrimitiveMode::Points:
2650 case PrimitiveMode::Lines:
2651 case PrimitiveMode::LineLoop:
2652 case PrimitiveMode::LineStrip:
2653 case PrimitiveMode::Triangles:
2654 case PrimitiveMode::TriangleStrip:
2655 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002656 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002657
Jamie Madill493f9572018-05-24 19:52:15 -04002658 case PrimitiveMode::LinesAdjacency:
2659 case PrimitiveMode::LineStripAdjacency:
2660 case PrimitiveMode::TrianglesAdjacency:
2661 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002662 if (!extensions.geometryShader)
2663 {
2664 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2665 return false;
2666 }
2667 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002668 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002669 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002670 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002671 }
2672
Jamie Madill250d33f2014-06-06 17:09:03 -04002673 if (count < 0)
2674 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002675 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002676 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002677 }
2678
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002679 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002680
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002681 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2682 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2683 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2684 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002685 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002686 // Check for mapped buffers
2687 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002688 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002689 {
2690 context->handleError(InvalidOperation());
2691 return false;
2692 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002693 }
2694
Jamie Madillcbcde722017-01-06 14:50:00 -05002695 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2696 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002697 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002698 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002699 {
Ken Russellb9f92502018-01-27 19:00:26 -08002700 ASSERT(framebuffer);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002701 const FramebufferAttachment *dsAttachment =
2702 framebuffer->getStencilOrDepthStencilAttachment();
Ken Russellb9f92502018-01-27 19:00:26 -08002703 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2704 ASSERT(stencilBits <= 8);
2705
Jinyoung Hur85769f02015-10-20 17:08:44 -04002706 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Ken Russellb9f92502018-01-27 19:00:26 -08002707 if (depthStencilState.stencilTest && stencilBits > 0)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002708 {
Ken Russellb9f92502018-01-27 19:00:26 -08002709 GLuint maxStencilValue = (1 << stencilBits) - 1;
2710
2711 bool differentRefs =
2712 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2713 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2714 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2715 (depthStencilState.stencilBackWritemask & maxStencilValue);
2716 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2717 (depthStencilState.stencilBackMask & maxStencilValue);
2718
2719 if (differentRefs || differentWritemasks || differentMasks)
Jamie Madillcbcde722017-01-06 14:50:00 -05002720 {
Ken Russellb9f92502018-01-27 19:00:26 -08002721 if (!extensions.webglCompatibility)
2722 {
2723 ERR() << "This ANGLE implementation does not support separate front/back "
2724 "stencil writemasks, reference values, or stencil mask values.";
2725 }
2726 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
2727 return false;
Jamie Madillcbcde722017-01-06 14:50:00 -05002728 }
Geoff Lang3a86ad32015-09-01 11:47:05 -04002729 }
Jamie Madillac528012014-06-20 13:21:23 -04002730 }
2731
Jamie Madill427064d2018-04-13 16:20:34 -04002732 if (!ValidateFramebufferComplete(context, framebuffer))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002733 {
Geoff Langb1196682014-07-23 13:47:29 -04002734 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002735 }
2736
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002737 // If we are running GLES1, there is no current program.
2738 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002739 {
Jamie Madilld4cfa572014-07-08 10:00:32 -04002740
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002741 gl::Program *program = state.getProgram();
2742 if (!program)
Martin Radev7cf61662017-07-26 17:10:53 +03002743 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002744 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Martin Radev7cf61662017-07-26 17:10:53 +03002745 return false;
2746 }
Martin Radev7e69f762017-07-27 14:54:13 +03002747
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002748 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2749 // vertex shader stage or fragment shader stage is a undefined behaviour.
2750 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2751 // produce undefined result.
2752 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2753 !program->hasLinkedShaderStage(ShaderType::Fragment))
Martin Radev7e69f762017-07-27 14:54:13 +03002754 {
2755 context->handleError(InvalidOperation()
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002756 << "It is a undefined behaviour to render without "
2757 "vertex shader stage or fragment shader stage.");
Martin Radev7e69f762017-07-27 14:54:13 +03002758 return false;
2759 }
Martin Radevffe754b2017-07-31 10:38:07 +03002760
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002761 if (!program->validateSamplers(nullptr, context->getCaps()))
Martin Radevffe754b2017-07-31 10:38:07 +03002762 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002763 context->handleError(InvalidOperation());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002764 return false;
2765 }
2766
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002767 if (extensions.multiview)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002768 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002769 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2770 const int framebufferNumViews = framebuffer->getNumViews();
2771 if (framebufferNumViews != programNumViews)
2772 {
2773 context->handleError(InvalidOperation()
2774 << "The number of views in the active program "
2775 "and draw framebuffer does not match.");
2776 return false;
2777 }
2778
2779 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2780 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2781 framebufferNumViews > 1)
2782 {
2783 context->handleError(InvalidOperation()
2784 << "There is an active transform feedback object "
2785 "when the number of views in the active draw "
2786 "framebuffer is greater than 1.");
2787 return false;
2788 }
2789
2790 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2791 state.isQueryActive(QueryType::TimeElapsed))
2792 {
2793 context->handleError(InvalidOperation()
2794 << "There is an active query for target "
2795 "GL_TIME_ELAPSED_EXT when the number of "
2796 "views in the active draw framebuffer is "
2797 "greater than 1.");
2798 return false;
2799 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002800 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002801
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002802 // Do geometry shader specific validations
2803 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002804 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002805 if (!IsCompatibleDrawModeWithGeometryShader(
2806 mode, program->getGeometryShaderInputPrimitiveType()))
2807 {
2808 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2809 IncompatibleDrawModeAgainstGeometryShader);
2810 return false;
2811 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002812 }
Geoff Lange0cff192017-05-30 13:04:56 -04002813
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002814 // Uniform buffer validation
2815 for (unsigned int uniformBlockIndex = 0;
2816 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Geoff Lang9ab5b822017-05-30 16:19:23 -04002817 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002818 const gl::InterfaceBlock &uniformBlock =
2819 program->getUniformBlockByIndex(uniformBlockIndex);
2820 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
2821 const OffsetBindingPointer<Buffer> &uniformBuffer =
2822 state.getIndexedUniformBuffer(blockBinding);
2823
2824 if (uniformBuffer.get() == nullptr)
2825 {
2826 // undefined behaviour
2827 context->handleError(
2828 InvalidOperation()
2829 << "It is undefined behaviour to have a used but unbound uniform buffer.");
2830 return false;
2831 }
2832
2833 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2834 if (uniformBufferSize < uniformBlock.dataSize)
2835 {
2836 // undefined behaviour
2837 context->handleError(
2838 InvalidOperation()
2839 << "It is undefined behaviour to use a uniform buffer that is too small.");
2840 return false;
2841 }
2842
2843 if (extensions.webglCompatibility &&
2844 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2845 {
2846 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2847 UniformBufferBoundForTransformFeedback);
2848 return false;
2849 }
Geoff Lang9ab5b822017-05-30 16:19:23 -04002850 }
2851
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002852 // Do some additonal WebGL-specific validation
2853 if (extensions.webglCompatibility)
Geoff Lange0cff192017-05-30 13:04:56 -04002854 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002855 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2856 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2857 transformFeedbackObject->buffersBoundForOtherUse())
2858 {
2859 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2860 TransformFeedbackBufferDoubleBound);
2861 return false;
2862 }
2863 // Detect rendering feedback loops for WebGL.
2864 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2865 {
2866 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
2867 return false;
2868 }
2869
2870 // Detect that the vertex shader input types match the attribute types
2871 if (!ValidateVertexShaderAttributeTypeMatch(context))
2872 {
2873 return false;
2874 }
2875
2876 // Detect that the color buffer types match the fragment shader output types
2877 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2878 {
2879 return false;
2880 }
Geoff Lange0cff192017-05-30 13:04:56 -04002881 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002882 }
2883
Jamie Madill9fdaa492018-02-16 10:52:11 -05002884 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002885}
2886
Jamie Madill5b772312018-03-08 20:28:32 -05002887bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002888 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002889 GLint first,
2890 GLsizei count,
2891 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002892{
Jamie Madillfd716582014-06-06 17:09:04 -04002893 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002894 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002895 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002896 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002897 }
2898
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002899 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002900 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002901 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002902 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002903 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002904 if (!ValidateTransformFeedbackPrimitiveMode(context,
2905 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002906 {
James Darpinian30b604d2018-03-12 17:26:57 -07002907 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2908 return false;
2909 }
2910
2911 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2912 {
2913 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2914 return false;
2915 }
Jamie Madillfd716582014-06-06 17:09:04 -04002916 }
2917
Jiajia Qind9671222016-11-29 16:30:31 +08002918 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002919 {
2920 return false;
2921 }
2922
Corentin Wallez71168a02016-12-19 15:11:18 -08002923 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002924 // - first < 0 has been checked as an error condition.
2925 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002926 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002927 ASSERT(first >= 0);
2928 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002929 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002930 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2931 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2932 {
2933 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2934 return false;
2935 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002936
Jamie Madill9fdaa492018-02-16 10:52:11 -05002937 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2938 {
2939 return false;
2940 }
Jamie Madillfd716582014-06-06 17:09:04 -04002941 }
2942
2943 return true;
2944}
2945
He Yunchaoced53ae2016-11-29 15:00:51 +08002946bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002947 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002948 GLint first,
2949 GLsizei count,
2950 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002951{
Geoff Lang63c5a592017-09-27 14:08:16 -04002952 if (!context->getExtensions().instancedArrays)
2953 {
2954 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2955 return false;
2956 }
2957
Corentin Wallez170efbf2017-05-02 13:45:01 -04002958 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002959 {
2960 return false;
2961 }
2962
Corentin Wallez0dc97812017-06-22 14:38:44 -04002963 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002964}
2965
Jamie Madill493f9572018-05-24 19:52:15 -04002966bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002967{
Jamie Madill250d33f2014-06-06 17:09:03 -04002968 switch (type)
2969 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002970 case GL_UNSIGNED_BYTE:
2971 case GL_UNSIGNED_SHORT:
2972 break;
2973 case GL_UNSIGNED_INT:
2974 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2975 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002976 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002977 return false;
2978 }
2979 break;
2980 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002981 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002982 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002983 }
2984
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002985 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002986
2987 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002988 if (curTransformFeedback && curTransformFeedback->isActive() &&
2989 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002990 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002991 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2992 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2993 if (context->getExtensions().geometryShader)
2994 {
2995 if (!ValidateTransformFeedbackPrimitiveMode(
2996 context, curTransformFeedback->getPrimitiveMode(), mode))
2997 {
2998 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2999 return false;
3000 }
3001 }
3002 else
3003 {
3004 // It is an invalid operation to call DrawElements, DrawRangeElements or
3005 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
3006 // 86)
3007 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3008 UnsupportedDrawModeForTransformFeedback);
3009 return false;
3010 }
Jamie Madill250d33f2014-06-06 17:09:03 -04003011 }
3012
Jiajia Qind9671222016-11-29 16:30:31 +08003013 return true;
3014}
3015
Jamie Madill5b772312018-03-08 20:28:32 -05003016bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003017 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003018 GLsizei count,
3019 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003020 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003021 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08003022{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08003023 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08003024 return false;
3025
3026 const State &state = context->getGLState();
3027
Corentin Wallez170efbf2017-05-02 13:45:01 -04003028 if (!ValidateDrawBase(context, mode, count))
3029 {
3030 return false;
3031 }
3032
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003033 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
3034 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
3035 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
3036 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04003037 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003038 // Check for mapped buffers
3039 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04003040 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003041 {
3042 context->handleError(InvalidOperation() << "Index buffer is mapped.");
3043 return false;
3044 }
Jamie Madill250d33f2014-06-06 17:09:03 -04003045 }
3046
He Yunchaoced53ae2016-11-29 15:00:51 +08003047 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003048 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003049
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003050 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3051
3052 if (context->getExtensions().webglCompatibility)
3053 {
3054 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3055 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3056 {
3057 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3058 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3059 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003060 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003061 return false;
3062 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003063
3064 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3065 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3066 // error is generated.
3067 if (reinterpret_cast<intptr_t>(indices) < 0)
3068 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003069 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003070 return false;
3071 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003072 }
3073
3074 if (context->getExtensions().webglCompatibility ||
3075 !context->getGLState().areClientArraysEnabled())
3076 {
Brandon Jones2a018152018-06-08 15:59:26 -07003077 if (!elementArrayBuffer)
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003078 {
3079 // [WebGL 1.0] Section 6.2 No Client Side Arrays
Brandon Jones2a018152018-06-08 15:59:26 -07003080 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3081 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003082 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003083 return false;
3084 }
3085 }
3086
Jamie Madill9fdaa492018-02-16 10:52:11 -05003087 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003088 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003089 // This is an application error that would normally result in a crash, but we catch it and
3090 // return an error
3091 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3092 return false;
3093 }
3094
3095 if (count > 0 && elementArrayBuffer)
3096 {
3097 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3098 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3099 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3100 constexpr uint64_t kMaxTypeSize = 8;
3101 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3102 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3103 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3104
3105 uint64_t typeSize = typeBytes;
3106 uint64_t elementCount = static_cast<uint64_t>(count);
3107 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3108
3109 // Doing the multiplication here is overflow-safe
3110 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3111
3112 // The offset can be any value, check for overflows
3113 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3114 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003115 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003116 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3117 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003118 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003119
3120 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3121 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003122 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003123 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3124 return false;
3125 }
3126
3127 ASSERT(isPow2(typeSize) && typeSize > 0);
3128 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3129 {
3130 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003131 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003132 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003133
3134 if (context->getExtensions().webglCompatibility &&
3135 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3136 {
3137 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3138 ElementArrayBufferBoundForTransformFeedback);
3139 return false;
3140 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003141 }
3142
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003143 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003144 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003145 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
3146 // access is enabled.
3147 if (!ValidateDrawAttribs(context, primcount, 0, 1))
3148 {
3149 return false;
3150 }
3151 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003152 else if (count == 0)
3153 {
3154 // ValidateDrawAttribs also does some extra validation that is independent of the vertex
3155 // count.
3156 if (!ValidateDrawAttribs(context, 0, 0, 0))
3157 {
3158 return false;
3159 }
3160 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003161 else
3162 {
3163 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003164 const DrawCallParams &params = context->getParams<DrawCallParams>();
3165 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3166 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003167
3168 // If we use an index greater than our maximum supported index range, return an error.
3169 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3170 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003171 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003172 {
3173 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3174 return false;
3175 }
3176
Jamie Madill6f5444d2018-03-14 10:08:11 -04003177 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end),
3178 static_cast<GLint>(indexRange.vertexCount())))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003179 {
3180 return false;
3181 }
3182
3183 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003184 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003185 }
3186
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003187 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003188}
3189
Jamie Madill5b772312018-03-08 20:28:32 -05003190bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003191 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003192 GLsizei count,
3193 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003194 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003195 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003196{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003197 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003198}
3199
Geoff Lang3edfe032015-09-04 16:38:24 -04003200bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003201 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003202 GLsizei count,
3203 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003204 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003205 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003206{
Geoff Lang63c5a592017-09-27 14:08:16 -04003207 if (!context->getExtensions().instancedArrays)
3208 {
3209 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3210 return false;
3211 }
3212
Corentin Wallez170efbf2017-05-02 13:45:01 -04003213 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003214 {
3215 return false;
3216 }
3217
Corentin Wallez0dc97812017-06-22 14:38:44 -04003218 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003219}
3220
He Yunchaoced53ae2016-11-29 15:00:51 +08003221bool ValidateFramebufferTextureBase(Context *context,
3222 GLenum target,
3223 GLenum attachment,
3224 GLuint texture,
3225 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003226{
Geoff Lange8afa902017-09-27 15:00:43 -04003227 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003228 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003229 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003230 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003231 }
3232
3233 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003234 {
3235 return false;
3236 }
3237
Jamie Madill55ec3b12014-07-03 10:38:57 -04003238 if (texture != 0)
3239 {
3240 gl::Texture *tex = context->getTexture(texture);
3241
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003242 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003243 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003244 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003245 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003246 }
3247
3248 if (level < 0)
3249 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003250 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003251 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003252 }
3253 }
3254
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003255 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003256 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003257
Jamie Madill84115c92015-04-23 15:00:07 -04003258 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003259 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003260 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003261 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003262 }
3263
3264 return true;
3265}
3266
Geoff Langb1196682014-07-23 13:47:29 -04003267bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003268{
3269 if (program == 0)
3270 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003271 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003272 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003273 }
3274
Dian Xiang769769a2015-09-09 15:20:08 -07003275 gl::Program *programObject = GetValidProgram(context, program);
3276 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003277 {
3278 return false;
3279 }
3280
Jamie Madill0063c512014-08-25 15:47:53 -04003281 if (!programObject || !programObject->isLinked())
3282 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003283 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003284 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003285 }
3286
Geoff Lang7dd2e102014-11-10 15:19:26 -05003287 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003288 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003289 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003290 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003291 }
3292
Jamie Madill0063c512014-08-25 15:47:53 -04003293 return true;
3294}
3295
Geoff Langf41d0ee2016-10-07 13:04:23 -04003296static bool ValidateSizedGetUniform(Context *context,
3297 GLuint program,
3298 GLint location,
3299 GLsizei bufSize,
3300 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003301{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003302 if (length)
3303 {
3304 *length = 0;
3305 }
3306
Jamie Madill78f41802014-08-25 15:47:55 -04003307 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003308 {
Jamie Madill78f41802014-08-25 15:47:55 -04003309 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003310 }
3311
Geoff Langf41d0ee2016-10-07 13:04:23 -04003312 if (bufSize < 0)
3313 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003314 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003315 return false;
3316 }
3317
Jamie Madilla502c742014-08-28 17:19:13 -04003318 gl::Program *programObject = context->getProgram(program);
3319 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003320
Jamie Madill78f41802014-08-25 15:47:55 -04003321 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003322 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003323 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003324 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003325 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003326 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003327 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003328 }
3329
Geoff Langf41d0ee2016-10-07 13:04:23 -04003330 if (length)
3331 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003332 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003333 }
3334
Jamie Madill0063c512014-08-25 15:47:53 -04003335 return true;
3336}
3337
He Yunchaoced53ae2016-11-29 15:00:51 +08003338bool ValidateGetnUniformfvEXT(Context *context,
3339 GLuint program,
3340 GLint location,
3341 GLsizei bufSize,
3342 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003343{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003344 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003345}
3346
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003347bool ValidateGetnUniformfvRobustANGLE(Context *context,
3348 GLuint program,
3349 GLint location,
3350 GLsizei bufSize,
3351 GLsizei *length,
3352 GLfloat *params)
3353{
3354 UNIMPLEMENTED();
3355 return false;
3356}
3357
He Yunchaoced53ae2016-11-29 15:00:51 +08003358bool ValidateGetnUniformivEXT(Context *context,
3359 GLuint program,
3360 GLint location,
3361 GLsizei bufSize,
3362 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003363{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003364 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3365}
3366
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003367bool ValidateGetnUniformivRobustANGLE(Context *context,
3368 GLuint program,
3369 GLint location,
3370 GLsizei bufSize,
3371 GLsizei *length,
3372 GLint *params)
3373{
3374 UNIMPLEMENTED();
3375 return false;
3376}
3377
3378bool ValidateGetnUniformuivRobustANGLE(Context *context,
3379 GLuint program,
3380 GLint location,
3381 GLsizei bufSize,
3382 GLsizei *length,
3383 GLuint *params)
3384{
3385 UNIMPLEMENTED();
3386 return false;
3387}
3388
Geoff Langf41d0ee2016-10-07 13:04:23 -04003389bool ValidateGetUniformfvRobustANGLE(Context *context,
3390 GLuint program,
3391 GLint location,
3392 GLsizei bufSize,
3393 GLsizei *length,
3394 GLfloat *params)
3395{
3396 if (!ValidateRobustEntryPoint(context, bufSize))
3397 {
3398 return false;
3399 }
3400
Brandon Jonesd1049182018-03-28 10:02:20 -07003401 GLsizei writeLength = 0;
3402
Geoff Langf41d0ee2016-10-07 13:04:23 -04003403 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003404 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3405 {
3406 return false;
3407 }
3408
3409 SetRobustLengthParam(length, writeLength);
3410
3411 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003412}
3413
3414bool ValidateGetUniformivRobustANGLE(Context *context,
3415 GLuint program,
3416 GLint location,
3417 GLsizei bufSize,
3418 GLsizei *length,
3419 GLint *params)
3420{
3421 if (!ValidateRobustEntryPoint(context, bufSize))
3422 {
3423 return false;
3424 }
3425
Brandon Jonesd1049182018-03-28 10:02:20 -07003426 GLsizei writeLength = 0;
3427
Geoff Langf41d0ee2016-10-07 13:04:23 -04003428 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003429 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3430 {
3431 return false;
3432 }
3433
3434 SetRobustLengthParam(length, writeLength);
3435
3436 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003437}
3438
3439bool ValidateGetUniformuivRobustANGLE(Context *context,
3440 GLuint program,
3441 GLint location,
3442 GLsizei bufSize,
3443 GLsizei *length,
3444 GLuint *params)
3445{
3446 if (!ValidateRobustEntryPoint(context, bufSize))
3447 {
3448 return false;
3449 }
3450
3451 if (context->getClientMajorVersion() < 3)
3452 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003453 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003454 return false;
3455 }
3456
Brandon Jonesd1049182018-03-28 10:02:20 -07003457 GLsizei writeLength = 0;
3458
Geoff Langf41d0ee2016-10-07 13:04:23 -04003459 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003460 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3461 {
3462 return false;
3463 }
3464
3465 SetRobustLengthParam(length, writeLength);
3466
3467 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003468}
3469
He Yunchaoced53ae2016-11-29 15:00:51 +08003470bool ValidateDiscardFramebufferBase(Context *context,
3471 GLenum target,
3472 GLsizei numAttachments,
3473 const GLenum *attachments,
3474 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003475{
3476 if (numAttachments < 0)
3477 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003478 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003479 return false;
3480 }
3481
3482 for (GLsizei i = 0; i < numAttachments; ++i)
3483 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003484 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003485 {
3486 if (defaultFramebuffer)
3487 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003488 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003489 return false;
3490 }
3491
3492 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3493 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003494 context->handleError(InvalidOperation() << "Requested color attachment is "
3495 "greater than the maximum supported "
3496 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003497 return false;
3498 }
3499 }
3500 else
3501 {
3502 switch (attachments[i])
3503 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003504 case GL_DEPTH_ATTACHMENT:
3505 case GL_STENCIL_ATTACHMENT:
3506 case GL_DEPTH_STENCIL_ATTACHMENT:
3507 if (defaultFramebuffer)
3508 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003509 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3510 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003511 return false;
3512 }
3513 break;
3514 case GL_COLOR:
3515 case GL_DEPTH:
3516 case GL_STENCIL:
3517 if (!defaultFramebuffer)
3518 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003519 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3520 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003521 return false;
3522 }
3523 break;
3524 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003525 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003526 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003527 }
3528 }
3529 }
3530
3531 return true;
3532}
3533
Austin Kinross6ee1e782015-05-29 17:05:37 -07003534bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3535{
Jamie Madill007530e2017-12-28 14:27:04 -05003536 if (!context->getExtensions().debugMarker)
3537 {
3538 // The debug marker calls should not set error state
3539 // However, it seems reasonable to set an error state if the extension is not enabled
3540 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3541 return false;
3542 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003543
Jamie Madill007530e2017-12-28 14:27:04 -05003544 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003545 if (length < 0)
3546 {
3547 return false;
3548 }
3549
3550 if (marker == nullptr)
3551 {
3552 return false;
3553 }
3554
3555 return true;
3556}
3557
3558bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3559{
Jamie Madill007530e2017-12-28 14:27:04 -05003560 if (!context->getExtensions().debugMarker)
3561 {
3562 // The debug marker calls should not set error state
3563 // However, it seems reasonable to set an error state if the extension is not enabled
3564 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3565 return false;
3566 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003567
Jamie Madill007530e2017-12-28 14:27:04 -05003568 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003569 if (length < 0)
3570 {
3571 return false;
3572 }
3573
3574 if (length > 0 && marker == nullptr)
3575 {
3576 return false;
3577 }
3578
3579 return true;
3580}
3581
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003582bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003583{
Geoff Langa8406172015-07-21 16:53:39 -04003584 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3585 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003586 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003587 return false;
3588 }
3589
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003590 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003591 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003592 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003593 if (!context->getExtensions().eglImage)
3594 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003595 context->handleError(InvalidEnum()
3596 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003597 }
3598 break;
3599
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003600 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003601 if (!context->getExtensions().eglImageExternal)
3602 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003603 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3604 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003605 }
Geoff Langa8406172015-07-21 16:53:39 -04003606 break;
3607
3608 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003609 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003610 return false;
3611 }
3612
Rafael Cintron05a449a2018-06-20 18:08:04 -07003613 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003614
Jamie Madill61e16b42017-06-19 11:13:23 -04003615 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003616 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003617 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003618 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003619 return false;
3620 }
3621
Jamie Madill007530e2017-12-28 14:27:04 -05003622 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003623 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003624 context->handleError(InvalidOperation()
3625 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003626 return false;
3627 }
3628
Geoff Langca271392017-04-05 12:30:00 -04003629 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003630 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003631 if (!textureCaps.texturable)
3632 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003633 context->handleError(InvalidOperation()
3634 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003635 return false;
3636 }
3637
Geoff Langdcab33b2015-07-21 13:03:16 -04003638 return true;
3639}
3640
3641bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003642 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003643 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003644{
Geoff Langa8406172015-07-21 16:53:39 -04003645 if (!context->getExtensions().eglImage)
3646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003647 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003648 return false;
3649 }
3650
3651 switch (target)
3652 {
3653 case GL_RENDERBUFFER:
3654 break;
3655
3656 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003657 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003658 return false;
3659 }
3660
Rafael Cintron05a449a2018-06-20 18:08:04 -07003661 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003662
Jamie Madill61e16b42017-06-19 11:13:23 -04003663 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003664 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003665 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003666 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003667 return false;
3668 }
3669
Geoff Langca271392017-04-05 12:30:00 -04003670 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003671 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04003672 if (!textureCaps.renderbuffer)
Geoff Langa8406172015-07-21 16:53:39 -04003673 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003674 context->handleError(InvalidOperation()
3675 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003676 return false;
3677 }
3678
Geoff Langdcab33b2015-07-21 13:03:16 -04003679 return true;
3680}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003681
3682bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3683{
Geoff Lang36167ab2015-12-07 10:27:14 -05003684 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003685 {
3686 // The default VAO should always exist
3687 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003688 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003689 return false;
3690 }
3691
3692 return true;
3693}
3694
Geoff Langc5629752015-12-07 16:29:04 -05003695bool ValidateProgramBinaryBase(Context *context,
3696 GLuint program,
3697 GLenum binaryFormat,
3698 const void *binary,
3699 GLint length)
3700{
3701 Program *programObject = GetValidProgram(context, program);
3702 if (programObject == nullptr)
3703 {
3704 return false;
3705 }
3706
3707 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3708 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3709 programBinaryFormats.end())
3710 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003711 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003712 return false;
3713 }
3714
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003715 if (context->hasActiveTransformFeedback(program))
3716 {
3717 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003718 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3719 "is associated with an active transform "
3720 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003721 return false;
3722 }
3723
Geoff Langc5629752015-12-07 16:29:04 -05003724 return true;
3725}
3726
3727bool ValidateGetProgramBinaryBase(Context *context,
3728 GLuint program,
3729 GLsizei bufSize,
3730 GLsizei *length,
3731 GLenum *binaryFormat,
3732 void *binary)
3733{
3734 Program *programObject = GetValidProgram(context, program);
3735 if (programObject == nullptr)
3736 {
3737 return false;
3738 }
3739
3740 if (!programObject->isLinked())
3741 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003742 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003743 return false;
3744 }
3745
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003746 if (context->getCaps().programBinaryFormats.empty())
3747 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003748 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003749 return false;
3750 }
3751
Geoff Langc5629752015-12-07 16:29:04 -05003752 return true;
3753}
Jamie Madillc29968b2016-01-20 11:17:23 -05003754
Jamie Madill5b772312018-03-08 20:28:32 -05003755bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003756{
3757 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003758 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003759 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003760 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3761 return false;
3762 }
3763 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3764 {
3765 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003766 return false;
3767 }
3768
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003769 ASSERT(context->getGLState().getDrawFramebuffer());
3770 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003771 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3772
3773 // This should come first before the check for the default frame buffer
3774 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3775 // rather than INVALID_OPERATION
3776 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3777 {
3778 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3779
3780 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003781 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3782 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003783 {
3784 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003785 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3786 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3787 // 3.1 is still a bit ambiguous about the error, but future specs are
3788 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003789 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003790 return false;
3791 }
3792 else if (bufs[colorAttachment] >= maxColorAttachment)
3793 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003794 context->handleError(InvalidOperation()
3795 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003796 return false;
3797 }
3798 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3799 frameBufferId != 0)
3800 {
3801 // INVALID_OPERATION-GL is bound to buffer and ith argument
3802 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003803 context->handleError(InvalidOperation()
3804 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003805 return false;
3806 }
3807 }
3808
3809 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3810 // and n is not 1 or bufs is bound to value other than BACK and NONE
3811 if (frameBufferId == 0)
3812 {
3813 if (n != 1)
3814 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003815 context->handleError(InvalidOperation()
3816 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003817 return false;
3818 }
3819
3820 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3821 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003822 context->handleError(
3823 InvalidOperation()
3824 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003825 return false;
3826 }
3827 }
3828
3829 return true;
3830}
3831
Geoff Lang496c02d2016-10-20 11:38:11 -07003832bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003833 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003834 GLenum pname,
3835 GLsizei *length,
3836 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003837{
Geoff Lang496c02d2016-10-20 11:38:11 -07003838 if (length)
3839 {
3840 *length = 0;
3841 }
3842
3843 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3844 {
3845 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003846 InvalidOperation()
3847 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003848 return false;
3849 }
3850
Corentin Walleze4477002017-12-01 14:39:58 -05003851 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003852 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003853 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003854 return false;
3855 }
3856
Geoff Lang496c02d2016-10-20 11:38:11 -07003857 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003858 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003859 case GL_BUFFER_MAP_POINTER:
3860 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003861
Geoff Lang496c02d2016-10-20 11:38:11 -07003862 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003863 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003864 return false;
3865 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003866
3867 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3868 // target bound to zero generate an INVALID_OPERATION error."
3869 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003870 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003871 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003872 context->handleError(InvalidOperation()
3873 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003874 return false;
3875 }
3876
Geoff Lang496c02d2016-10-20 11:38:11 -07003877 if (length)
3878 {
3879 *length = 1;
3880 }
3881
Olli Etuaho4f667482016-03-30 15:56:35 +03003882 return true;
3883}
3884
Corentin Wallez336129f2017-10-17 15:55:40 -04003885bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003886{
Corentin Walleze4477002017-12-01 14:39:58 -05003887 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003888 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003889 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003890 return false;
3891 }
3892
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003893 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003894
3895 if (buffer == nullptr || !buffer->isMapped())
3896 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003897 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003898 return false;
3899 }
3900
3901 return true;
3902}
3903
3904bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003905 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003906 GLintptr offset,
3907 GLsizeiptr length,
3908 GLbitfield access)
3909{
Corentin Walleze4477002017-12-01 14:39:58 -05003910 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003911 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003912 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003913 return false;
3914 }
3915
Brandon Jones6cad5662017-06-14 13:25:13 -07003916 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003917 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003918 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3919 return false;
3920 }
3921
3922 if (length < 0)
3923 {
3924 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003925 return false;
3926 }
3927
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003928 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003929
3930 if (!buffer)
3931 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003932 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003933 return false;
3934 }
3935
3936 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003937 CheckedNumeric<size_t> checkedOffset(offset);
3938 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003939
Jamie Madille2e406c2016-06-02 13:04:10 -04003940 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003941 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003942 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003943 return false;
3944 }
3945
3946 // Check for invalid bits in the mask
3947 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3948 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3949 GL_MAP_UNSYNCHRONIZED_BIT;
3950
3951 if (access & ~(allAccessBits))
3952 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003953 context->handleError(InvalidValue()
3954 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003955 return false;
3956 }
3957
3958 if (length == 0)
3959 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003960 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003961 return false;
3962 }
3963
3964 if (buffer->isMapped())
3965 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003966 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003967 return false;
3968 }
3969
3970 // Check for invalid bit combinations
3971 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3972 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003973 context->handleError(InvalidOperation()
3974 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003975 return false;
3976 }
3977
3978 GLbitfield writeOnlyBits =
3979 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3980
3981 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3982 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003983 context->handleError(InvalidOperation()
3984 << "Invalid access bits when mapping buffer for reading: 0x"
3985 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003986 return false;
3987 }
3988
3989 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3990 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003991 context->handleError(
3992 InvalidOperation()
3993 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003994 return false;
3995 }
Geoff Lang79f71042017-08-14 16:43:43 -04003996
3997 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003998}
3999
4000bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004001 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03004002 GLintptr offset,
4003 GLsizeiptr length)
4004{
Brandon Jones6cad5662017-06-14 13:25:13 -07004005 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03004006 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004007 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
4008 return false;
4009 }
4010
4011 if (length < 0)
4012 {
4013 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03004014 return false;
4015 }
4016
Corentin Walleze4477002017-12-01 14:39:58 -05004017 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03004018 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004019 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03004020 return false;
4021 }
4022
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004023 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004024
4025 if (buffer == nullptr)
4026 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004027 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004028 return false;
4029 }
4030
4031 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4032 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004033 context->handleError(InvalidOperation()
4034 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004035 return false;
4036 }
4037
4038 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004039 CheckedNumeric<size_t> checkedOffset(offset);
4040 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004041
Jamie Madille2e406c2016-06-02 13:04:10 -04004042 if (!checkedSize.IsValid() ||
4043 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004044 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004045 context->handleError(InvalidValue()
4046 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004047 return false;
4048 }
4049
4050 return true;
4051}
4052
Olli Etuaho41997e72016-03-10 13:38:39 +02004053bool ValidateGenOrDelete(Context *context, GLint n)
4054{
4055 if (n < 0)
4056 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004057 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02004058 return false;
4059 }
4060 return true;
4061}
4062
Jamie Madill5b772312018-03-08 20:28:32 -05004063bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04004064{
4065 if (!context->getExtensions().robustClientMemory)
4066 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004067 context->handleError(InvalidOperation()
4068 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004069 return false;
4070 }
4071
4072 if (bufSize < 0)
4073 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004074 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004075 return false;
4076 }
4077
4078 return true;
4079}
4080
Jamie Madill5b772312018-03-08 20:28:32 -05004081bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004082{
4083 if (bufSize < numParams)
4084 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004085 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4086 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004087 return false;
4088 }
4089
4090 return true;
4091}
4092
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004093bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004094 GLenum target,
4095 GLenum attachment,
4096 GLenum pname,
4097 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004098{
Geoff Lange8afa902017-09-27 15:00:43 -04004099 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004100 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004101 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004102 return false;
4103 }
4104
4105 int clientVersion = context->getClientMajorVersion();
4106
4107 switch (pname)
4108 {
4109 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4110 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4111 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4112 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4113 break;
4114
Martin Radeve5285d22017-07-14 16:23:53 +03004115 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4116 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4117 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4118 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4119 if (clientVersion < 3 || !context->getExtensions().multiview)
4120 {
4121 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4122 return false;
4123 }
4124 break;
4125
Geoff Langff5b2d52016-09-07 11:32:23 -04004126 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4127 if (clientVersion < 3 && !context->getExtensions().sRGB)
4128 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004129 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004130 return false;
4131 }
4132 break;
4133
4134 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4135 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4136 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4137 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4138 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4139 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4140 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4141 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4142 if (clientVersion < 3)
4143 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004144 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004145 return false;
4146 }
4147 break;
4148
Jiawei Shaoa8802472018-05-28 11:17:47 +08004149 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4150 if (!context->getExtensions().geometryShader)
4151 {
4152 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4153 return false;
4154 }
4155 break;
4156
Geoff Langff5b2d52016-09-07 11:32:23 -04004157 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004158 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004159 return false;
4160 }
4161
4162 // Determine if the attachment is a valid enum
4163 switch (attachment)
4164 {
4165 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004166 case GL_DEPTH:
4167 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004168 if (clientVersion < 3)
4169 {
Geoff Langfa125c92017-10-24 13:01:46 -04004170 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004171 return false;
4172 }
4173 break;
4174
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004175 case GL_DEPTH_STENCIL_ATTACHMENT:
4176 if (clientVersion < 3 && !context->isWebGL1())
4177 {
4178 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4179 return false;
4180 }
4181 break;
4182
Geoff Langfa125c92017-10-24 13:01:46 -04004183 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004184 case GL_DEPTH_ATTACHMENT:
4185 case GL_STENCIL_ATTACHMENT:
4186 break;
4187
4188 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004189 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4190 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004191 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4192 {
Geoff Langfa125c92017-10-24 13:01:46 -04004193 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004194 return false;
4195 }
4196 break;
4197 }
4198
4199 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4200 ASSERT(framebuffer);
4201
4202 if (framebuffer->id() == 0)
4203 {
4204 if (clientVersion < 3)
4205 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004206 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004207 return false;
4208 }
4209
4210 switch (attachment)
4211 {
4212 case GL_BACK:
4213 case GL_DEPTH:
4214 case GL_STENCIL:
4215 break;
4216
4217 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004218 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004219 return false;
4220 }
4221 }
4222 else
4223 {
4224 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4225 {
4226 // Valid attachment query
4227 }
4228 else
4229 {
4230 switch (attachment)
4231 {
4232 case GL_DEPTH_ATTACHMENT:
4233 case GL_STENCIL_ATTACHMENT:
4234 break;
4235
4236 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004237 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004238 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004239 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004240 return false;
4241 }
4242 break;
4243
4244 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004245 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004246 return false;
4247 }
4248 }
4249 }
4250
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004251 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004252 if (attachmentObject)
4253 {
4254 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4255 attachmentObject->type() == GL_TEXTURE ||
4256 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4257
4258 switch (pname)
4259 {
4260 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4261 if (attachmentObject->type() != GL_RENDERBUFFER &&
4262 attachmentObject->type() != GL_TEXTURE)
4263 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004264 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004265 return false;
4266 }
4267 break;
4268
4269 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4270 if (attachmentObject->type() != GL_TEXTURE)
4271 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004272 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004273 return false;
4274 }
4275 break;
4276
4277 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4278 if (attachmentObject->type() != GL_TEXTURE)
4279 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004280 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004281 return false;
4282 }
4283 break;
4284
4285 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4286 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4287 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004288 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004289 return false;
4290 }
4291 break;
4292
4293 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4294 if (attachmentObject->type() != GL_TEXTURE)
4295 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004296 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004297 return false;
4298 }
4299 break;
4300
4301 default:
4302 break;
4303 }
4304 }
4305 else
4306 {
4307 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4308 // is NONE, then querying any other pname will generate INVALID_ENUM.
4309
4310 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4311 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4312 // INVALID_OPERATION for all other pnames
4313
4314 switch (pname)
4315 {
4316 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4317 break;
4318
4319 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4320 if (clientVersion < 3)
4321 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004322 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004323 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004324 return false;
4325 }
4326 break;
4327
4328 default:
4329 if (clientVersion < 3)
4330 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004331 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004332 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004333 return false;
4334 }
4335 else
4336 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004337 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004338 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004339 return false;
4340 }
4341 }
4342 }
4343
Martin Radeve5285d22017-07-14 16:23:53 +03004344 if (numParams)
4345 {
4346 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4347 {
4348 // Only when the viewport offsets are queried we can have a varying number of output
4349 // parameters.
4350 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4351 *numParams = numViews * 2;
4352 }
4353 else
4354 {
4355 // For all other queries we can have only one output parameter.
4356 *numParams = 1;
4357 }
4358 }
4359
Geoff Langff5b2d52016-09-07 11:32:23 -04004360 return true;
4361}
4362
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004363bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004364 GLenum target,
4365 GLenum attachment,
4366 GLenum pname,
4367 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004368 GLsizei *length,
4369 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004370{
4371 if (!ValidateRobustEntryPoint(context, bufSize))
4372 {
4373 return false;
4374 }
4375
Brandon Jonesd1049182018-03-28 10:02:20 -07004376 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004377 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004378 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004379 {
4380 return false;
4381 }
4382
Brandon Jonesd1049182018-03-28 10:02:20 -07004383 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004384 {
4385 return false;
4386 }
4387
Brandon Jonesd1049182018-03-28 10:02:20 -07004388 SetRobustLengthParam(length, numParams);
4389
Geoff Langff5b2d52016-09-07 11:32:23 -04004390 return true;
4391}
4392
Jamie Madill5b772312018-03-08 20:28:32 -05004393bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004394 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004395 GLenum pname,
4396 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004397 GLsizei *length,
4398 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004399{
4400 if (!ValidateRobustEntryPoint(context, bufSize))
4401 {
4402 return false;
4403 }
4404
Brandon Jonesd1049182018-03-28 10:02:20 -07004405 GLsizei numParams = 0;
4406
4407 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004408 {
4409 return false;
4410 }
4411
Brandon Jonesd1049182018-03-28 10:02:20 -07004412 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004413 {
4414 return false;
4415 }
4416
Brandon Jonesd1049182018-03-28 10:02:20 -07004417 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004418 return true;
4419}
4420
Jamie Madill5b772312018-03-08 20:28:32 -05004421bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004422 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004423 GLenum pname,
4424 GLsizei bufSize,
4425 GLsizei *length,
4426 GLint64 *params)
4427{
Brandon Jonesd1049182018-03-28 10:02:20 -07004428 GLsizei numParams = 0;
4429
Geoff Langebebe1c2016-10-14 12:01:31 -04004430 if (!ValidateRobustEntryPoint(context, bufSize))
4431 {
4432 return false;
4433 }
4434
Brandon Jonesd1049182018-03-28 10:02:20 -07004435 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004436 {
4437 return false;
4438 }
4439
Brandon Jonesd1049182018-03-28 10:02:20 -07004440 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004441 {
4442 return false;
4443 }
4444
Brandon Jonesd1049182018-03-28 10:02:20 -07004445 SetRobustLengthParam(length, numParams);
4446
Geoff Langff5b2d52016-09-07 11:32:23 -04004447 return true;
4448}
4449
Jamie Madill5b772312018-03-08 20:28:32 -05004450bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004451{
4452 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004453 if (numParams)
4454 {
4455 *numParams = 1;
4456 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004457
4458 Program *programObject = GetValidProgram(context, program);
4459 if (!programObject)
4460 {
4461 return false;
4462 }
4463
4464 switch (pname)
4465 {
4466 case GL_DELETE_STATUS:
4467 case GL_LINK_STATUS:
4468 case GL_VALIDATE_STATUS:
4469 case GL_INFO_LOG_LENGTH:
4470 case GL_ATTACHED_SHADERS:
4471 case GL_ACTIVE_ATTRIBUTES:
4472 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4473 case GL_ACTIVE_UNIFORMS:
4474 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4475 break;
4476
4477 case GL_PROGRAM_BINARY_LENGTH:
4478 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4479 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004480 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4481 "requires GL_OES_get_program_binary or "
4482 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004483 return false;
4484 }
4485 break;
4486
4487 case GL_ACTIVE_UNIFORM_BLOCKS:
4488 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4489 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4490 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4491 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4492 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4493 if (context->getClientMajorVersion() < 3)
4494 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004495 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004496 return false;
4497 }
4498 break;
4499
Yunchao He61afff12017-03-14 15:34:03 +08004500 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004501 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004502 if (context->getClientVersion() < Version(3, 1))
4503 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004504 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004505 return false;
4506 }
4507 break;
4508
Jiawei Shao6ae51612018-02-23 14:03:25 +08004509 case GL_COMPUTE_WORK_GROUP_SIZE:
4510 if (context->getClientVersion() < Version(3, 1))
4511 {
4512 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4513 return false;
4514 }
4515
4516 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4517 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4518 // program which has not been linked successfully, or which does not contain objects to
4519 // form a compute shader.
4520 if (!programObject->isLinked())
4521 {
4522 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4523 return false;
4524 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004525 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004526 {
4527 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4528 return false;
4529 }
4530 break;
4531
Jiawei Shao447bfac2018-03-14 14:23:40 +08004532 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4533 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4534 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4535 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4536 if (!context->getExtensions().geometryShader)
4537 {
4538 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4539 return false;
4540 }
4541
4542 // [EXT_geometry_shader] Chapter 7.12
4543 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4544 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4545 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4546 // successfully, or which does not contain objects to form a geometry shader.
4547 if (!programObject->isLinked())
4548 {
4549 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4550 return false;
4551 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004552 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004553 {
4554 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4555 return false;
4556 }
4557 break;
4558
Geoff Langff5b2d52016-09-07 11:32:23 -04004559 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004560 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004561 return false;
4562 }
4563
4564 return true;
4565}
4566
4567bool ValidateGetProgramivRobustANGLE(Context *context,
4568 GLuint program,
4569 GLenum pname,
4570 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004571 GLsizei *length,
4572 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004573{
4574 if (!ValidateRobustEntryPoint(context, bufSize))
4575 {
4576 return false;
4577 }
4578
Brandon Jonesd1049182018-03-28 10:02:20 -07004579 GLsizei numParams = 0;
4580
4581 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004582 {
4583 return false;
4584 }
4585
Brandon Jonesd1049182018-03-28 10:02:20 -07004586 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004587 {
4588 return false;
4589 }
4590
Brandon Jonesd1049182018-03-28 10:02:20 -07004591 SetRobustLengthParam(length, numParams);
4592
Geoff Langff5b2d52016-09-07 11:32:23 -04004593 return true;
4594}
4595
Geoff Lang740d9022016-10-07 11:20:52 -04004596bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4597 GLenum target,
4598 GLenum pname,
4599 GLsizei bufSize,
4600 GLsizei *length,
4601 GLint *params)
4602{
4603 if (!ValidateRobustEntryPoint(context, bufSize))
4604 {
4605 return false;
4606 }
4607
Brandon Jonesd1049182018-03-28 10:02:20 -07004608 GLsizei numParams = 0;
4609
4610 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004611 {
4612 return false;
4613 }
4614
Brandon Jonesd1049182018-03-28 10:02:20 -07004615 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004616 {
4617 return false;
4618 }
4619
Brandon Jonesd1049182018-03-28 10:02:20 -07004620 SetRobustLengthParam(length, numParams);
4621
Geoff Lang740d9022016-10-07 11:20:52 -04004622 return true;
4623}
4624
Geoff Langd7d0ed32016-10-07 11:33:51 -04004625bool ValidateGetShaderivRobustANGLE(Context *context,
4626 GLuint shader,
4627 GLenum pname,
4628 GLsizei bufSize,
4629 GLsizei *length,
4630 GLint *params)
4631{
4632 if (!ValidateRobustEntryPoint(context, bufSize))
4633 {
4634 return false;
4635 }
4636
Brandon Jonesd1049182018-03-28 10:02:20 -07004637 GLsizei numParams = 0;
4638
4639 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004640 {
4641 return false;
4642 }
4643
Brandon Jonesd1049182018-03-28 10:02:20 -07004644 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004645 {
4646 return false;
4647 }
4648
Brandon Jonesd1049182018-03-28 10:02:20 -07004649 SetRobustLengthParam(length, numParams);
4650
Geoff Langd7d0ed32016-10-07 11:33:51 -04004651 return true;
4652}
4653
Geoff Langc1984ed2016-10-07 12:41:00 -04004654bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004655 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004656 GLenum pname,
4657 GLsizei bufSize,
4658 GLsizei *length,
4659 GLfloat *params)
4660{
4661 if (!ValidateRobustEntryPoint(context, bufSize))
4662 {
4663 return false;
4664 }
4665
Brandon Jonesd1049182018-03-28 10:02:20 -07004666 GLsizei numParams = 0;
4667
4668 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004669 {
4670 return false;
4671 }
4672
Brandon Jonesd1049182018-03-28 10:02:20 -07004673 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004674 {
4675 return false;
4676 }
4677
Brandon Jonesd1049182018-03-28 10:02:20 -07004678 SetRobustLengthParam(length, numParams);
4679
Geoff Langc1984ed2016-10-07 12:41:00 -04004680 return true;
4681}
4682
Geoff Langc1984ed2016-10-07 12:41:00 -04004683bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004684 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004685 GLenum pname,
4686 GLsizei bufSize,
4687 GLsizei *length,
4688 GLint *params)
4689{
Brandon Jonesd1049182018-03-28 10:02:20 -07004690
Geoff Langc1984ed2016-10-07 12:41:00 -04004691 if (!ValidateRobustEntryPoint(context, bufSize))
4692 {
4693 return false;
4694 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004695 GLsizei numParams = 0;
4696 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004697 {
4698 return false;
4699 }
4700
Brandon Jonesd1049182018-03-28 10:02:20 -07004701 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004702 {
4703 return false;
4704 }
4705
Brandon Jonesd1049182018-03-28 10:02:20 -07004706 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004707 return true;
4708}
4709
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004710bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4711 TextureType target,
4712 GLenum pname,
4713 GLsizei bufSize,
4714 GLsizei *length,
4715 GLint *params)
4716{
4717 UNIMPLEMENTED();
4718 return false;
4719}
4720
4721bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4722 TextureType target,
4723 GLenum pname,
4724 GLsizei bufSize,
4725 GLsizei *length,
4726 GLuint *params)
4727{
4728 UNIMPLEMENTED();
4729 return false;
4730}
4731
Geoff Langc1984ed2016-10-07 12:41:00 -04004732bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004733 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004734 GLenum pname,
4735 GLsizei bufSize,
4736 const GLfloat *params)
4737{
4738 if (!ValidateRobustEntryPoint(context, bufSize))
4739 {
4740 return false;
4741 }
4742
4743 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4744}
4745
Geoff Langc1984ed2016-10-07 12:41:00 -04004746bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004747 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004748 GLenum pname,
4749 GLsizei bufSize,
4750 const GLint *params)
4751{
4752 if (!ValidateRobustEntryPoint(context, bufSize))
4753 {
4754 return false;
4755 }
4756
4757 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4758}
4759
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004760bool ValidateTexParameterIivRobustANGLE(Context *context,
4761 TextureType target,
4762 GLenum pname,
4763 GLsizei bufSize,
4764 const GLint *params)
4765{
4766 UNIMPLEMENTED();
4767 return false;
4768}
4769
4770bool ValidateTexParameterIuivRobustANGLE(Context *context,
4771 TextureType target,
4772 GLenum pname,
4773 GLsizei bufSize,
4774 const GLuint *params)
4775{
4776 UNIMPLEMENTED();
4777 return false;
4778}
4779
Geoff Langc1984ed2016-10-07 12:41:00 -04004780bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4781 GLuint sampler,
4782 GLenum pname,
4783 GLuint bufSize,
4784 GLsizei *length,
4785 GLfloat *params)
4786{
4787 if (!ValidateRobustEntryPoint(context, bufSize))
4788 {
4789 return false;
4790 }
4791
Brandon Jonesd1049182018-03-28 10:02:20 -07004792 GLsizei numParams = 0;
4793
4794 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004795 {
4796 return false;
4797 }
4798
Brandon Jonesd1049182018-03-28 10:02:20 -07004799 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004800 {
4801 return false;
4802 }
4803
Brandon Jonesd1049182018-03-28 10:02:20 -07004804 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004805 return true;
4806}
4807
Geoff Langc1984ed2016-10-07 12:41:00 -04004808bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4809 GLuint sampler,
4810 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004811 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004812 GLsizei *length,
4813 GLint *params)
4814{
4815 if (!ValidateRobustEntryPoint(context, bufSize))
4816 {
4817 return false;
4818 }
4819
Brandon Jonesd1049182018-03-28 10:02:20 -07004820 GLsizei numParams = 0;
4821
4822 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004823 {
4824 return false;
4825 }
4826
Brandon Jonesd1049182018-03-28 10:02:20 -07004827 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004828 {
4829 return false;
4830 }
4831
Brandon Jonesd1049182018-03-28 10:02:20 -07004832 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004833 return true;
4834}
4835
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004836bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4837 GLuint sampler,
4838 GLenum pname,
4839 GLsizei bufSize,
4840 GLsizei *length,
4841 GLint *params)
4842{
4843 UNIMPLEMENTED();
4844 return false;
4845}
4846
4847bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4848 GLuint sampler,
4849 GLenum pname,
4850 GLsizei bufSize,
4851 GLsizei *length,
4852 GLuint *params)
4853{
4854 UNIMPLEMENTED();
4855 return false;
4856}
4857
Geoff Langc1984ed2016-10-07 12:41:00 -04004858bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4859 GLuint sampler,
4860 GLenum pname,
4861 GLsizei bufSize,
4862 const GLfloat *params)
4863{
4864 if (!ValidateRobustEntryPoint(context, bufSize))
4865 {
4866 return false;
4867 }
4868
4869 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4870}
4871
Geoff Langc1984ed2016-10-07 12:41:00 -04004872bool ValidateSamplerParameterivRobustANGLE(Context *context,
4873 GLuint sampler,
4874 GLenum pname,
4875 GLsizei bufSize,
4876 const GLint *params)
4877{
4878 if (!ValidateRobustEntryPoint(context, bufSize))
4879 {
4880 return false;
4881 }
4882
4883 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4884}
4885
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004886bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4887 GLuint sampler,
4888 GLenum pname,
4889 GLsizei bufSize,
4890 const GLint *param)
4891{
4892 UNIMPLEMENTED();
4893 return false;
4894}
4895
4896bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4897 GLuint sampler,
4898 GLenum pname,
4899 GLsizei bufSize,
4900 const GLuint *param)
4901{
4902 UNIMPLEMENTED();
4903 return false;
4904}
4905
Geoff Lang0b031062016-10-13 14:30:04 -04004906bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4907 GLuint index,
4908 GLenum pname,
4909 GLsizei bufSize,
4910 GLsizei *length,
4911 GLfloat *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, false))
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);
Geoff Lang0b031062016-10-13 14:30:04 -04004931 return true;
4932}
4933
Geoff Lang0b031062016-10-13 14:30:04 -04004934bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4935 GLuint index,
4936 GLenum pname,
4937 GLsizei bufSize,
4938 GLsizei *length,
4939 GLint *params)
4940{
4941 if (!ValidateRobustEntryPoint(context, bufSize))
4942 {
4943 return false;
4944 }
4945
Brandon Jonesd1049182018-03-28 10:02:20 -07004946 GLsizei writeLength = 0;
4947
4948 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004949 {
4950 return false;
4951 }
4952
Brandon Jonesd1049182018-03-28 10:02:20 -07004953 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004954 {
4955 return false;
4956 }
4957
Brandon Jonesd1049182018-03-28 10:02:20 -07004958 SetRobustLengthParam(length, writeLength);
4959
Geoff Lang0b031062016-10-13 14:30:04 -04004960 return true;
4961}
4962
Geoff Lang0b031062016-10-13 14:30:04 -04004963bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4964 GLuint index,
4965 GLenum pname,
4966 GLsizei bufSize,
4967 GLsizei *length,
4968 void **pointer)
4969{
4970 if (!ValidateRobustEntryPoint(context, bufSize))
4971 {
4972 return false;
4973 }
4974
Brandon Jonesd1049182018-03-28 10:02:20 -07004975 GLsizei writeLength = 0;
4976
4977 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004978 {
4979 return false;
4980 }
4981
Brandon Jonesd1049182018-03-28 10:02:20 -07004982 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004983 {
4984 return false;
4985 }
4986
Brandon Jonesd1049182018-03-28 10:02:20 -07004987 SetRobustLengthParam(length, writeLength);
4988
Geoff Lang0b031062016-10-13 14:30:04 -04004989 return true;
4990}
4991
Geoff Lang0b031062016-10-13 14:30:04 -04004992bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4993 GLuint index,
4994 GLenum pname,
4995 GLsizei bufSize,
4996 GLsizei *length,
4997 GLint *params)
4998{
4999 if (!ValidateRobustEntryPoint(context, bufSize))
5000 {
5001 return false;
5002 }
5003
Brandon Jonesd1049182018-03-28 10:02:20 -07005004 GLsizei writeLength = 0;
5005
5006 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04005007 {
5008 return false;
5009 }
5010
Brandon Jonesd1049182018-03-28 10:02:20 -07005011 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04005012 {
5013 return false;
5014 }
5015
Brandon Jonesd1049182018-03-28 10:02:20 -07005016 SetRobustLengthParam(length, writeLength);
5017
Geoff Lang0b031062016-10-13 14:30:04 -04005018 return true;
5019}
5020
Geoff Lang0b031062016-10-13 14:30:04 -04005021bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5022 GLuint index,
5023 GLenum pname,
5024 GLsizei bufSize,
5025 GLsizei *length,
5026 GLuint *params)
5027{
5028 if (!ValidateRobustEntryPoint(context, bufSize))
5029 {
5030 return false;
5031 }
5032
Brandon Jonesd1049182018-03-28 10:02:20 -07005033 GLsizei writeLength = 0;
5034
5035 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04005036 {
5037 return false;
5038 }
5039
Brandon Jonesd1049182018-03-28 10:02:20 -07005040 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04005041 {
5042 return false;
5043 }
5044
Brandon Jonesd1049182018-03-28 10:02:20 -07005045 SetRobustLengthParam(length, writeLength);
5046
Geoff Lang0b031062016-10-13 14:30:04 -04005047 return true;
5048}
5049
Geoff Lang6899b872016-10-14 11:30:13 -04005050bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5051 GLuint program,
5052 GLuint uniformBlockIndex,
5053 GLenum pname,
5054 GLsizei bufSize,
5055 GLsizei *length,
5056 GLint *params)
5057{
5058 if (!ValidateRobustEntryPoint(context, bufSize))
5059 {
5060 return false;
5061 }
5062
Brandon Jonesd1049182018-03-28 10:02:20 -07005063 GLsizei writeLength = 0;
5064
5065 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
5066 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005067 {
5068 return false;
5069 }
5070
Brandon Jonesd1049182018-03-28 10:02:20 -07005071 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005072 {
5073 return false;
5074 }
5075
Brandon Jonesd1049182018-03-28 10:02:20 -07005076 SetRobustLengthParam(length, writeLength);
5077
Geoff Lang6899b872016-10-14 11:30:13 -04005078 return true;
5079}
5080
Brandon Jones416aaf92018-04-10 08:10:16 -07005081bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07005082 GLenum target,
5083 GLenum internalformat,
5084 GLenum pname,
5085 GLsizei bufSize,
5086 GLsizei *length,
5087 GLint *params)
5088{
5089 if (!ValidateRobustEntryPoint(context, bufSize))
5090 {
5091 return false;
5092 }
5093
Brandon Jonesd1049182018-03-28 10:02:20 -07005094 GLsizei numParams = 0;
5095
5096 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5097 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005098 {
5099 return false;
5100 }
5101
Brandon Jonesd1049182018-03-28 10:02:20 -07005102 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005103 {
5104 return false;
5105 }
5106
Brandon Jonesd1049182018-03-28 10:02:20 -07005107 SetRobustLengthParam(length, numParams);
5108
Geoff Lang0a9661f2016-10-20 10:59:20 -07005109 return true;
5110}
5111
Jamie Madill5b772312018-03-08 20:28:32 -05005112bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005113 GLuint attribIndex,
5114 GLint size,
5115 GLenum type,
5116 GLboolean pureInteger)
5117{
5118 const Caps &caps = context->getCaps();
5119 if (attribIndex >= caps.maxVertexAttributes)
5120 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005121 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005122 return false;
5123 }
5124
5125 if (size < 1 || size > 4)
5126 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005127 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005128 return false;
Shao80957d92017-02-20 21:25:59 +08005129 }
5130
5131 switch (type)
5132 {
5133 case GL_BYTE:
5134 case GL_UNSIGNED_BYTE:
5135 case GL_SHORT:
5136 case GL_UNSIGNED_SHORT:
5137 break;
5138
5139 case GL_INT:
5140 case GL_UNSIGNED_INT:
5141 if (context->getClientMajorVersion() < 3)
5142 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005143 context->handleError(InvalidEnum()
5144 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005145 return false;
5146 }
5147 break;
5148
5149 case GL_FIXED:
5150 case GL_FLOAT:
5151 if (pureInteger)
5152 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005153 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005154 return false;
5155 }
5156 break;
5157
5158 case GL_HALF_FLOAT:
5159 if (context->getClientMajorVersion() < 3)
5160 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005161 context->handleError(InvalidEnum()
5162 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005163 return false;
5164 }
5165 if (pureInteger)
5166 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005167 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005168 return false;
5169 }
5170 break;
5171
5172 case GL_INT_2_10_10_10_REV:
5173 case GL_UNSIGNED_INT_2_10_10_10_REV:
5174 if (context->getClientMajorVersion() < 3)
5175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005176 context->handleError(InvalidEnum()
5177 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005178 return false;
5179 }
5180 if (pureInteger)
5181 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005182 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005183 return false;
5184 }
5185 if (size != 4)
5186 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005187 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5188 "UNSIGNED_INT_2_10_10_10_REV and "
5189 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005190 return false;
5191 }
5192 break;
5193
5194 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005195 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005196 return false;
5197 }
5198
5199 return true;
5200}
5201
Geoff Lang76e65652017-03-27 14:58:02 -04005202// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5203// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5204// specified clear value and the type of a buffer that is being cleared generates an
5205// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005206bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005207 GLint drawbuffer,
5208 const GLenum *validComponentTypes,
5209 size_t validComponentTypeCount)
5210{
5211 const FramebufferAttachment *attachment =
5212 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5213 if (attachment)
5214 {
5215 GLenum componentType = attachment->getFormat().info->componentType;
5216 const GLenum *end = validComponentTypes + validComponentTypeCount;
5217 if (std::find(validComponentTypes, end, componentType) == end)
5218 {
5219 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005220 InvalidOperation()
5221 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005222 return false;
5223 }
5224 }
5225
5226 return true;
5227}
5228
Jamie Madill5b772312018-03-08 20:28:32 -05005229bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005230{
5231 if (!ValidateRobustEntryPoint(context, dataSize))
5232 {
5233 return false;
5234 }
5235
Corentin Wallez336129f2017-10-17 15:55:40 -04005236 gl::Buffer *pixelUnpackBuffer =
5237 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005238 if (pixelUnpackBuffer == nullptr)
5239 {
5240 if (dataSize < imageSize)
5241 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005242 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005243 }
5244 }
5245 return true;
5246}
5247
Jamie Madill5b772312018-03-08 20:28:32 -05005248bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005249 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005250 GLenum pname,
5251 bool pointerVersion,
5252 GLsizei *numParams)
5253{
5254 if (numParams)
5255 {
5256 *numParams = 0;
5257 }
5258
Corentin Walleze4477002017-12-01 14:39:58 -05005259 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005260 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005261 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005262 return false;
5263 }
5264
5265 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5266 if (!buffer)
5267 {
5268 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005269 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005270 return false;
5271 }
5272
5273 const Extensions &extensions = context->getExtensions();
5274
5275 switch (pname)
5276 {
5277 case GL_BUFFER_USAGE:
5278 case GL_BUFFER_SIZE:
5279 break;
5280
5281 case GL_BUFFER_ACCESS_OES:
5282 if (!extensions.mapBuffer)
5283 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005284 context->handleError(InvalidEnum()
5285 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005286 return false;
5287 }
5288 break;
5289
5290 case GL_BUFFER_MAPPED:
5291 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5292 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5293 !extensions.mapBufferRange)
5294 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005295 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5296 "GL_OES_mapbuffer or "
5297 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005298 return false;
5299 }
5300 break;
5301
5302 case GL_BUFFER_MAP_POINTER:
5303 if (!pointerVersion)
5304 {
5305 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005306 InvalidEnum()
5307 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005308 return false;
5309 }
5310 break;
5311
5312 case GL_BUFFER_ACCESS_FLAGS:
5313 case GL_BUFFER_MAP_OFFSET:
5314 case GL_BUFFER_MAP_LENGTH:
5315 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5316 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005317 context->handleError(InvalidEnum()
5318 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005319 return false;
5320 }
5321 break;
5322
5323 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005324 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005325 return false;
5326 }
5327
5328 // All buffer parameter queries return one value.
5329 if (numParams)
5330 {
5331 *numParams = 1;
5332 }
5333
5334 return true;
5335}
5336
5337bool ValidateGetRenderbufferParameterivBase(Context *context,
5338 GLenum target,
5339 GLenum pname,
5340 GLsizei *length)
5341{
5342 if (length)
5343 {
5344 *length = 0;
5345 }
5346
5347 if (target != GL_RENDERBUFFER)
5348 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005349 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005350 return false;
5351 }
5352
5353 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5354 if (renderbuffer == nullptr)
5355 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005356 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005357 return false;
5358 }
5359
5360 switch (pname)
5361 {
5362 case GL_RENDERBUFFER_WIDTH:
5363 case GL_RENDERBUFFER_HEIGHT:
5364 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5365 case GL_RENDERBUFFER_RED_SIZE:
5366 case GL_RENDERBUFFER_GREEN_SIZE:
5367 case GL_RENDERBUFFER_BLUE_SIZE:
5368 case GL_RENDERBUFFER_ALPHA_SIZE:
5369 case GL_RENDERBUFFER_DEPTH_SIZE:
5370 case GL_RENDERBUFFER_STENCIL_SIZE:
5371 break;
5372
5373 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5374 if (!context->getExtensions().framebufferMultisample)
5375 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005376 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005377 return false;
5378 }
5379 break;
5380
5381 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005382 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005383 return false;
5384 }
5385
5386 if (length)
5387 {
5388 *length = 1;
5389 }
5390 return true;
5391}
5392
5393bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5394{
5395 if (length)
5396 {
5397 *length = 0;
5398 }
5399
5400 if (GetValidShader(context, shader) == nullptr)
5401 {
5402 return false;
5403 }
5404
5405 switch (pname)
5406 {
5407 case GL_SHADER_TYPE:
5408 case GL_DELETE_STATUS:
5409 case GL_COMPILE_STATUS:
5410 case GL_INFO_LOG_LENGTH:
5411 case GL_SHADER_SOURCE_LENGTH:
5412 break;
5413
5414 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5415 if (!context->getExtensions().translatedShaderSource)
5416 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005417 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005418 return false;
5419 }
5420 break;
5421
5422 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005423 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005424 return false;
5425 }
5426
5427 if (length)
5428 {
5429 *length = 1;
5430 }
5431 return true;
5432}
5433
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005434bool ValidateGetTexParameterBase(Context *context,
5435 TextureType target,
5436 GLenum pname,
5437 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005438{
5439 if (length)
5440 {
5441 *length = 0;
5442 }
5443
5444 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5445 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005446 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005447 return false;
5448 }
5449
5450 if (context->getTargetTexture(target) == nullptr)
5451 {
5452 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005453 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005454 return false;
5455 }
5456
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005457 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5458 {
5459 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5460 return false;
5461 }
5462
Jamie Madillbe849e42017-05-02 15:49:00 -04005463 switch (pname)
5464 {
5465 case GL_TEXTURE_MAG_FILTER:
5466 case GL_TEXTURE_MIN_FILTER:
5467 case GL_TEXTURE_WRAP_S:
5468 case GL_TEXTURE_WRAP_T:
5469 break;
5470
5471 case GL_TEXTURE_USAGE_ANGLE:
5472 if (!context->getExtensions().textureUsage)
5473 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005474 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005475 return false;
5476 }
5477 break;
5478
5479 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005480 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005481 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005482 return false;
5483 }
5484 break;
5485
5486 case GL_TEXTURE_IMMUTABLE_FORMAT:
5487 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5488 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005489 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005490 return false;
5491 }
5492 break;
5493
5494 case GL_TEXTURE_WRAP_R:
5495 case GL_TEXTURE_IMMUTABLE_LEVELS:
5496 case GL_TEXTURE_SWIZZLE_R:
5497 case GL_TEXTURE_SWIZZLE_G:
5498 case GL_TEXTURE_SWIZZLE_B:
5499 case GL_TEXTURE_SWIZZLE_A:
5500 case GL_TEXTURE_BASE_LEVEL:
5501 case GL_TEXTURE_MAX_LEVEL:
5502 case GL_TEXTURE_MIN_LOD:
5503 case GL_TEXTURE_MAX_LOD:
5504 case GL_TEXTURE_COMPARE_MODE:
5505 case GL_TEXTURE_COMPARE_FUNC:
5506 if (context->getClientMajorVersion() < 3)
5507 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005508 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005509 return false;
5510 }
5511 break;
5512
5513 case GL_TEXTURE_SRGB_DECODE_EXT:
5514 if (!context->getExtensions().textureSRGBDecode)
5515 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005516 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005517 return false;
5518 }
5519 break;
5520
Yunchao Hebacaa712018-01-30 14:01:39 +08005521 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5522 if (context->getClientVersion() < Version(3, 1))
5523 {
5524 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5525 return false;
5526 }
5527 break;
5528
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005529 case GL_GENERATE_MIPMAP:
5530 case GL_TEXTURE_CROP_RECT_OES:
5531 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5532 // after GL_OES_draw_texture functionality implemented
5533 if (context->getClientMajorVersion() > 1)
5534 {
5535 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5536 return false;
5537 }
5538 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005539 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005540 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005541 return false;
5542 }
5543
5544 if (length)
5545 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005546 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005547 }
5548 return true;
5549}
5550
5551bool ValidateGetVertexAttribBase(Context *context,
5552 GLuint index,
5553 GLenum pname,
5554 GLsizei *length,
5555 bool pointer,
5556 bool pureIntegerEntryPoint)
5557{
5558 if (length)
5559 {
5560 *length = 0;
5561 }
5562
5563 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5564 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005565 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005566 return false;
5567 }
5568
5569 if (index >= context->getCaps().maxVertexAttributes)
5570 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005571 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005572 return false;
5573 }
5574
5575 if (pointer)
5576 {
5577 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5578 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005579 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005580 return false;
5581 }
5582 }
5583 else
5584 {
5585 switch (pname)
5586 {
5587 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5588 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5589 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5590 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5591 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5592 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5593 case GL_CURRENT_VERTEX_ATTRIB:
5594 break;
5595
5596 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5597 static_assert(
5598 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5599 "ANGLE extension enums not equal to GL enums.");
5600 if (context->getClientMajorVersion() < 3 &&
5601 !context->getExtensions().instancedArrays)
5602 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005603 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5604 "requires OpenGL ES 3.0 or "
5605 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005606 return false;
5607 }
5608 break;
5609
5610 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5611 if (context->getClientMajorVersion() < 3)
5612 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005613 context->handleError(
5614 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005615 return false;
5616 }
5617 break;
5618
5619 case GL_VERTEX_ATTRIB_BINDING:
5620 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5621 if (context->getClientVersion() < ES_3_1)
5622 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005623 context->handleError(InvalidEnum()
5624 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005625 return false;
5626 }
5627 break;
5628
5629 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005630 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005631 return false;
5632 }
5633 }
5634
5635 if (length)
5636 {
5637 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5638 {
5639 *length = 4;
5640 }
5641 else
5642 {
5643 *length = 1;
5644 }
5645 }
5646
5647 return true;
5648}
5649
Jamie Madill4928b7c2017-06-20 12:57:39 -04005650bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005651 GLint x,
5652 GLint y,
5653 GLsizei width,
5654 GLsizei height,
5655 GLenum format,
5656 GLenum type,
5657 GLsizei bufSize,
5658 GLsizei *length,
5659 GLsizei *columns,
5660 GLsizei *rows,
5661 void *pixels)
5662{
5663 if (length != nullptr)
5664 {
5665 *length = 0;
5666 }
5667 if (rows != nullptr)
5668 {
5669 *rows = 0;
5670 }
5671 if (columns != nullptr)
5672 {
5673 *columns = 0;
5674 }
5675
5676 if (width < 0 || height < 0)
5677 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005678 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005679 return false;
5680 }
5681
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005682 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005683
Jamie Madill427064d2018-04-13 16:20:34 -04005684 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005685 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005686 return false;
5687 }
5688
Jamie Madille98b1b52018-03-08 09:47:23 -05005689 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005690 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005691 return false;
5692 }
5693
Jamie Madill690c8eb2018-03-12 15:20:03 -04005694 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005695 ASSERT(framebuffer);
5696
5697 if (framebuffer->getReadBufferState() == GL_NONE)
5698 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005699 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005700 return false;
5701 }
5702
5703 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5704 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5705 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5706 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5707 // situation is an application error that would lead to a crash in ANGLE.
5708 if (readBuffer == nullptr)
5709 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005710 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005711 return false;
5712 }
5713
Martin Radev28031682017-07-28 14:47:56 +03005714 // ANGLE_multiview, Revision 1:
5715 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5716 // current read framebuffer is not NONE.
5717 if (readBuffer->getMultiviewLayout() != GL_NONE)
5718 {
5719 context->handleError(InvalidFramebufferOperation()
5720 << "Attempting to read from a multi-view framebuffer.");
5721 return false;
5722 }
5723
Geoff Lang280ba992017-04-18 16:30:58 -04005724 if (context->getExtensions().webglCompatibility)
5725 {
5726 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5727 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5728 // and type before validating the combination of format and type. However, the
5729 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5730 // verifies that GL_INVALID_OPERATION is generated.
5731 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5732 // dEQP/WebGL.
5733 if (!ValidReadPixelsFormatEnum(context, format))
5734 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005735 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005736 return false;
5737 }
5738
5739 if (!ValidReadPixelsTypeEnum(context, type))
5740 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005741 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005742 return false;
5743 }
5744 }
5745
Jamie Madill690c8eb2018-03-12 15:20:03 -04005746 GLenum currentFormat = GL_NONE;
5747 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5748
5749 GLenum currentType = GL_NONE;
5750 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5751
Jamie Madillbe849e42017-05-02 15:49:00 -04005752 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5753
5754 bool validFormatTypeCombination =
5755 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5756
5757 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5758 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005759 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005760 return false;
5761 }
5762
5763 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005764 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005765 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5766 {
5767 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005768 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005769 return false;
5770 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005771 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5772 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5773 {
5774 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5775 return false;
5776 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005777
5778 // .. the data would be packed to the buffer object such that the memory writes required
5779 // would exceed the data store size.
5780 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5781 const gl::Extents size(width, height, 1);
5782 const auto &pack = context->getGLState().getPackState();
5783
5784 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5785 if (endByteOrErr.isError())
5786 {
5787 context->handleError(endByteOrErr.getError());
5788 return false;
5789 }
5790
5791 size_t endByte = endByteOrErr.getResult();
5792 if (bufSize >= 0)
5793 {
5794 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5795 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005796 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005797 return false;
5798 }
5799 }
5800
5801 if (pixelPackBuffer != nullptr)
5802 {
5803 CheckedNumeric<size_t> checkedEndByte(endByte);
5804 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5805 checkedEndByte += checkedOffset;
5806
5807 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5808 {
5809 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005810 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005811 return false;
5812 }
5813 }
5814
5815 if (pixelPackBuffer == nullptr && length != nullptr)
5816 {
5817 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5818 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005819 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005820 return false;
5821 }
5822
5823 *length = static_cast<GLsizei>(endByte);
5824 }
5825
Geoff Langa953b522018-02-21 16:56:23 -05005826 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005827 angle::CheckedNumeric<int> clippedExtent(length);
5828 if (start < 0)
5829 {
5830 // "subtract" the area that is less than 0
5831 clippedExtent += start;
5832 }
5833
Geoff Langa953b522018-02-21 16:56:23 -05005834 angle::CheckedNumeric<int> readExtent = start;
5835 readExtent += length;
5836 if (!readExtent.IsValid())
5837 {
5838 return false;
5839 }
5840
5841 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005842 {
5843 // Subtract the region to the right of the read buffer
5844 clippedExtent -= (readExtent - bufferSize);
5845 }
5846
5847 if (!clippedExtent.IsValid())
5848 {
Geoff Langa953b522018-02-21 16:56:23 -05005849 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005850 }
5851
Geoff Langa953b522018-02-21 16:56:23 -05005852 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5853 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005854 };
5855
Geoff Langa953b522018-02-21 16:56:23 -05005856 GLsizei writtenColumns = 0;
5857 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5858 {
5859 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5860 return false;
5861 }
5862
5863 GLsizei writtenRows = 0;
5864 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5865 {
5866 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5867 return false;
5868 }
5869
Jamie Madillbe849e42017-05-02 15:49:00 -04005870 if (columns != nullptr)
5871 {
Geoff Langa953b522018-02-21 16:56:23 -05005872 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005873 }
5874
5875 if (rows != nullptr)
5876 {
Geoff Langa953b522018-02-21 16:56:23 -05005877 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005878 }
5879
5880 return true;
5881}
5882
5883template <typename ParamType>
5884bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005885 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005886 GLenum pname,
5887 GLsizei bufSize,
5888 const ParamType *params)
5889{
5890 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5891 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005892 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005893 return false;
5894 }
5895
5896 if (context->getTargetTexture(target) == nullptr)
5897 {
5898 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005899 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005900 return false;
5901 }
5902
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005903 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005904 if (bufSize >= 0 && bufSize < minBufSize)
5905 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005906 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005907 return false;
5908 }
5909
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005910 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5911 {
5912 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5913 return false;
5914 }
5915
Jamie Madillbe849e42017-05-02 15:49:00 -04005916 switch (pname)
5917 {
5918 case GL_TEXTURE_WRAP_R:
5919 case GL_TEXTURE_SWIZZLE_R:
5920 case GL_TEXTURE_SWIZZLE_G:
5921 case GL_TEXTURE_SWIZZLE_B:
5922 case GL_TEXTURE_SWIZZLE_A:
5923 case GL_TEXTURE_BASE_LEVEL:
5924 case GL_TEXTURE_MAX_LEVEL:
5925 case GL_TEXTURE_COMPARE_MODE:
5926 case GL_TEXTURE_COMPARE_FUNC:
5927 case GL_TEXTURE_MIN_LOD:
5928 case GL_TEXTURE_MAX_LOD:
5929 if (context->getClientMajorVersion() < 3)
5930 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005931 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005932 return false;
5933 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005934 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005935 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005936 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5937 "available without "
5938 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005939 return false;
5940 }
5941 break;
5942
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005943 case GL_GENERATE_MIPMAP:
5944 case GL_TEXTURE_CROP_RECT_OES:
5945 if (context->getClientMajorVersion() > 1)
5946 {
5947 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5948 return false;
5949 }
5950 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005951 default:
5952 break;
5953 }
5954
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005955 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005956 {
5957 switch (pname)
5958 {
5959 case GL_TEXTURE_MIN_FILTER:
5960 case GL_TEXTURE_MAG_FILTER:
5961 case GL_TEXTURE_WRAP_S:
5962 case GL_TEXTURE_WRAP_T:
5963 case GL_TEXTURE_WRAP_R:
5964 case GL_TEXTURE_MIN_LOD:
5965 case GL_TEXTURE_MAX_LOD:
5966 case GL_TEXTURE_COMPARE_MODE:
5967 case GL_TEXTURE_COMPARE_FUNC:
5968 context->handleError(InvalidEnum()
5969 << "Invalid parameter for 2D multisampled textures.");
5970 return false;
5971 }
5972 }
5973
Jamie Madillbe849e42017-05-02 15:49:00 -04005974 switch (pname)
5975 {
5976 case GL_TEXTURE_WRAP_S:
5977 case GL_TEXTURE_WRAP_T:
5978 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005979 {
5980 bool restrictedWrapModes =
5981 target == TextureType::External || target == TextureType::Rectangle;
5982 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005983 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005984 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005985 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005986 }
5987 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005988
5989 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005990 {
5991 bool restrictedMinFilter =
5992 target == TextureType::External || target == TextureType::Rectangle;
5993 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005994 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005995 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005996 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005997 }
5998 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005999
6000 case GL_TEXTURE_MAG_FILTER:
6001 if (!ValidateTextureMagFilterValue(context, params))
6002 {
6003 return false;
6004 }
6005 break;
6006
6007 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04006008 if (!context->getExtensions().textureUsage)
6009 {
6010 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6011 return false;
6012 }
6013
Jamie Madillbe849e42017-05-02 15:49:00 -04006014 switch (ConvertToGLenum(params[0]))
6015 {
6016 case GL_NONE:
6017 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
6018 break;
6019
6020 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006021 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006022 return false;
6023 }
6024 break;
6025
6026 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07006027 {
6028 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6029 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04006030 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07006031 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04006032 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07006033 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
6034 }
6035 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006036
6037 case GL_TEXTURE_MIN_LOD:
6038 case GL_TEXTURE_MAX_LOD:
6039 // any value is permissible
6040 break;
6041
6042 case GL_TEXTURE_COMPARE_MODE:
6043 if (!ValidateTextureCompareModeValue(context, params))
6044 {
6045 return false;
6046 }
6047 break;
6048
6049 case GL_TEXTURE_COMPARE_FUNC:
6050 if (!ValidateTextureCompareFuncValue(context, params))
6051 {
6052 return false;
6053 }
6054 break;
6055
6056 case GL_TEXTURE_SWIZZLE_R:
6057 case GL_TEXTURE_SWIZZLE_G:
6058 case GL_TEXTURE_SWIZZLE_B:
6059 case GL_TEXTURE_SWIZZLE_A:
6060 switch (ConvertToGLenum(params[0]))
6061 {
6062 case GL_RED:
6063 case GL_GREEN:
6064 case GL_BLUE:
6065 case GL_ALPHA:
6066 case GL_ZERO:
6067 case GL_ONE:
6068 break;
6069
6070 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006071 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006072 return false;
6073 }
6074 break;
6075
6076 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006077 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006078 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006079 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006080 return false;
6081 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006082 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006083 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006084 context->handleError(InvalidOperation()
6085 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006086 return false;
6087 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006088 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08006089 {
6090 context->handleError(InvalidOperation()
6091 << "Base level must be 0 for multisampled textures.");
6092 return false;
6093 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006094 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006095 {
6096 context->handleError(InvalidOperation()
6097 << "Base level must be 0 for rectangle textures.");
6098 return false;
6099 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006100 break;
6101
6102 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006103 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006104 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006105 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006106 return false;
6107 }
6108 break;
6109
6110 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6111 if (context->getClientVersion() < Version(3, 1))
6112 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006113 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006114 return false;
6115 }
6116 switch (ConvertToGLenum(params[0]))
6117 {
6118 case GL_DEPTH_COMPONENT:
6119 case GL_STENCIL_INDEX:
6120 break;
6121
6122 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006123 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006124 return false;
6125 }
6126 break;
6127
6128 case GL_TEXTURE_SRGB_DECODE_EXT:
6129 if (!ValidateTextureSRGBDecodeValue(context, params))
6130 {
6131 return false;
6132 }
6133 break;
6134
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006135 case GL_GENERATE_MIPMAP:
6136 case GL_TEXTURE_CROP_RECT_OES:
6137 if (context->getClientMajorVersion() > 1)
6138 {
6139 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
6140 return false;
6141 }
6142 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006143 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006144 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006145 return false;
6146 }
6147
6148 return true;
6149}
6150
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006151template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6152template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006153
Jamie Madill5b772312018-03-08 20:28:32 -05006154bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006155{
6156 if (index >= MAX_VERTEX_ATTRIBS)
6157 {
6158 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6159 return false;
6160 }
6161
6162 return true;
6163}
6164
6165bool ValidateGetActiveUniformBlockivBase(Context *context,
6166 GLuint program,
6167 GLuint uniformBlockIndex,
6168 GLenum pname,
6169 GLsizei *length)
6170{
6171 if (length)
6172 {
6173 *length = 0;
6174 }
6175
6176 if (context->getClientMajorVersion() < 3)
6177 {
6178 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6179 return false;
6180 }
6181
6182 Program *programObject = GetValidProgram(context, program);
6183 if (!programObject)
6184 {
6185 return false;
6186 }
6187
6188 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6189 {
6190 context->handleError(InvalidValue()
6191 << "uniformBlockIndex exceeds active uniform block count.");
6192 return false;
6193 }
6194
6195 switch (pname)
6196 {
6197 case GL_UNIFORM_BLOCK_BINDING:
6198 case GL_UNIFORM_BLOCK_DATA_SIZE:
6199 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6200 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6201 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6202 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6203 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6204 break;
6205
6206 default:
6207 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6208 return false;
6209 }
6210
6211 if (length)
6212 {
6213 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6214 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006215 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006216 programObject->getUniformBlockByIndex(uniformBlockIndex);
6217 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6218 }
6219 else
6220 {
6221 *length = 1;
6222 }
6223 }
6224
6225 return true;
6226}
6227
Jamie Madill9696d072017-08-26 23:19:57 -04006228template <typename ParamType>
6229bool ValidateSamplerParameterBase(Context *context,
6230 GLuint sampler,
6231 GLenum pname,
6232 GLsizei bufSize,
6233 ParamType *params)
6234{
6235 if (context->getClientMajorVersion() < 3)
6236 {
6237 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6238 return false;
6239 }
6240
6241 if (!context->isSampler(sampler))
6242 {
6243 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6244 return false;
6245 }
6246
6247 const GLsizei minBufSize = 1;
6248 if (bufSize >= 0 && bufSize < minBufSize)
6249 {
6250 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6251 return false;
6252 }
6253
6254 switch (pname)
6255 {
6256 case GL_TEXTURE_WRAP_S:
6257 case GL_TEXTURE_WRAP_T:
6258 case GL_TEXTURE_WRAP_R:
6259 if (!ValidateTextureWrapModeValue(context, params, false))
6260 {
6261 return false;
6262 }
6263 break;
6264
6265 case GL_TEXTURE_MIN_FILTER:
6266 if (!ValidateTextureMinFilterValue(context, params, false))
6267 {
6268 return false;
6269 }
6270 break;
6271
6272 case GL_TEXTURE_MAG_FILTER:
6273 if (!ValidateTextureMagFilterValue(context, params))
6274 {
6275 return false;
6276 }
6277 break;
6278
6279 case GL_TEXTURE_MIN_LOD:
6280 case GL_TEXTURE_MAX_LOD:
6281 // any value is permissible
6282 break;
6283
6284 case GL_TEXTURE_COMPARE_MODE:
6285 if (!ValidateTextureCompareModeValue(context, params))
6286 {
6287 return false;
6288 }
6289 break;
6290
6291 case GL_TEXTURE_COMPARE_FUNC:
6292 if (!ValidateTextureCompareFuncValue(context, params))
6293 {
6294 return false;
6295 }
6296 break;
6297
6298 case GL_TEXTURE_SRGB_DECODE_EXT:
6299 if (!ValidateTextureSRGBDecodeValue(context, params))
6300 {
6301 return false;
6302 }
6303 break;
6304
Luc Ferron1b1a8642018-01-23 15:12:01 -05006305 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6306 {
6307 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6308 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6309 {
6310 return false;
6311 }
6312 }
6313 break;
6314
Jamie Madill9696d072017-08-26 23:19:57 -04006315 default:
6316 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6317 return false;
6318 }
6319
6320 return true;
6321}
6322
6323template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6324template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6325
6326bool ValidateGetSamplerParameterBase(Context *context,
6327 GLuint sampler,
6328 GLenum pname,
6329 GLsizei *length)
6330{
6331 if (length)
6332 {
6333 *length = 0;
6334 }
6335
6336 if (context->getClientMajorVersion() < 3)
6337 {
6338 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6339 return false;
6340 }
6341
6342 if (!context->isSampler(sampler))
6343 {
6344 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6345 return false;
6346 }
6347
6348 switch (pname)
6349 {
6350 case GL_TEXTURE_WRAP_S:
6351 case GL_TEXTURE_WRAP_T:
6352 case GL_TEXTURE_WRAP_R:
6353 case GL_TEXTURE_MIN_FILTER:
6354 case GL_TEXTURE_MAG_FILTER:
6355 case GL_TEXTURE_MIN_LOD:
6356 case GL_TEXTURE_MAX_LOD:
6357 case GL_TEXTURE_COMPARE_MODE:
6358 case GL_TEXTURE_COMPARE_FUNC:
6359 break;
6360
Luc Ferron1b1a8642018-01-23 15:12:01 -05006361 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6362 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6363 {
6364 return false;
6365 }
6366 break;
6367
Jamie Madill9696d072017-08-26 23:19:57 -04006368 case GL_TEXTURE_SRGB_DECODE_EXT:
6369 if (!context->getExtensions().textureSRGBDecode)
6370 {
6371 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6372 return false;
6373 }
6374 break;
6375
6376 default:
6377 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6378 return false;
6379 }
6380
6381 if (length)
6382 {
6383 *length = 1;
6384 }
6385 return true;
6386}
6387
6388bool ValidateGetInternalFormativBase(Context *context,
6389 GLenum target,
6390 GLenum internalformat,
6391 GLenum pname,
6392 GLsizei bufSize,
6393 GLsizei *numParams)
6394{
6395 if (numParams)
6396 {
6397 *numParams = 0;
6398 }
6399
6400 if (context->getClientMajorVersion() < 3)
6401 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006402 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006403 return false;
6404 }
6405
6406 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006407 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006408 {
6409 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6410 return false;
6411 }
6412
6413 switch (target)
6414 {
6415 case GL_RENDERBUFFER:
6416 break;
6417
6418 case GL_TEXTURE_2D_MULTISAMPLE:
6419 if (context->getClientVersion() < ES_3_1)
6420 {
6421 context->handleError(InvalidOperation()
6422 << "Texture target requires at least OpenGL ES 3.1.");
6423 return false;
6424 }
6425 break;
6426
6427 default:
6428 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6429 return false;
6430 }
6431
6432 if (bufSize < 0)
6433 {
6434 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6435 return false;
6436 }
6437
6438 GLsizei maxWriteParams = 0;
6439 switch (pname)
6440 {
6441 case GL_NUM_SAMPLE_COUNTS:
6442 maxWriteParams = 1;
6443 break;
6444
6445 case GL_SAMPLES:
6446 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6447 break;
6448
6449 default:
6450 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6451 return false;
6452 }
6453
6454 if (numParams)
6455 {
6456 // glGetInternalFormativ will not overflow bufSize
6457 *numParams = std::min(bufSize, maxWriteParams);
6458 }
6459
6460 return true;
6461}
6462
Jamie Madille98b1b52018-03-08 09:47:23 -05006463bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6464{
Jamie Madill427064d2018-04-13 16:20:34 -04006465 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006466 {
6467 context->handleError(InvalidOperation());
6468 return false;
6469 }
6470 return true;
6471}
6472
Lingfeng Yang038dd532018-03-29 17:31:52 -07006473bool ValidateMultitextureUnit(Context *context, GLenum texture)
6474{
6475 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6476 {
6477 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6478 return false;
6479 }
6480 return true;
6481}
6482
Jamie Madillc29968b2016-01-20 11:17:23 -05006483} // namespace gl