blob: da6f98971a21a3a501c7d23bfeefe53de1f0a74f [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
Jamie Madill2eb65032018-07-30 10:25:57 -0400121 const AttributesMask &activeAttribs = context->getActiveBufferedAttribsMask();
Jamie Madill51af38b2018-04-15 08:50:56 -0400122
123 for (size_t attributeIndex : activeAttribs)
Jamie Madill1ca74672015-07-21 15:14:11 -0400124 {
125 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Jamie Madill51af38b2018-04-15 08:50:56 -0400126 ASSERT(attrib.enabled);
Corentin Wallez672f7f32017-06-15 17:42:17 -0400127
Lingfeng Yang038dd532018-03-29 17:31:52 -0700128 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
Jamie Madill2eb65032018-07-30 10:25:57 -0400129 ASSERT(context->isGLES1() || program->isAttribLocationActive(attributeIndex));
Corentin Wallezfd456442016-12-21 17:57:00 -0500130
Jamie Madill02c9c042018-04-17 13:43:48 -0400131 GLint maxVertexElement = maxVertex;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300132 GLuint divisor = binding.getDivisor();
Jamie Madill02c9c042018-04-17 13:43:48 -0400133 if (divisor != 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500134 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300135 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500136 }
137
138 // We do manual overflow checks here instead of using safe_math.h because it was
139 // a bottleneck. Thanks to some properties of GL we know inequalities that can
140 // help us make the overflow checks faster.
141
142 // The max possible attribSize is 16 for a vector of 4 32 bit values.
143 constexpr uint64_t kMaxAttribSize = 16;
144 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
145 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
146
147 // We know attribStride is given as a GLsizei which is typedefed to int.
148 // We also know an upper bound for attribSize.
Jamie Madill02c9c042018-04-17 13:43:48 -0400149 static_assert(std::is_same<int, GLsizei>::value, "Unexpected type");
150 ASSERT(ComputeVertexAttributeStride(attrib, binding) == binding.getStride());
151 uint64_t attribStride = binding.getStride();
152 ASSERT(attribStride <= kIntMax && ComputeVertexAttributeTypeSize(attrib) <= kMaxAttribSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500153
Jamie Madill02c9c042018-04-17 13:43:48 -0400154 // Computing the product of two 32-bit ints will fit in 64 bits without overflow.
155 static_assert(kIntMax * kIntMax < kUint64Max, "Unexpected overflow");
156 uint64_t attribDataSizeMinusAttribSize = maxVertexElement * attribStride;
Corentin Wallezfd456442016-12-21 17:57:00 -0500157
158 // An overflow can happen when adding the offset, check for it.
Jamie Madill02c9c042018-04-17 13:43:48 -0400159 if (attribDataSizeMinusAttribSize > kUint64Max - attrib.cachedSizePlusRelativeOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500160 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700161 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500162 return false;
163 }
Corentin Wallezfd456442016-12-21 17:57:00 -0500164
165 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
Jamie Madill02c9c042018-04-17 13:43:48 -0400166 // We can return INVALID_OPERATION if our array buffer does not have enough backing data.
167 if (attribDataSizeMinusAttribSize + attrib.cachedSizePlusRelativeOffset >
168 binding.getCachedBufferSizeMinusOffset())
Corentin Wallezfd456442016-12-21 17:57:00 -0500169 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700170 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500171 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400172 }
Jamie Madill02c9c042018-04-17 13:43:48 -0400173 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800174
Jamie Madill7267aa62018-04-17 15:28:21 -0400175 if (webglCompatibility && vao->hasTransformFeedbackBindingConflict(activeAttribs))
Jamie Madill02c9c042018-04-17 13:43:48 -0400176 {
Jamie Madill7267aa62018-04-17 15:28:21 -0400177 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexBufferBoundForTransformFeedback);
178 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400179 }
180
181 return true;
182}
183
Jamie Madill5b772312018-03-08 20:28:32 -0500184bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400185{
186 switch (type)
187 {
188 // Types referenced in Table 3.4 of the ES 2.0.25 spec
189 case GL_UNSIGNED_BYTE:
190 case GL_UNSIGNED_SHORT_4_4_4_4:
191 case GL_UNSIGNED_SHORT_5_5_5_1:
192 case GL_UNSIGNED_SHORT_5_6_5:
193 return context->getClientVersion() >= ES_2_0;
194
195 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
196 case GL_BYTE:
197 case GL_INT:
198 case GL_SHORT:
199 case GL_UNSIGNED_INT:
200 case GL_UNSIGNED_INT_10F_11F_11F_REV:
201 case GL_UNSIGNED_INT_24_8:
202 case GL_UNSIGNED_INT_2_10_10_10_REV:
203 case GL_UNSIGNED_INT_5_9_9_9_REV:
204 case GL_UNSIGNED_SHORT:
205 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
206 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
207 return context->getClientVersion() >= ES_3_0;
208
209 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400210 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
211 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400212
213 case GL_HALF_FLOAT:
214 return context->getClientVersion() >= ES_3_0 ||
215 context->getExtensions().textureHalfFloat;
216
217 case GL_HALF_FLOAT_OES:
218 return context->getExtensions().colorBufferHalfFloat;
219
220 default:
221 return false;
222 }
223}
224
Jamie Madill5b772312018-03-08 20:28:32 -0500225bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400226{
227 switch (format)
228 {
229 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
230 case GL_RGBA:
231 case GL_RGB:
232 case GL_ALPHA:
233 return context->getClientVersion() >= ES_2_0;
234
235 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
236 case GL_RG:
237 case GL_RED:
238 case GL_RGBA_INTEGER:
239 case GL_RGB_INTEGER:
240 case GL_RG_INTEGER:
241 case GL_RED_INTEGER:
242 return context->getClientVersion() >= ES_3_0;
243
244 case GL_SRGB_ALPHA_EXT:
245 case GL_SRGB_EXT:
246 return context->getExtensions().sRGB;
247
248 case GL_BGRA_EXT:
249 return context->getExtensions().readFormatBGRA;
250
251 default:
252 return false;
253 }
254}
255
Jamie Madill5b772312018-03-08 20:28:32 -0500256bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400257 GLenum framebufferComponentType,
258 GLenum format,
259 GLenum type)
260{
261 switch (framebufferComponentType)
262 {
263 case GL_UNSIGNED_NORMALIZED:
264 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
265 // ReadPixels with BGRA even if the extension is not present
266 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
267 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
268 type == GL_UNSIGNED_BYTE);
269
270 case GL_SIGNED_NORMALIZED:
271 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
272
273 case GL_INT:
274 return (format == GL_RGBA_INTEGER && type == GL_INT);
275
276 case GL_UNSIGNED_INT:
277 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
278
279 case GL_FLOAT:
280 return (format == GL_RGBA && type == GL_FLOAT);
281
282 default:
283 UNREACHABLE();
284 return false;
285 }
286}
287
Geoff Langc1984ed2016-10-07 12:41:00 -0400288template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400289bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400290{
291 switch (ConvertToGLenum(params[0]))
292 {
293 case GL_CLAMP_TO_EDGE:
294 break;
295
296 case GL_REPEAT:
297 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400298 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400299 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400300 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700301 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400302 return false;
303 }
304 break;
305
306 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700307 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400308 return false;
309 }
310
311 return true;
312}
313
314template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400315bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400316{
317 switch (ConvertToGLenum(params[0]))
318 {
319 case GL_NEAREST:
320 case GL_LINEAR:
321 break;
322
323 case GL_NEAREST_MIPMAP_NEAREST:
324 case GL_LINEAR_MIPMAP_NEAREST:
325 case GL_NEAREST_MIPMAP_LINEAR:
326 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400327 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400328 {
329 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700330 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400331 return false;
332 }
333 break;
334
335 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700336 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400337 return false;
338 }
339
340 return true;
341}
342
343template <typename ParamType>
344bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
345{
346 switch (ConvertToGLenum(params[0]))
347 {
348 case GL_NEAREST:
349 case GL_LINEAR:
350 break;
351
352 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700353 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400354 return false;
355 }
356
357 return true;
358}
359
360template <typename ParamType>
361bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
362{
363 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
364 switch (ConvertToGLenum(params[0]))
365 {
366 case GL_NONE:
367 case GL_COMPARE_REF_TO_TEXTURE:
368 break;
369
370 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700371 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400372 return false;
373 }
374
375 return true;
376}
377
378template <typename ParamType>
379bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
380{
381 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
382 switch (ConvertToGLenum(params[0]))
383 {
384 case GL_LEQUAL:
385 case GL_GEQUAL:
386 case GL_LESS:
387 case GL_GREATER:
388 case GL_EQUAL:
389 case GL_NOTEQUAL:
390 case GL_ALWAYS:
391 case GL_NEVER:
392 break;
393
394 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700395 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400396 return false;
397 }
398
399 return true;
400}
401
402template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700403bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
404{
405 if (!context->getExtensions().textureSRGBDecode)
406 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700407 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700408 return false;
409 }
410
411 switch (ConvertToGLenum(params[0]))
412 {
413 case GL_DECODE_EXT:
414 case GL_SKIP_DECODE_EXT:
415 break;
416
417 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700418 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700419 return false;
420 }
421
422 return true;
423}
424
Luc Ferron1b1a8642018-01-23 15:12:01 -0500425bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
426{
427 if (!context->getExtensions().textureFilterAnisotropic)
428 {
429 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
430 return false;
431 }
432
433 return true;
434}
435
436bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
437{
438 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
439 {
440 return false;
441 }
442
443 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
444
445 if (paramValue < 1 || paramValue > largest)
446 {
447 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
448 return false;
449 }
450
451 return true;
452}
453
Jamie Madill5b772312018-03-08 20:28:32 -0500454bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400455{
456 const Program *program = context->getGLState().getProgram();
457 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
458
Brandon Jonesc405ae72017-12-06 14:15:03 -0800459 if (!ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
460 framebuffer->getDrawBufferTypeMask().to_ulong(),
461 program->getActiveOutputVariables().to_ulong(),
462 framebuffer->getDrawBufferMask().to_ulong()))
Geoff Lange0cff192017-05-30 13:04:56 -0400463 {
Brandon Jones76746f92017-11-22 11:44:41 -0800464 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
465 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400466 }
467
468 return true;
469}
470
Jamie Madill5b772312018-03-08 20:28:32 -0500471bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400472{
Lingfeng Yang038dd532018-03-29 17:31:52 -0700473 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400474 const Program *program = context->getGLState().getProgram();
475 const VertexArray *vao = context->getGLState().getVertexArray();
476
Brandon Jonesc405ae72017-12-06 14:15:03 -0800477 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
478 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
479 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
480
481 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
482 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
483 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
484
485 if (!ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
486 program->getAttributesMask().to_ulong(), 0xFFFF))
Geoff Lang9ab5b822017-05-30 16:19:23 -0400487 {
Brandon Jonesc405ae72017-12-06 14:15:03 -0800488 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexShaderTypeMismatch);
489 return false;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400490 }
Geoff Lang9ab5b822017-05-30 16:19:23 -0400491 return true;
492}
493
Jamie Madill493f9572018-05-24 19:52:15 -0400494bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
495 PrimitiveMode geometryShaderInputPrimitiveType)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800496{
497 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
Jamie Madill493f9572018-05-24 19:52:15 -0400498 switch (drawMode)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800499 {
Jamie Madill493f9572018-05-24 19:52:15 -0400500 case PrimitiveMode::Points:
501 return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
502 case PrimitiveMode::Lines:
503 case PrimitiveMode::LineStrip:
504 case PrimitiveMode::LineLoop:
505 return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
506 case PrimitiveMode::LinesAdjacency:
507 case PrimitiveMode::LineStripAdjacency:
508 return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
509 case PrimitiveMode::Triangles:
510 case PrimitiveMode::TriangleFan:
511 case PrimitiveMode::TriangleStrip:
512 return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
513 case PrimitiveMode::TrianglesAdjacency:
514 case PrimitiveMode::TriangleStripAdjacency:
515 return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
Jiawei Shaofccebff2018-03-08 13:51:02 +0800516 default:
517 UNREACHABLE();
518 return false;
519 }
520}
521
Lingfeng Yangf97641c2018-06-21 19:22:45 -0700522// GLES1 texture parameters are a small subset of the others
523bool IsValidGLES1TextureParameter(GLenum pname)
524{
525 switch (pname)
526 {
527 case GL_TEXTURE_MAG_FILTER:
528 case GL_TEXTURE_MIN_FILTER:
529 case GL_TEXTURE_WRAP_S:
530 case GL_TEXTURE_WRAP_T:
531 case GL_TEXTURE_WRAP_R:
532 case GL_GENERATE_MIPMAP:
533 case GL_TEXTURE_CROP_RECT_OES:
534 return true;
535 default:
536 return false;
537 }
538}
539
Geoff Langf41a7152016-09-19 15:11:17 -0400540} // anonymous namespace
541
Brandon Jonesd1049182018-03-28 10:02:20 -0700542void SetRobustLengthParam(GLsizei *length, GLsizei value)
543{
544 if (length)
545 {
546 *length = value;
547 }
548}
549
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500550bool IsETC2EACFormat(const GLenum format)
551{
552 // ES 3.1, Table 8.19
553 switch (format)
554 {
555 case GL_COMPRESSED_R11_EAC:
556 case GL_COMPRESSED_SIGNED_R11_EAC:
557 case GL_COMPRESSED_RG11_EAC:
558 case GL_COMPRESSED_SIGNED_RG11_EAC:
559 case GL_COMPRESSED_RGB8_ETC2:
560 case GL_COMPRESSED_SRGB8_ETC2:
561 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
562 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
563 case GL_COMPRESSED_RGBA8_ETC2_EAC:
564 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
565 return true;
566
567 default:
568 return false;
569 }
570}
571
Jamie Madill5b772312018-03-08 20:28:32 -0500572bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400573{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800574 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400575 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800576 case TextureType::_2D:
577 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800578 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400579
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800580 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400581 return context->getExtensions().textureRectangle;
582
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800583 case TextureType::_3D:
584 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800585 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500586
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800587 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800588 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400589
He Yunchaoced53ae2016-11-29 15:00:51 +0800590 default:
591 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500592 }
Jamie Madill35d15012013-10-07 10:46:37 -0400593}
594
Jamie Madill5b772312018-03-08 20:28:32 -0500595bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500596{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800597 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500598 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800599 case TextureType::_2D:
600 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500601 return true;
602
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800603 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400604 return context->getExtensions().textureRectangle;
605
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500606 default:
607 return false;
608 }
609}
610
Jamie Madill5b772312018-03-08 20:28:32 -0500611bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500612{
613 switch (target)
614 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800615 case TextureType::_3D:
616 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300617 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500618
619 default:
620 return false;
621 }
622}
623
Ian Ewellbda75592016-04-18 17:25:54 -0400624// Most texture GL calls are not compatible with external textures, so we have a separate validation
625// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500626bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400627{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800628 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400629 (context->getExtensions().eglImageExternal ||
630 context->getExtensions().eglStreamConsumerExternal);
631}
632
Shannon Woods4dfed832014-03-17 20:03:39 -0400633// This function differs from ValidTextureTarget in that the target must be
634// usable as the destination of a 2D operation-- so a cube face is valid, but
635// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400636// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500637bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400638{
639 switch (target)
640 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800641 case TextureTarget::_2D:
642 case TextureTarget::CubeMapNegativeX:
643 case TextureTarget::CubeMapNegativeY:
644 case TextureTarget::CubeMapNegativeZ:
645 case TextureTarget::CubeMapPositiveX:
646 case TextureTarget::CubeMapPositiveY:
647 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800648 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800649 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400650 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800651 default:
652 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500653 }
654}
655
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800656bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400657 PrimitiveMode transformFeedbackPrimitiveMode,
658 PrimitiveMode renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800659{
660 ASSERT(context);
661
662 if (!context->getExtensions().geometryShader)
663 {
664 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
665 // that does not match the current transform feedback object's draw mode (if transform
666 // feedback is active), (3.0.2, section 2.14, pg 86)
667 return transformFeedbackPrimitiveMode == renderPrimitiveMode;
668 }
669
670 // [GL_EXT_geometry_shader] Table 12.1gs
Jamie Madill493f9572018-05-24 19:52:15 -0400671 switch (renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800672 {
Jamie Madill493f9572018-05-24 19:52:15 -0400673 case PrimitiveMode::Points:
674 return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
675 case PrimitiveMode::Lines:
676 case PrimitiveMode::LineStrip:
677 case PrimitiveMode::LineLoop:
678 return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
679 case PrimitiveMode::Triangles:
680 case PrimitiveMode::TriangleFan:
681 case PrimitiveMode::TriangleStrip:
682 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800683 default:
684 UNREACHABLE();
685 return false;
686 }
687}
688
Jamie Madill5b772312018-03-08 20:28:32 -0500689bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400690 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400691 GLsizei count,
692 GLenum type,
693 const GLvoid *indices,
694 GLsizei primcount)
695{
696 if (primcount < 0)
697 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700698 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400699 return false;
700 }
701
702 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
703 {
704 return false;
705 }
706
Jamie Madill9fdaa492018-02-16 10:52:11 -0500707 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400708}
709
710bool ValidateDrawArraysInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400711 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400712 GLint first,
713 GLsizei count,
714 GLsizei primcount)
715{
716 if (primcount < 0)
717 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700718 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400719 return false;
720 }
721
722 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
723 {
724 return false;
725 }
726
Jamie Madill9fdaa492018-02-16 10:52:11 -0500727 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400728}
729
Jamie Madill5b772312018-03-08 20:28:32 -0500730bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400731{
732 // Verify there is at least one active attribute with a divisor of zero
733 const State &state = context->getGLState();
734
735 Program *program = state.getProgram();
736
737 const auto &attribs = state.getVertexArray()->getVertexAttributes();
738 const auto &bindings = state.getVertexArray()->getVertexBindings();
739 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
740 {
741 const VertexAttribute &attrib = attribs[attributeIndex];
742 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300743 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400744 {
745 return true;
746 }
747 }
748
Brandon Jonesafa75152017-07-21 13:11:29 -0700749 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400750 return false;
751}
752
Jamie Madill5b772312018-03-08 20:28:32 -0500753bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500754{
755 switch (target)
756 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800757 case TextureType::_3D:
758 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800759 return true;
760 default:
761 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400762 }
763}
764
Jamie Madill5b772312018-03-08 20:28:32 -0500765bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800766{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800767 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800768 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800769 case TextureType::_2D:
770 case TextureType::_2DArray:
771 case TextureType::_2DMultisample:
772 case TextureType::CubeMap:
773 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800774 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800775 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400776 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800777 default:
778 return false;
779 }
780}
781
Jamie Madill5b772312018-03-08 20:28:32 -0500782bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500783{
He Yunchaoced53ae2016-11-29 15:00:51 +0800784 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
785 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400786 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500787
788 switch (target)
789 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800790 case GL_FRAMEBUFFER:
791 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400792
He Yunchaoced53ae2016-11-29 15:00:51 +0800793 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800794 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400795 return (context->getExtensions().framebufferBlit ||
796 context->getClientMajorVersion() >= 3);
797
He Yunchaoced53ae2016-11-29 15:00:51 +0800798 default:
799 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500800 }
801}
802
Jamie Madill5b772312018-03-08 20:28:32 -0500803bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400804{
Jamie Madillc29968b2016-01-20 11:17:23 -0500805 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400806 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800807 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400808 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800809 case TextureType::_2D:
810 case TextureType::_2DArray:
811 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500812 maxDimension = caps.max2DTextureSize;
813 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800814 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800815 maxDimension = caps.maxCubeMapTextureSize;
816 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800817 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400818 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800819 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800820 maxDimension = caps.max3DTextureSize;
821 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800822 default:
823 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400824 }
825
Brandon Jones6cad5662017-06-14 13:25:13 -0700826 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400827}
828
Jamie Madill5b772312018-03-08 20:28:32 -0500829bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800830 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700831 GLint level,
832 GLsizei width,
833 GLsizei height,
834 GLsizei depth,
835 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400836{
Brandon Jones6cad5662017-06-14 13:25:13 -0700837 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400838 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700839 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400840 return false;
841 }
Austin Kinross08528e12015-10-07 16:24:40 -0700842 // TexSubImage parameters can be NPOT without textureNPOT extension,
843 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500844 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500845 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500846 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400847 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400848 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700849 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400850 return false;
851 }
852
853 if (!ValidMipLevel(context, target, level))
854 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700855 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400856 return false;
857 }
858
859 return true;
860}
861
Geoff Lang966c9402017-04-18 12:38:27 -0400862bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
863{
864 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
865 (size % blockSize == 0);
866}
867
Jamie Madill5b772312018-03-08 20:28:32 -0500868bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500869 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400870 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500871 GLsizei width,
872 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400873{
Geoff Langca271392017-04-05 12:30:00 -0400874 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400875 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400876 {
877 return false;
878 }
879
Geoff Lang966c9402017-04-18 12:38:27 -0400880 if (width < 0 || height < 0)
881 {
882 return false;
883 }
884
885 if (CompressedTextureFormatRequiresExactSize(internalFormat))
886 {
887 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
888 // block size for level 0 but WebGL disallows this.
889 bool smallerThanBlockSizeAllowed =
890 level > 0 || !context->getExtensions().webglCompatibility;
891
892 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
893 smallerThanBlockSizeAllowed) ||
894 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
895 smallerThanBlockSizeAllowed))
896 {
897 return false;
898 }
899 }
900
901 return true;
902}
903
Jamie Madill5b772312018-03-08 20:28:32 -0500904bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400905 GLenum internalFormat,
906 GLint xoffset,
907 GLint yoffset,
908 GLsizei width,
909 GLsizei height,
910 size_t textureWidth,
911 size_t textureHeight)
912{
913 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
914 if (!formatInfo.compressed)
915 {
916 return false;
917 }
918
Geoff Lang44ff5a72017-02-03 15:15:43 -0500919 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400920 {
921 return false;
922 }
923
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500924 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400925 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500926 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400927 yoffset % formatInfo.compressedBlockHeight != 0)
928 {
929 return false;
930 }
931
932 // Allowed to either have data that is a multiple of block size or is smaller than the block
933 // size but fills the entire mip
934 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
935 static_cast<size_t>(width) == textureWidth &&
936 static_cast<size_t>(height) == textureHeight;
937 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
938 (height % formatInfo.compressedBlockHeight) == 0;
939 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400940 {
941 return false;
942 }
943 }
944
Geoff Langd4f180b2013-09-24 13:57:44 -0400945 return true;
946}
947
Jamie Madill5b772312018-03-08 20:28:32 -0500948bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800949 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400950 GLsizei width,
951 GLsizei height,
952 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400953 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400954 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400955 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400956 GLsizei imageSize)
957{
Corentin Wallez336129f2017-10-17 15:55:40 -0400958 gl::Buffer *pixelUnpackBuffer =
959 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400960 if (pixelUnpackBuffer == nullptr && imageSize < 0)
961 {
962 // Checks are not required
963 return true;
964 }
965
966 // ...the data would be unpacked from the buffer object such that the memory reads required
967 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400968 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
969 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400970 const gl::Extents size(width, height, depth);
971 const auto &unpack = context->getGLState().getUnpackState();
972
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800973 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Jamie Madillca2ff382018-07-11 09:01:17 -0400974 GLuint endByte = 0;
975 if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
Geoff Langff5b2d52016-09-07 11:32:23 -0400976 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400977 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400978 return false;
979 }
980
Geoff Langff5b2d52016-09-07 11:32:23 -0400981 if (pixelUnpackBuffer)
982 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400983 CheckedNumeric<size_t> checkedEndByte(endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400984 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
985 checkedEndByte += checkedOffset;
986
987 if (!checkedEndByte.IsValid() ||
988 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
989 {
990 // Overflow past the end of the buffer
Jamie Madillca2ff382018-07-11 09:01:17 -0400991 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400992 return false;
993 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800994 if (context->getExtensions().webglCompatibility &&
995 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
996 {
997 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
998 PixelUnpackBufferBoundForTransformFeedback);
999 return false;
1000 }
Geoff Langff5b2d52016-09-07 11:32:23 -04001001 }
1002 else
1003 {
1004 ASSERT(imageSize >= 0);
1005 if (pixels == nullptr && imageSize != 0)
1006 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001007 context->handleError(InvalidOperation()
1008 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001009 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001010 }
1011
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001012 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001013 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001014 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001015 return false;
1016 }
1017 }
1018
1019 return true;
1020}
1021
Corentin Wallezad3ae902018-03-09 13:40:42 -05001022bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -05001023{
Geoff Lang37dde692014-01-31 16:34:54 -05001024 switch (queryType)
1025 {
Corentin Wallezad3ae902018-03-09 13:40:42 -05001026 case QueryType::AnySamples:
1027 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001028 return context->getClientMajorVersion() >= 3 ||
1029 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -05001030 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +08001031 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -05001032 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +08001033 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -05001034 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +08001035 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -05001036 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +08001037 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +08001038 default:
1039 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001040 }
1041}
1042
Jamie Madill5b772312018-03-08 20:28:32 -05001043bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001044 GLenum type,
1045 GLboolean normalized,
1046 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001047 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001048 bool pureInteger)
1049{
1050 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001051 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1052 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1053 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1054 // parameter exceeds 255.
1055 constexpr GLsizei kMaxWebGLStride = 255;
1056 if (stride > kMaxWebGLStride)
1057 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001058 context->handleError(InvalidValue()
1059 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001060 return false;
1061 }
1062
1063 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1064 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1065 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1066 // or an INVALID_OPERATION error is generated.
1067 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1068 size_t typeSize = GetVertexFormatTypeSize(internalType);
1069
1070 ASSERT(isPow2(typeSize) && typeSize > 0);
1071 size_t sizeMask = (typeSize - 1);
1072 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1073 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001074 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001075 return false;
1076 }
1077
1078 if ((stride & sizeMask) != 0)
1079 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001080 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001081 return false;
1082 }
1083
1084 return true;
1085}
1086
Jamie Madill5b772312018-03-08 20:28:32 -05001087Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001088{
He Yunchaoced53ae2016-11-29 15:00:51 +08001089 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1090 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1091 // or program object and INVALID_OPERATION if the provided name identifies an object
1092 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001093
Dian Xiang769769a2015-09-09 15:20:08 -07001094 Program *validProgram = context->getProgram(id);
1095
1096 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001097 {
Dian Xiang769769a2015-09-09 15:20:08 -07001098 if (context->getShader(id))
1099 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001100 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001101 }
1102 else
1103 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001104 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001105 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001106 }
Dian Xiang769769a2015-09-09 15:20:08 -07001107
1108 return validProgram;
1109}
1110
Jamie Madill5b772312018-03-08 20:28:32 -05001111Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001112{
1113 // See ValidProgram for spec details.
1114
1115 Shader *validShader = context->getShader(id);
1116
1117 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001118 {
Dian Xiang769769a2015-09-09 15:20:08 -07001119 if (context->getProgram(id))
1120 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001121 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001122 }
1123 else
1124 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001125 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001126 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001127 }
Dian Xiang769769a2015-09-09 15:20:08 -07001128
1129 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001130}
1131
Geoff Langb1196682014-07-23 13:47:29 -04001132bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001133{
Geoff Langfa125c92017-10-24 13:01:46 -04001134 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001135 {
Geoff Langfa125c92017-10-24 13:01:46 -04001136 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1137 {
1138 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1139 return false;
1140 }
Jamie Madillb4472272014-07-03 10:38:55 -04001141
Geoff Langfa125c92017-10-24 13:01:46 -04001142 // Color attachment 0 is validated below because it is always valid
1143 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001144 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001145 {
Geoff Langfa125c92017-10-24 13:01:46 -04001146 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001147 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001148 }
1149 }
1150 else
1151 {
1152 switch (attachment)
1153 {
Geoff Langfa125c92017-10-24 13:01:46 -04001154 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001155 case GL_DEPTH_ATTACHMENT:
1156 case GL_STENCIL_ATTACHMENT:
1157 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001158
He Yunchaoced53ae2016-11-29 15:00:51 +08001159 case GL_DEPTH_STENCIL_ATTACHMENT:
1160 if (!context->getExtensions().webglCompatibility &&
1161 context->getClientMajorVersion() < 3)
1162 {
Geoff Langfa125c92017-10-24 13:01:46 -04001163 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001164 return false;
1165 }
1166 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001167
He Yunchaoced53ae2016-11-29 15:00:51 +08001168 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001169 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001170 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001171 }
1172 }
1173
1174 return true;
1175}
1176
Jamie Madill5b772312018-03-08 20:28:32 -05001177bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001178 GLenum target,
1179 GLsizei samples,
1180 GLenum internalformat,
1181 GLsizei width,
1182 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001183{
1184 switch (target)
1185 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001186 case GL_RENDERBUFFER:
1187 break;
1188 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001189 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001190 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001191 }
1192
1193 if (width < 0 || height < 0 || samples < 0)
1194 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001195 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001196 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001197 }
1198
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001199 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1200 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1201
1202 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04001203 if (!formatCaps.renderbuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001204 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001205 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001206 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001207 }
1208
1209 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1210 // 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 -08001211 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001212 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1213 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001214 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001215 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001216 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001217 }
1218
Geoff Langaae65a42014-05-26 12:43:44 -04001219 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001220 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001221 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001222 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001223 }
1224
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001225 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001226 if (handle == 0)
1227 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001228 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001229 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001230 }
1231
1232 return true;
1233}
1234
He Yunchaoced53ae2016-11-29 15:00:51 +08001235bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1236 GLenum target,
1237 GLenum attachment,
1238 GLenum renderbuffertarget,
1239 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001240{
Geoff Lange8afa902017-09-27 15:00:43 -04001241 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001242 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001243 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001244 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001245 }
1246
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001247 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001248
Jamie Madill84115c92015-04-23 15:00:07 -04001249 ASSERT(framebuffer);
1250 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001251 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001252 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001253 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001254 }
1255
Jamie Madillb4472272014-07-03 10:38:55 -04001256 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001257 {
Jamie Madillb4472272014-07-03 10:38:55 -04001258 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001259 }
1260
Jamie Madillab9d82c2014-01-21 16:38:14 -05001261 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1262 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1263 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1264 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1265 if (renderbuffer != 0)
1266 {
1267 if (!context->getRenderbuffer(renderbuffer))
1268 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001269 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001270 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001271 }
1272 }
1273
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001274 return true;
1275}
1276
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001277bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001278 GLint srcX0,
1279 GLint srcY0,
1280 GLint srcX1,
1281 GLint srcY1,
1282 GLint dstX0,
1283 GLint dstY0,
1284 GLint dstX1,
1285 GLint dstY1,
1286 GLbitfield mask,
1287 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001288{
1289 switch (filter)
1290 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001291 case GL_NEAREST:
1292 break;
1293 case GL_LINEAR:
1294 break;
1295 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001296 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001297 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001298 }
1299
1300 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1301 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001302 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001303 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001304 }
1305
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001306 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1307 // color buffer, leaving only nearest being unfiltered from above
1308 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1309 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001310 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001311 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001312 }
1313
Jamie Madill51f40ec2016-06-15 14:06:00 -04001314 const auto &glState = context->getGLState();
1315 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1316 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001317
1318 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001319 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001320 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001321 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001322 }
1323
Jamie Madill427064d2018-04-13 16:20:34 -04001324 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001325 {
Jamie Madill48faf802014-11-06 15:27:22 -05001326 return false;
1327 }
1328
Jamie Madill427064d2018-04-13 16:20:34 -04001329 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001330 {
Jamie Madill48faf802014-11-06 15:27:22 -05001331 return false;
1332 }
1333
Qin Jiajiaaef92162018-02-27 13:51:44 +08001334 if (readFramebuffer->id() == drawFramebuffer->id())
1335 {
1336 context->handleError(InvalidOperation());
1337 return false;
1338 }
1339
Jamie Madille98b1b52018-03-08 09:47:23 -05001340 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001341 {
Geoff Langb1196682014-07-23 13:47:29 -04001342 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001343 }
1344
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001345 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1346 // always run it in order to avoid triggering driver bugs.
1347 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1348 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001349 {
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001350 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1351 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001352 }
1353
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001354 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1355
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001356 if (mask & GL_COLOR_BUFFER_BIT)
1357 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001358 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001359 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001360
He Yunchao66a41a22016-12-15 16:45:05 +08001361 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001362 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001363 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001364
Geoff Langa15472a2015-08-11 11:48:03 -04001365 for (size_t drawbufferIdx = 0;
1366 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001367 {
Geoff Langa15472a2015-08-11 11:48:03 -04001368 const FramebufferAttachment *attachment =
1369 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1370 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001371 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001372 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001373
Geoff Langb2f3d052013-08-13 12:49:27 -04001374 // The GL ES 3.0.2 spec (pg 193) states that:
1375 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001376 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1377 // as well
1378 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1379 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001380 // Changes with EXT_color_buffer_float:
1381 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001382 GLenum readComponentType = readFormat.info->componentType;
1383 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001384 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001385 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001386 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001387 drawComponentType == GL_SIGNED_NORMALIZED);
1388
1389 if (extensions.colorBufferFloat)
1390 {
1391 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1392 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1393
1394 if (readFixedOrFloat != drawFixedOrFloat)
1395 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001396 context->handleError(InvalidOperation()
1397 << "If the read buffer contains fixed-point or "
1398 "floating-point values, the draw buffer must "
1399 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001400 return false;
1401 }
1402 }
1403 else if (readFixedPoint != drawFixedPoint)
1404 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001405 context->handleError(InvalidOperation()
1406 << "If the read buffer contains fixed-point values, "
1407 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001408 return false;
1409 }
1410
1411 if (readComponentType == GL_UNSIGNED_INT &&
1412 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001413 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001414 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001415 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001416 }
1417
Jamie Madill6163c752015-12-07 16:32:59 -05001418 if (readComponentType == GL_INT && drawComponentType != GL_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 Madilla3944d42016-07-22 22:13:26 -04001424 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001425 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001427 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001428 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001429 }
Geoff Lange4915782017-04-12 15:19:07 -04001430
1431 if (context->getExtensions().webglCompatibility &&
1432 *readColorBuffer == *attachment)
1433 {
1434 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001435 InvalidOperation()
1436 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001437 return false;
1438 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001439 }
1440 }
1441
Jamie Madilla3944d42016-07-22 22:13:26 -04001442 if ((readFormat.info->componentType == GL_INT ||
1443 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1444 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001445 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001446 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001447 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001448 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001449 }
He Yunchao66a41a22016-12-15 16:45:05 +08001450 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1451 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1452 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1453 // situation is an application error that would lead to a crash in ANGLE.
1454 else if (drawFramebuffer->hasEnabledDrawBuffer())
1455 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001456 context->handleError(
1457 InvalidOperation()
1458 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001459 return false;
1460 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001461 }
1462
He Yunchaoced53ae2016-11-29 15:00:51 +08001463 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001464 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1465 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001466 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001467 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001468 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001469 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001470 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001471 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001472 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001473
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001474 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001475 {
Kenneth Russell69382852017-07-21 16:38:44 -04001476 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001477 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001478 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001479 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001480 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001481
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001482 if (readBuffer->getSamples() > 0 && !sameBounds)
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 Lange4915782017-04-12 15:19:07 -04001487
1488 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1489 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001490 context->handleError(
1491 InvalidOperation()
1492 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001493 return false;
1494 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001495 }
He Yunchao66a41a22016-12-15 16:45:05 +08001496 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1497 else if (drawBuffer)
1498 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001499 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1500 "depth/stencil attachment of a "
1501 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001502 return false;
1503 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001504 }
1505 }
1506
Martin Radeva3ed4572017-07-27 18:29:37 +03001507 // ANGLE_multiview, Revision 1:
1508 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001509 // multi-view layout of the current draw framebuffer is not NONE, or if the multi-view layout of
1510 // the current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of
1511 // views in the current read framebuffer is more than one.
1512 if (readFramebuffer->readDisallowedByMultiview())
Martin Radeva3ed4572017-07-27 18:29:37 +03001513 {
1514 context->handleError(InvalidFramebufferOperation()
1515 << "Attempt to read from a multi-view framebuffer.");
1516 return false;
1517 }
1518 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1519 {
1520 context->handleError(InvalidFramebufferOperation()
1521 << "Attempt to write to a multi-view framebuffer.");
1522 return false;
1523 }
1524
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001525 return true;
1526}
1527
Jamie Madill4928b7c2017-06-20 12:57:39 -04001528bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001529 GLint x,
1530 GLint y,
1531 GLsizei width,
1532 GLsizei height,
1533 GLenum format,
1534 GLenum type,
1535 GLsizei bufSize,
1536 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001537 GLsizei *columns,
1538 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001539 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001540{
1541 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001542 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001543 return false;
1544 }
1545
Brandon Jonesd1049182018-03-28 10:02:20 -07001546 GLsizei writeLength = 0;
1547 GLsizei writeColumns = 0;
1548 GLsizei writeRows = 0;
1549
1550 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1551 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001552 {
Geoff Langb1196682014-07-23 13:47:29 -04001553 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001554 }
1555
Brandon Jonesd1049182018-03-28 10:02:20 -07001556 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001557 {
Geoff Langb1196682014-07-23 13:47:29 -04001558 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001559 }
1560
Brandon Jonesd1049182018-03-28 10:02:20 -07001561 SetRobustLengthParam(length, writeLength);
1562 SetRobustLengthParam(columns, writeColumns);
1563 SetRobustLengthParam(rows, writeRows);
1564
Jamie Madillc29968b2016-01-20 11:17:23 -05001565 return true;
1566}
1567
1568bool ValidateReadnPixelsEXT(Context *context,
1569 GLint x,
1570 GLint y,
1571 GLsizei width,
1572 GLsizei height,
1573 GLenum format,
1574 GLenum type,
1575 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001576 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001577{
1578 if (bufSize < 0)
1579 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001580 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001581 return false;
1582 }
1583
Geoff Lang62fce5b2016-09-30 10:46:35 -04001584 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001585 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001586}
Jamie Madill26e91952014-03-05 15:01:27 -05001587
Jamie Madill4928b7c2017-06-20 12:57:39 -04001588bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001589 GLint x,
1590 GLint y,
1591 GLsizei width,
1592 GLsizei height,
1593 GLenum format,
1594 GLenum type,
1595 GLsizei bufSize,
1596 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001597 GLsizei *columns,
1598 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001599 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001600{
Brandon Jonesd1049182018-03-28 10:02:20 -07001601 GLsizei writeLength = 0;
1602 GLsizei writeColumns = 0;
1603 GLsizei writeRows = 0;
1604
Geoff Lang62fce5b2016-09-30 10:46:35 -04001605 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001606 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001607 return false;
1608 }
1609
Brandon Jonesd1049182018-03-28 10:02:20 -07001610 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1611 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001612 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001613 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001614 }
1615
Brandon Jonesd1049182018-03-28 10:02:20 -07001616 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001617 {
1618 return false;
1619 }
1620
Brandon Jonesd1049182018-03-28 10:02:20 -07001621 SetRobustLengthParam(length, writeLength);
1622 SetRobustLengthParam(columns, writeColumns);
1623 SetRobustLengthParam(rows, writeRows);
1624
Geoff Lang62fce5b2016-09-30 10:46:35 -04001625 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001626}
1627
Jamie Madillf0e04492017-08-26 15:28:42 -04001628bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001629{
1630 if (!context->getExtensions().occlusionQueryBoolean &&
1631 !context->getExtensions().disjointTimerQuery)
1632 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001633 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001634 return false;
1635 }
1636
Olli Etuaho41997e72016-03-10 13:38:39 +02001637 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001638}
1639
Jamie Madillf0e04492017-08-26 15:28:42 -04001640bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001641{
1642 if (!context->getExtensions().occlusionQueryBoolean &&
1643 !context->getExtensions().disjointTimerQuery)
1644 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001645 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001646 return false;
1647 }
1648
Olli Etuaho41997e72016-03-10 13:38:39 +02001649 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001650}
1651
Jamie Madillf0e04492017-08-26 15:28:42 -04001652bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1653{
1654 if (!context->getExtensions().occlusionQueryBoolean &&
1655 !context->getExtensions().disjointTimerQuery)
1656 {
1657 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1658 return false;
1659 }
1660
1661 return true;
1662}
1663
Corentin Wallezad3ae902018-03-09 13:40:42 -05001664bool ValidateBeginQueryBase(gl::Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001665{
1666 if (!ValidQueryType(context, target))
1667 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001668 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001669 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001670 }
1671
1672 if (id == 0)
1673 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001674 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001675 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001676 }
1677
1678 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1679 // of zero, if the active query object name for <target> is non-zero (for the
1680 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1681 // the active query for either target is non-zero), if <id> is the name of an
1682 // existing query object whose type does not match <target>, or if <id> is the
1683 // active query object name for any query type, the error INVALID_OPERATION is
1684 // generated.
1685
1686 // Ensure no other queries are active
1687 // NOTE: If other queries than occlusion are supported, we will need to check
1688 // separately that:
1689 // a) The query ID passed is not the current active query for any target/type
1690 // b) There are no active queries for the requested target (and in the case
1691 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1692 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001693
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001694 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001695 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001696 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001697 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001698 }
1699
1700 Query *queryObject = context->getQuery(id, true, target);
1701
1702 // check that name was obtained with glGenQueries
1703 if (!queryObject)
1704 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001705 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001706 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001707 }
1708
1709 // check for type mismatch
1710 if (queryObject->getType() != target)
1711 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001712 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001713 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001714 }
1715
1716 return true;
1717}
1718
Corentin Wallezad3ae902018-03-09 13:40:42 -05001719bool ValidateBeginQueryEXT(gl::Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001720{
1721 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001722 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001723 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001724 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001725 return false;
1726 }
1727
1728 return ValidateBeginQueryBase(context, target, id);
1729}
1730
Corentin Wallezad3ae902018-03-09 13:40:42 -05001731bool ValidateEndQueryBase(gl::Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001732{
1733 if (!ValidQueryType(context, target))
1734 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001735 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001736 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001737 }
1738
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001739 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001740
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001741 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001743 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001744 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001745 }
1746
Jamie Madill45c785d2014-05-13 14:09:34 -04001747 return true;
1748}
1749
Corentin Wallezad3ae902018-03-09 13:40:42 -05001750bool ValidateEndQueryEXT(gl::Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001751{
1752 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001753 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001754 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001755 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001756 return false;
1757 }
1758
1759 return ValidateEndQueryBase(context, target);
1760}
1761
Corentin Wallezad3ae902018-03-09 13:40:42 -05001762bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001763{
1764 if (!context->getExtensions().disjointTimerQuery)
1765 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001766 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001767 return false;
1768 }
1769
Corentin Wallezad3ae902018-03-09 13:40:42 -05001770 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001771 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001772 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001773 return false;
1774 }
1775
1776 Query *queryObject = context->getQuery(id, true, target);
1777 if (queryObject == nullptr)
1778 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001779 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001780 return false;
1781 }
1782
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001783 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001784 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001785 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001786 return false;
1787 }
1788
1789 return true;
1790}
1791
Corentin Wallezad3ae902018-03-09 13:40:42 -05001792bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001793{
Geoff Lang2186c382016-10-14 10:54:54 -04001794 if (numParams)
1795 {
1796 *numParams = 0;
1797 }
1798
Corentin Wallezad3ae902018-03-09 13:40:42 -05001799 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001800 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001801 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001802 return false;
1803 }
1804
1805 switch (pname)
1806 {
1807 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001808 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001809 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001810 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001811 return false;
1812 }
1813 break;
1814 case GL_QUERY_COUNTER_BITS_EXT:
1815 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001816 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001817 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001818 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001819 return false;
1820 }
1821 break;
1822 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001823 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001824 return false;
1825 }
1826
Geoff Lang2186c382016-10-14 10:54:54 -04001827 if (numParams)
1828 {
1829 // All queries return only one value
1830 *numParams = 1;
1831 }
1832
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001833 return true;
1834}
1835
Corentin Wallezad3ae902018-03-09 13:40:42 -05001836bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001837{
1838 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001839 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001840 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001841 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001842 return false;
1843 }
1844
Geoff Lang2186c382016-10-14 10:54:54 -04001845 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001846}
1847
Geoff Lang2186c382016-10-14 10:54:54 -04001848bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001849 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001850 GLenum pname,
1851 GLsizei bufSize,
1852 GLsizei *length,
1853 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001854{
Geoff Lang2186c382016-10-14 10:54:54 -04001855 if (!ValidateRobustEntryPoint(context, bufSize))
1856 {
1857 return false;
1858 }
1859
Brandon Jonesd1049182018-03-28 10:02:20 -07001860 GLsizei numParams = 0;
1861
1862 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001863 {
1864 return false;
1865 }
1866
Brandon Jonesd1049182018-03-28 10:02:20 -07001867 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001868 {
1869 return false;
1870 }
1871
Brandon Jonesd1049182018-03-28 10:02:20 -07001872 SetRobustLengthParam(length, numParams);
1873
Geoff Lang2186c382016-10-14 10:54:54 -04001874 return true;
1875}
1876
1877bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1878{
1879 if (numParams)
1880 {
1881 *numParams = 0;
1882 }
1883
Corentin Wallezad3ae902018-03-09 13:40:42 -05001884 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001885
1886 if (!queryObject)
1887 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001888 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001889 return false;
1890 }
1891
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001892 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001893 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001894 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001895 return false;
1896 }
1897
1898 switch (pname)
1899 {
1900 case GL_QUERY_RESULT_EXT:
1901 case GL_QUERY_RESULT_AVAILABLE_EXT:
1902 break;
1903
1904 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001905 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001906 return false;
1907 }
1908
Geoff Lang2186c382016-10-14 10:54:54 -04001909 if (numParams)
1910 {
1911 *numParams = 1;
1912 }
1913
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001914 return true;
1915}
1916
1917bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1918{
1919 if (!context->getExtensions().disjointTimerQuery)
1920 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001921 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001922 return false;
1923 }
Geoff Lang2186c382016-10-14 10:54:54 -04001924 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1925}
1926
1927bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1928 GLuint id,
1929 GLenum pname,
1930 GLsizei bufSize,
1931 GLsizei *length,
1932 GLint *params)
1933{
1934 if (!context->getExtensions().disjointTimerQuery)
1935 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001936 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001937 return false;
1938 }
1939
1940 if (!ValidateRobustEntryPoint(context, bufSize))
1941 {
1942 return false;
1943 }
1944
Brandon Jonesd1049182018-03-28 10:02:20 -07001945 GLsizei numParams = 0;
1946
1947 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001948 {
1949 return false;
1950 }
1951
Brandon Jonesd1049182018-03-28 10:02:20 -07001952 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001953 {
1954 return false;
1955 }
1956
Brandon Jonesd1049182018-03-28 10:02:20 -07001957 SetRobustLengthParam(length, numParams);
1958
Geoff Lang2186c382016-10-14 10:54:54 -04001959 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001960}
1961
1962bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1963{
1964 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001965 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001966 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001967 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001968 return false;
1969 }
Geoff Lang2186c382016-10-14 10:54:54 -04001970 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1971}
1972
1973bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1974 GLuint id,
1975 GLenum pname,
1976 GLsizei bufSize,
1977 GLsizei *length,
1978 GLuint *params)
1979{
1980 if (!context->getExtensions().disjointTimerQuery &&
1981 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1982 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001983 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001984 return false;
1985 }
1986
1987 if (!ValidateRobustEntryPoint(context, bufSize))
1988 {
1989 return false;
1990 }
1991
Brandon Jonesd1049182018-03-28 10:02:20 -07001992 GLsizei numParams = 0;
1993
1994 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001995 {
1996 return false;
1997 }
1998
Brandon Jonesd1049182018-03-28 10:02:20 -07001999 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002000 {
2001 return false;
2002 }
2003
Brandon Jonesd1049182018-03-28 10:02:20 -07002004 SetRobustLengthParam(length, numParams);
2005
Geoff Lang2186c382016-10-14 10:54:54 -04002006 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002007}
2008
2009bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2010{
2011 if (!context->getExtensions().disjointTimerQuery)
2012 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002013 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002014 return false;
2015 }
Geoff Lang2186c382016-10-14 10:54:54 -04002016 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2017}
2018
2019bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2020 GLuint id,
2021 GLenum pname,
2022 GLsizei bufSize,
2023 GLsizei *length,
2024 GLint64 *params)
2025{
2026 if (!context->getExtensions().disjointTimerQuery)
2027 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002028 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002029 return false;
2030 }
2031
2032 if (!ValidateRobustEntryPoint(context, bufSize))
2033 {
2034 return false;
2035 }
2036
Brandon Jonesd1049182018-03-28 10:02:20 -07002037 GLsizei numParams = 0;
2038
2039 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002040 {
2041 return false;
2042 }
2043
Brandon Jonesd1049182018-03-28 10:02:20 -07002044 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002045 {
2046 return false;
2047 }
2048
Brandon Jonesd1049182018-03-28 10:02:20 -07002049 SetRobustLengthParam(length, numParams);
2050
Geoff Lang2186c382016-10-14 10:54:54 -04002051 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002052}
2053
2054bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2055{
2056 if (!context->getExtensions().disjointTimerQuery)
2057 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002058 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002059 return false;
2060 }
Geoff Lang2186c382016-10-14 10:54:54 -04002061 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2062}
2063
2064bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2065 GLuint id,
2066 GLenum pname,
2067 GLsizei bufSize,
2068 GLsizei *length,
2069 GLuint64 *params)
2070{
2071 if (!context->getExtensions().disjointTimerQuery)
2072 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002073 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002074 return false;
2075 }
2076
2077 if (!ValidateRobustEntryPoint(context, bufSize))
2078 {
2079 return false;
2080 }
2081
Brandon Jonesd1049182018-03-28 10:02:20 -07002082 GLsizei numParams = 0;
2083
2084 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002085 {
2086 return false;
2087 }
2088
Brandon Jonesd1049182018-03-28 10:02:20 -07002089 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002090 {
2091 return false;
2092 }
2093
Brandon Jonesd1049182018-03-28 10:02:20 -07002094 SetRobustLengthParam(length, numParams);
2095
Geoff Lang2186c382016-10-14 10:54:54 -04002096 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002097}
2098
Jamie Madill5b772312018-03-08 20:28:32 -05002099bool ValidateUniformCommonBase(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002100 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002101 GLint location,
2102 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002103 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002104{
Jiajia Qin5451d532017-11-16 17:16:34 +08002105 // TODO(Jiajia): Add image uniform check in future.
2106 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002107 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002108 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002109 return false;
2110 }
2111
Jiajia Qin5451d532017-11-16 17:16:34 +08002112 if (!program)
2113 {
2114 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2115 return false;
2116 }
2117
2118 if (!program->isLinked())
2119 {
2120 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2121 return false;
2122 }
2123
2124 if (location == -1)
2125 {
2126 // Silently ignore the uniform command
2127 return false;
2128 }
2129
2130 const auto &uniformLocations = program->getUniformLocations();
2131 size_t castedLocation = static_cast<size_t>(location);
2132 if (castedLocation >= uniformLocations.size())
2133 {
2134 context->handleError(InvalidOperation() << "Invalid uniform location");
2135 return false;
2136 }
2137
2138 const auto &uniformLocation = uniformLocations[castedLocation];
2139 if (uniformLocation.ignored)
2140 {
2141 // Silently ignore the uniform command
2142 return false;
2143 }
2144
2145 if (!uniformLocation.used())
2146 {
2147 context->handleError(InvalidOperation());
2148 return false;
2149 }
2150
2151 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2152
2153 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002154 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002155 {
2156 context->handleError(InvalidOperation());
2157 return false;
2158 }
2159
2160 *uniformOut = &uniform;
2161 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002162}
2163
Jamie Madill5b772312018-03-08 20:28:32 -05002164bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002165 GLenum uniformType,
2166 GLsizei count,
2167 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002168{
Jiajia Qin5451d532017-11-16 17:16:34 +08002169 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2170 // It is compatible with INT or BOOL.
2171 // Do these cheap tests first, for a little extra speed.
2172 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002173 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002174 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002175 }
2176
Jiajia Qin5451d532017-11-16 17:16:34 +08002177 if (IsSamplerType(uniformType))
2178 {
2179 // Check that the values are in range.
2180 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2181 for (GLsizei i = 0; i < count; ++i)
2182 {
2183 if (value[i] < 0 || value[i] >= max)
2184 {
2185 context->handleError(InvalidValue() << "sampler uniform value out of range");
2186 return false;
2187 }
2188 }
2189 return true;
2190 }
2191
2192 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2193 return false;
2194}
2195
Jamie Madill5b772312018-03-08 20:28:32 -05002196bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002197{
2198 // Check that the value type is compatible with uniform type.
2199 // Do the cheaper test first, for a little extra speed.
2200 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2201 {
2202 return true;
2203 }
2204
2205 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2206 return false;
2207}
2208
Jamie Madill5b772312018-03-08 20:28:32 -05002209bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002210{
2211 // Check that the value type is compatible with uniform type.
2212 if (valueType == uniformType)
2213 {
2214 return true;
2215 }
2216
2217 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2218 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002219}
2220
Jamie Madill5b772312018-03-08 20:28:32 -05002221bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002222{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002223 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002224 gl::Program *programObject = context->getGLState().getProgram();
2225 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2226 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002227}
2228
Jamie Madill5b772312018-03-08 20:28:32 -05002229bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002230{
2231 const LinkedUniform *uniform = nullptr;
2232 gl::Program *programObject = context->getGLState().getProgram();
2233 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2234 ValidateUniform1ivValue(context, uniform->type, count, value);
2235}
2236
Jamie Madill5b772312018-03-08 20:28:32 -05002237bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002238 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002239 GLint location,
2240 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002241 GLboolean transpose)
2242{
Geoff Lang92019432017-11-20 13:09:34 -05002243 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002244 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002245 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002246 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002247 }
2248
Jamie Madill62d31cb2015-09-11 13:25:51 -04002249 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002250 gl::Program *programObject = context->getGLState().getProgram();
2251 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2252 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002253}
2254
Jamie Madill5b772312018-03-08 20:28:32 -05002255bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002256{
2257 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2258 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002259 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002260 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002261 }
2262
Jamie Madill0af26e12015-03-05 19:54:33 -05002263 const Caps &caps = context->getCaps();
2264
Jamie Madill893ab082014-05-16 16:56:10 -04002265 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2266 {
2267 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2268
Jamie Madill0af26e12015-03-05 19:54:33 -05002269 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002270 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002271 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002272 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002273 }
2274 }
2275
2276 switch (pname)
2277 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002278 case GL_TEXTURE_BINDING_2D:
2279 case GL_TEXTURE_BINDING_CUBE_MAP:
2280 case GL_TEXTURE_BINDING_3D:
2281 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002282 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002283 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002284 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2285 if (!context->getExtensions().textureRectangle)
2286 {
2287 context->handleError(InvalidEnum()
2288 << "ANGLE_texture_rectangle extension not present");
2289 return false;
2290 }
2291 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002292 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2293 if (!context->getExtensions().eglStreamConsumerExternal &&
2294 !context->getExtensions().eglImageExternal)
2295 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002296 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2297 "nor GL_OES_EGL_image_external "
2298 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002299 return false;
2300 }
2301 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002302
He Yunchaoced53ae2016-11-29 15:00:51 +08002303 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2304 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002305 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002306 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2307 ASSERT(readFramebuffer);
2308
Jamie Madill427064d2018-04-13 16:20:34 -04002309 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002310 {
Geoff Langb1196682014-07-23 13:47:29 -04002311 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002312 }
2313
Jamie Madille98b1b52018-03-08 09:47:23 -05002314 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002315 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002316 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002317 return false;
2318 }
2319
Jamie Madille98b1b52018-03-08 09:47:23 -05002320 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002321 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002322 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002323 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002324 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002325 }
2326 }
2327 break;
2328
He Yunchaoced53ae2016-11-29 15:00:51 +08002329 default:
2330 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002331 }
2332
2333 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002334 if (*numParams == 0)
2335 {
2336 return false;
2337 }
2338
2339 return true;
2340}
2341
Brandon Jonesd1049182018-03-28 10:02:20 -07002342bool ValidateGetBooleanvRobustANGLE(Context *context,
2343 GLenum pname,
2344 GLsizei bufSize,
2345 GLsizei *length,
2346 GLboolean *params)
2347{
2348 GLenum nativeType;
2349 unsigned int numParams = 0;
2350
2351 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2352 {
2353 return false;
2354 }
2355
2356 SetRobustLengthParam(length, numParams);
2357
2358 return true;
2359}
2360
2361bool ValidateGetFloatvRobustANGLE(Context *context,
2362 GLenum pname,
2363 GLsizei bufSize,
2364 GLsizei *length,
2365 GLfloat *params)
2366{
2367 GLenum nativeType;
2368 unsigned int numParams = 0;
2369
2370 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2371 {
2372 return false;
2373 }
2374
2375 SetRobustLengthParam(length, numParams);
2376
2377 return true;
2378}
2379
2380bool ValidateGetIntegervRobustANGLE(Context *context,
2381 GLenum pname,
2382 GLsizei bufSize,
2383 GLsizei *length,
2384 GLint *data)
2385{
2386 GLenum nativeType;
2387 unsigned int numParams = 0;
2388
2389 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2390 {
2391 return false;
2392 }
2393
2394 SetRobustLengthParam(length, numParams);
2395
2396 return true;
2397}
2398
2399bool ValidateGetInteger64vRobustANGLE(Context *context,
2400 GLenum pname,
2401 GLsizei bufSize,
2402 GLsizei *length,
2403 GLint64 *data)
2404{
2405 GLenum nativeType;
2406 unsigned int numParams = 0;
2407
2408 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2409 {
2410 return false;
2411 }
2412
2413 if (nativeType == GL_INT_64_ANGLEX)
2414 {
2415 CastStateValues(context, nativeType, pname, numParams, data);
2416 return false;
2417 }
2418
2419 SetRobustLengthParam(length, numParams);
2420 return true;
2421}
2422
Jamie Madill5b772312018-03-08 20:28:32 -05002423bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002424 GLenum pname,
2425 GLsizei bufSize,
2426 GLenum *nativeType,
2427 unsigned int *numParams)
2428{
2429 if (!ValidateRobustEntryPoint(context, bufSize))
2430 {
2431 return false;
2432 }
2433
2434 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2435 {
2436 return false;
2437 }
2438
2439 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002440 {
2441 return false;
2442 }
2443
2444 return true;
2445}
2446
Jamie Madill5b772312018-03-08 20:28:32 -05002447bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002448 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002449 GLint level,
2450 GLenum internalformat,
2451 bool isSubImage,
2452 GLint xoffset,
2453 GLint yoffset,
2454 GLint zoffset,
2455 GLint x,
2456 GLint y,
2457 GLsizei width,
2458 GLsizei height,
2459 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002460 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002461{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002462 TextureType texType = TextureTargetToType(target);
2463
Brandon Jones6cad5662017-06-14 13:25:13 -07002464 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002465 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002466 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2467 return false;
2468 }
2469
2470 if (width < 0 || height < 0)
2471 {
2472 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002473 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002474 }
2475
He Yunchaoced53ae2016-11-29 15:00:51 +08002476 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2477 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002478 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002479 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002480 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002481 }
2482
2483 if (border != 0)
2484 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002485 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002486 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002487 }
2488
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002489 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002490 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002491 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002492 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002493 }
2494
Jamie Madille98b1b52018-03-08 09:47:23 -05002495 const gl::State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002496 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002497 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002498 {
Geoff Langb1196682014-07-23 13:47:29 -04002499 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002500 }
2501
Jamie Madille98b1b52018-03-08 09:47:23 -05002502 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002503 {
Geoff Langb1196682014-07-23 13:47:29 -04002504 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002505 }
2506
Martin Radev138064f2016-07-15 12:03:41 +03002507 if (readFramebuffer->getReadBufferState() == GL_NONE)
2508 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002509 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002510 return false;
2511 }
2512
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002513 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2514 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002515 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002516 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002517 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2518 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002519 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002520 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002521 return false;
2522 }
2523
Martin Radev04e2c3b2017-07-27 16:54:35 +03002524 // ANGLE_multiview spec, Revision 1:
2525 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2526 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002527 // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
2528 // framebuffer is more than one.
2529 if (readFramebuffer->readDisallowedByMultiview())
Martin Radev04e2c3b2017-07-27 16:54:35 +03002530 {
2531 context->handleError(InvalidFramebufferOperation()
2532 << "The active read framebuffer object has multiview attachments.");
2533 return false;
2534 }
2535
Geoff Langaae65a42014-05-26 12:43:44 -04002536 const gl::Caps &caps = context->getCaps();
2537
Geoff Langaae65a42014-05-26 12:43:44 -04002538 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002539 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002540 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002541 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002542 maxDimension = caps.max2DTextureSize;
2543 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002544
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002545 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002546 maxDimension = caps.maxCubeMapTextureSize;
2547 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002548
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002549 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002550 maxDimension = caps.maxRectangleTextureSize;
2551 break;
2552
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002553 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002554 maxDimension = caps.max2DTextureSize;
2555 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002556
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002557 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002558 maxDimension = caps.max3DTextureSize;
2559 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002560
He Yunchaoced53ae2016-11-29 15:00:51 +08002561 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002562 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002563 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002564 }
2565
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002566 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002567 if (!texture)
2568 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002569 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002570 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002571 }
2572
Geoff Lang69cce582015-09-17 13:20:36 -04002573 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002574 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002575 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002576 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002577 }
2578
Geoff Langca271392017-04-05 12:30:00 -04002579 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002580 isSubImage ? *texture->getFormat(target, level).info
2581 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002582
Geoff Lang966c9402017-04-18 12:38:27 -04002583 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002584 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002585 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002586 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002587 }
2588
2589 if (isSubImage)
2590 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002591 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2592 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2593 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002594 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002595 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002596 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002597 }
2598 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002599 else
2600 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002601 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002602 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002603 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002604 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002605 }
2606
Geoff Langeb66a6e2016-10-31 13:06:12 -04002607 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002608 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002609 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002610 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002611 }
2612
2613 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002614 if (static_cast<int>(width) > maxLevelDimension ||
2615 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002616 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002617 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002618 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002619 }
2620 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002621
Jamie Madill0c8abca2016-07-22 20:21:26 -04002622 if (textureFormatOut)
2623 {
2624 *textureFormatOut = texture->getFormat(target, level);
2625 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002626
2627 // Detect texture copying feedback loops for WebGL.
2628 if (context->getExtensions().webglCompatibility)
2629 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002630 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002631 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002632 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002633 return false;
2634 }
2635 }
2636
Jamie Madill560a8d82014-05-21 13:06:20 -04002637 return true;
2638}
2639
Jamie Madill493f9572018-05-24 19:52:15 -04002640bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002641{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002642 const Extensions &extensions = context->getExtensions();
2643
Jamie Madill1aeb1312014-06-20 13:21:25 -04002644 switch (mode)
2645 {
Jamie Madill493f9572018-05-24 19:52:15 -04002646 case PrimitiveMode::Points:
2647 case PrimitiveMode::Lines:
2648 case PrimitiveMode::LineLoop:
2649 case PrimitiveMode::LineStrip:
2650 case PrimitiveMode::Triangles:
2651 case PrimitiveMode::TriangleStrip:
2652 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002653 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002654
Jamie Madill493f9572018-05-24 19:52:15 -04002655 case PrimitiveMode::LinesAdjacency:
2656 case PrimitiveMode::LineStripAdjacency:
2657 case PrimitiveMode::TrianglesAdjacency:
2658 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002659 if (!extensions.geometryShader)
2660 {
2661 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2662 return false;
2663 }
2664 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002665 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002666 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002667 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002668 }
2669
Jamie Madill250d33f2014-06-06 17:09:03 -04002670 if (count < 0)
2671 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002672 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002673 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002674 }
2675
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002676 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002677
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002678 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2679 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2680 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2681 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002682 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002683 // Check for mapped buffers
2684 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002685 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002686 {
2687 context->handleError(InvalidOperation());
2688 return false;
2689 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002690 }
2691
Jamie Madillcbcde722017-01-06 14:50:00 -05002692 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2693 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002694 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002695 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002696 {
Ken Russellb9f92502018-01-27 19:00:26 -08002697 ASSERT(framebuffer);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002698 const FramebufferAttachment *dsAttachment =
2699 framebuffer->getStencilOrDepthStencilAttachment();
Ken Russellb9f92502018-01-27 19:00:26 -08002700 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2701 ASSERT(stencilBits <= 8);
2702
Jinyoung Hur85769f02015-10-20 17:08:44 -04002703 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Ken Russellb9f92502018-01-27 19:00:26 -08002704 if (depthStencilState.stencilTest && stencilBits > 0)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002705 {
Ken Russellb9f92502018-01-27 19:00:26 -08002706 GLuint maxStencilValue = (1 << stencilBits) - 1;
2707
2708 bool differentRefs =
2709 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2710 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2711 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2712 (depthStencilState.stencilBackWritemask & maxStencilValue);
2713 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2714 (depthStencilState.stencilBackMask & maxStencilValue);
2715
2716 if (differentRefs || differentWritemasks || differentMasks)
Jamie Madillcbcde722017-01-06 14:50:00 -05002717 {
Ken Russellb9f92502018-01-27 19:00:26 -08002718 if (!extensions.webglCompatibility)
2719 {
Jamie Madilla2f043d2018-07-10 17:21:20 -04002720 WARN() << "This ANGLE implementation does not support separate front/back "
2721 "stencil writemasks, reference values, or stencil mask values.";
Ken Russellb9f92502018-01-27 19:00:26 -08002722 }
2723 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
2724 return false;
Jamie Madillcbcde722017-01-06 14:50:00 -05002725 }
Geoff Lang3a86ad32015-09-01 11:47:05 -04002726 }
Jamie Madillac528012014-06-20 13:21:23 -04002727 }
2728
Jamie Madill427064d2018-04-13 16:20:34 -04002729 if (!ValidateFramebufferComplete(context, framebuffer))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002730 {
Geoff Langb1196682014-07-23 13:47:29 -04002731 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002732 }
2733
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002734 // If we are running GLES1, there is no current program.
2735 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002736 {
Jamie Madilld4cfa572014-07-08 10:00:32 -04002737
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002738 gl::Program *program = state.getProgram();
2739 if (!program)
Martin Radev7cf61662017-07-26 17:10:53 +03002740 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002741 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Martin Radev7cf61662017-07-26 17:10:53 +03002742 return false;
2743 }
Martin Radev7e69f762017-07-27 14:54:13 +03002744
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002745 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2746 // vertex shader stage or fragment shader stage is a undefined behaviour.
2747 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2748 // produce undefined result.
2749 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2750 !program->hasLinkedShaderStage(ShaderType::Fragment))
Martin Radev7e69f762017-07-27 14:54:13 +03002751 {
2752 context->handleError(InvalidOperation()
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002753 << "It is a undefined behaviour to render without "
2754 "vertex shader stage or fragment shader stage.");
Martin Radev7e69f762017-07-27 14:54:13 +03002755 return false;
2756 }
Martin Radevffe754b2017-07-31 10:38:07 +03002757
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002758 if (!program->validateSamplers(nullptr, context->getCaps()))
Martin Radevffe754b2017-07-31 10:38:07 +03002759 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002760 context->handleError(InvalidOperation());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002761 return false;
2762 }
2763
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002764 if (extensions.multiview)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002765 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002766 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2767 const int framebufferNumViews = framebuffer->getNumViews();
2768 if (framebufferNumViews != programNumViews)
2769 {
2770 context->handleError(InvalidOperation()
2771 << "The number of views in the active program "
2772 "and draw framebuffer does not match.");
2773 return false;
2774 }
2775
2776 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2777 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2778 framebufferNumViews > 1)
2779 {
2780 context->handleError(InvalidOperation()
2781 << "There is an active transform feedback object "
2782 "when the number of views in the active draw "
2783 "framebuffer is greater than 1.");
2784 return false;
2785 }
2786
2787 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2788 state.isQueryActive(QueryType::TimeElapsed))
2789 {
2790 context->handleError(InvalidOperation()
2791 << "There is an active query for target "
2792 "GL_TIME_ELAPSED_EXT when the number of "
2793 "views in the active draw framebuffer is "
2794 "greater than 1.");
2795 return false;
2796 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002797 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002798
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002799 // Do geometry shader specific validations
2800 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002801 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002802 if (!IsCompatibleDrawModeWithGeometryShader(
2803 mode, program->getGeometryShaderInputPrimitiveType()))
2804 {
2805 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2806 IncompatibleDrawModeAgainstGeometryShader);
2807 return false;
2808 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002809 }
Geoff Lange0cff192017-05-30 13:04:56 -04002810
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002811 // Uniform buffer validation
2812 for (unsigned int uniformBlockIndex = 0;
2813 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Geoff Lang9ab5b822017-05-30 16:19:23 -04002814 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002815 const gl::InterfaceBlock &uniformBlock =
2816 program->getUniformBlockByIndex(uniformBlockIndex);
2817 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
2818 const OffsetBindingPointer<Buffer> &uniformBuffer =
2819 state.getIndexedUniformBuffer(blockBinding);
2820
2821 if (uniformBuffer.get() == nullptr)
2822 {
2823 // undefined behaviour
2824 context->handleError(
2825 InvalidOperation()
2826 << "It is undefined behaviour to have a used but unbound uniform buffer.");
2827 return false;
2828 }
2829
2830 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2831 if (uniformBufferSize < uniformBlock.dataSize)
2832 {
2833 // undefined behaviour
2834 context->handleError(
2835 InvalidOperation()
2836 << "It is undefined behaviour to use a uniform buffer that is too small.");
2837 return false;
2838 }
2839
2840 if (extensions.webglCompatibility &&
2841 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2842 {
2843 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2844 UniformBufferBoundForTransformFeedback);
2845 return false;
2846 }
Geoff Lang9ab5b822017-05-30 16:19:23 -04002847 }
2848
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002849 // Do some additonal WebGL-specific validation
2850 if (extensions.webglCompatibility)
Geoff Lange0cff192017-05-30 13:04:56 -04002851 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002852 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2853 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2854 transformFeedbackObject->buffersBoundForOtherUse())
2855 {
2856 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2857 TransformFeedbackBufferDoubleBound);
2858 return false;
2859 }
2860 // Detect rendering feedback loops for WebGL.
2861 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2862 {
2863 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
2864 return false;
2865 }
2866
2867 // Detect that the vertex shader input types match the attribute types
2868 if (!ValidateVertexShaderAttributeTypeMatch(context))
2869 {
2870 return false;
2871 }
2872
2873 // Detect that the color buffer types match the fragment shader output types
2874 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2875 {
2876 return false;
2877 }
Geoff Lange0cff192017-05-30 13:04:56 -04002878 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002879 }
2880
Jamie Madill9fdaa492018-02-16 10:52:11 -05002881 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002882}
2883
Jamie Madill5b772312018-03-08 20:28:32 -05002884bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002885 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002886 GLint first,
2887 GLsizei count,
2888 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002889{
Jamie Madillfd716582014-06-06 17:09:04 -04002890 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002891 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002892 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002893 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002894 }
2895
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002896 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002897 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002898 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002899 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002900 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002901 if (!ValidateTransformFeedbackPrimitiveMode(context,
2902 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002903 {
James Darpinian30b604d2018-03-12 17:26:57 -07002904 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2905 return false;
2906 }
2907
2908 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2909 {
2910 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2911 return false;
2912 }
Jamie Madillfd716582014-06-06 17:09:04 -04002913 }
2914
Jiajia Qind9671222016-11-29 16:30:31 +08002915 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002916 {
2917 return false;
2918 }
2919
Corentin Wallez71168a02016-12-19 15:11:18 -08002920 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002921 // - first < 0 has been checked as an error condition.
2922 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002923 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002924 ASSERT(first >= 0);
2925 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002926 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002927 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2928 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2929 {
2930 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2931 return false;
2932 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002933
Jamie Madill9fdaa492018-02-16 10:52:11 -05002934 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2935 {
2936 return false;
2937 }
Jamie Madillfd716582014-06-06 17:09:04 -04002938 }
2939
2940 return true;
2941}
2942
He Yunchaoced53ae2016-11-29 15:00:51 +08002943bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002944 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002945 GLint first,
2946 GLsizei count,
2947 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002948{
Geoff Lang63c5a592017-09-27 14:08:16 -04002949 if (!context->getExtensions().instancedArrays)
2950 {
2951 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2952 return false;
2953 }
2954
Corentin Wallez170efbf2017-05-02 13:45:01 -04002955 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002956 {
2957 return false;
2958 }
2959
Corentin Wallez0dc97812017-06-22 14:38:44 -04002960 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002961}
2962
Jamie Madill493f9572018-05-24 19:52:15 -04002963bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002964{
Jamie Madill250d33f2014-06-06 17:09:03 -04002965 switch (type)
2966 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002967 case GL_UNSIGNED_BYTE:
2968 case GL_UNSIGNED_SHORT:
2969 break;
2970 case GL_UNSIGNED_INT:
2971 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2972 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002973 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002974 return false;
2975 }
2976 break;
2977 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002978 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002979 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002980 }
2981
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002982 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002983
2984 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002985 if (curTransformFeedback && curTransformFeedback->isActive() &&
2986 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002987 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002988 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2989 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2990 if (context->getExtensions().geometryShader)
2991 {
2992 if (!ValidateTransformFeedbackPrimitiveMode(
2993 context, curTransformFeedback->getPrimitiveMode(), mode))
2994 {
2995 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2996 return false;
2997 }
2998 }
2999 else
3000 {
3001 // It is an invalid operation to call DrawElements, DrawRangeElements or
3002 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
3003 // 86)
3004 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3005 UnsupportedDrawModeForTransformFeedback);
3006 return false;
3007 }
Jamie Madill250d33f2014-06-06 17:09:03 -04003008 }
3009
Jiajia Qind9671222016-11-29 16:30:31 +08003010 return true;
3011}
3012
Jamie Madill5b772312018-03-08 20:28:32 -05003013bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003014 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003015 GLsizei count,
3016 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003017 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003018 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08003019{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08003020 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08003021 return false;
3022
3023 const State &state = context->getGLState();
3024
Corentin Wallez170efbf2017-05-02 13:45:01 -04003025 if (!ValidateDrawBase(context, mode, count))
3026 {
3027 return false;
3028 }
3029
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003030 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
3031 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
3032 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
3033 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04003034 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003035 // Check for mapped buffers
3036 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04003037 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003038 {
3039 context->handleError(InvalidOperation() << "Index buffer is mapped.");
3040 return false;
3041 }
Jamie Madill250d33f2014-06-06 17:09:03 -04003042 }
3043
He Yunchaoced53ae2016-11-29 15:00:51 +08003044 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003045 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003046
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003047 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3048
3049 if (context->getExtensions().webglCompatibility)
3050 {
3051 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3052 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3053 {
3054 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3055 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3056 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003057 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003058 return false;
3059 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003060
3061 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3062 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3063 // error is generated.
3064 if (reinterpret_cast<intptr_t>(indices) < 0)
3065 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003066 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003067 return false;
3068 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003069 }
3070
3071 if (context->getExtensions().webglCompatibility ||
3072 !context->getGLState().areClientArraysEnabled())
3073 {
Brandon Jones2a018152018-06-08 15:59:26 -07003074 if (!elementArrayBuffer)
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003075 {
3076 // [WebGL 1.0] Section 6.2 No Client Side Arrays
Brandon Jones2a018152018-06-08 15:59:26 -07003077 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3078 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003079 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003080 return false;
3081 }
3082 }
3083
Jamie Madill9fdaa492018-02-16 10:52:11 -05003084 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003085 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003086 // This is an application error that would normally result in a crash, but we catch it and
3087 // return an error
3088 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3089 return false;
3090 }
3091
3092 if (count > 0 && elementArrayBuffer)
3093 {
3094 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3095 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3096 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3097 constexpr uint64_t kMaxTypeSize = 8;
3098 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3099 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3100 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3101
3102 uint64_t typeSize = typeBytes;
3103 uint64_t elementCount = static_cast<uint64_t>(count);
3104 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3105
3106 // Doing the multiplication here is overflow-safe
3107 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3108
3109 // The offset can be any value, check for overflows
3110 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3111 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003112 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003113 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3114 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003115 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003116
3117 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3118 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003119 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003120 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3121 return false;
3122 }
3123
3124 ASSERT(isPow2(typeSize) && typeSize > 0);
3125 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3126 {
3127 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003128 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003129 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003130
3131 if (context->getExtensions().webglCompatibility &&
3132 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3133 {
3134 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3135 ElementArrayBufferBoundForTransformFeedback);
3136 return false;
3137 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003138 }
3139
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003140 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003141 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003142 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
3143 // access is enabled.
3144 if (!ValidateDrawAttribs(context, primcount, 0, 1))
3145 {
3146 return false;
3147 }
3148 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003149 else if (count == 0)
3150 {
3151 // ValidateDrawAttribs also does some extra validation that is independent of the vertex
3152 // count.
3153 if (!ValidateDrawAttribs(context, 0, 0, 0))
3154 {
3155 return false;
3156 }
3157 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003158 else
3159 {
3160 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003161 const DrawCallParams &params = context->getParams<DrawCallParams>();
3162 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3163 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003164
3165 // If we use an index greater than our maximum supported index range, return an error.
3166 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3167 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003168 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003169 {
3170 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3171 return false;
3172 }
3173
Jamie Madill6f5444d2018-03-14 10:08:11 -04003174 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end),
3175 static_cast<GLint>(indexRange.vertexCount())))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003176 {
3177 return false;
3178 }
3179
3180 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003181 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003182 }
3183
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003184 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003185}
3186
Jamie Madill5b772312018-03-08 20:28:32 -05003187bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003188 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003189 GLsizei count,
3190 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003191 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003192 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003193{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003194 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003195}
3196
Geoff Lang3edfe032015-09-04 16:38:24 -04003197bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003198 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003199 GLsizei count,
3200 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003201 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003202 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003203{
Geoff Lang63c5a592017-09-27 14:08:16 -04003204 if (!context->getExtensions().instancedArrays)
3205 {
3206 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3207 return false;
3208 }
3209
Corentin Wallez170efbf2017-05-02 13:45:01 -04003210 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003211 {
3212 return false;
3213 }
3214
Corentin Wallez0dc97812017-06-22 14:38:44 -04003215 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003216}
3217
He Yunchaoced53ae2016-11-29 15:00:51 +08003218bool ValidateFramebufferTextureBase(Context *context,
3219 GLenum target,
3220 GLenum attachment,
3221 GLuint texture,
3222 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003223{
Geoff Lange8afa902017-09-27 15:00:43 -04003224 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003225 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003226 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003227 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003228 }
3229
3230 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003231 {
3232 return false;
3233 }
3234
Jamie Madill55ec3b12014-07-03 10:38:57 -04003235 if (texture != 0)
3236 {
3237 gl::Texture *tex = context->getTexture(texture);
3238
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003239 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003240 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003241 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003242 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003243 }
3244
3245 if (level < 0)
3246 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003247 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003248 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003249 }
3250 }
3251
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003252 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003253 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003254
Jamie Madill84115c92015-04-23 15:00:07 -04003255 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003256 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003257 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003258 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003259 }
3260
3261 return true;
3262}
3263
Geoff Langb1196682014-07-23 13:47:29 -04003264bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003265{
3266 if (program == 0)
3267 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003268 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003269 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003270 }
3271
Dian Xiang769769a2015-09-09 15:20:08 -07003272 gl::Program *programObject = GetValidProgram(context, program);
3273 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003274 {
3275 return false;
3276 }
3277
Jamie Madill0063c512014-08-25 15:47:53 -04003278 if (!programObject || !programObject->isLinked())
3279 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003280 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003281 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003282 }
3283
Geoff Lang7dd2e102014-11-10 15:19:26 -05003284 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003285 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003286 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003287 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003288 }
3289
Jamie Madill0063c512014-08-25 15:47:53 -04003290 return true;
3291}
3292
Geoff Langf41d0ee2016-10-07 13:04:23 -04003293static bool ValidateSizedGetUniform(Context *context,
3294 GLuint program,
3295 GLint location,
3296 GLsizei bufSize,
3297 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003298{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003299 if (length)
3300 {
3301 *length = 0;
3302 }
3303
Jamie Madill78f41802014-08-25 15:47:55 -04003304 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003305 {
Jamie Madill78f41802014-08-25 15:47:55 -04003306 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003307 }
3308
Geoff Langf41d0ee2016-10-07 13:04:23 -04003309 if (bufSize < 0)
3310 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003311 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003312 return false;
3313 }
3314
Jamie Madilla502c742014-08-28 17:19:13 -04003315 gl::Program *programObject = context->getProgram(program);
3316 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003317
Jamie Madill78f41802014-08-25 15:47:55 -04003318 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003319 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003320 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003321 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003322 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003323 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003324 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003325 }
3326
Geoff Langf41d0ee2016-10-07 13:04:23 -04003327 if (length)
3328 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003329 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003330 }
3331
Jamie Madill0063c512014-08-25 15:47:53 -04003332 return true;
3333}
3334
He Yunchaoced53ae2016-11-29 15:00:51 +08003335bool ValidateGetnUniformfvEXT(Context *context,
3336 GLuint program,
3337 GLint location,
3338 GLsizei bufSize,
3339 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003340{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003341 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003342}
3343
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003344bool ValidateGetnUniformfvRobustANGLE(Context *context,
3345 GLuint program,
3346 GLint location,
3347 GLsizei bufSize,
3348 GLsizei *length,
3349 GLfloat *params)
3350{
3351 UNIMPLEMENTED();
3352 return false;
3353}
3354
He Yunchaoced53ae2016-11-29 15:00:51 +08003355bool ValidateGetnUniformivEXT(Context *context,
3356 GLuint program,
3357 GLint location,
3358 GLsizei bufSize,
3359 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003360{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003361 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3362}
3363
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003364bool ValidateGetnUniformivRobustANGLE(Context *context,
3365 GLuint program,
3366 GLint location,
3367 GLsizei bufSize,
3368 GLsizei *length,
3369 GLint *params)
3370{
3371 UNIMPLEMENTED();
3372 return false;
3373}
3374
3375bool ValidateGetnUniformuivRobustANGLE(Context *context,
3376 GLuint program,
3377 GLint location,
3378 GLsizei bufSize,
3379 GLsizei *length,
3380 GLuint *params)
3381{
3382 UNIMPLEMENTED();
3383 return false;
3384}
3385
Geoff Langf41d0ee2016-10-07 13:04:23 -04003386bool ValidateGetUniformfvRobustANGLE(Context *context,
3387 GLuint program,
3388 GLint location,
3389 GLsizei bufSize,
3390 GLsizei *length,
3391 GLfloat *params)
3392{
3393 if (!ValidateRobustEntryPoint(context, bufSize))
3394 {
3395 return false;
3396 }
3397
Brandon Jonesd1049182018-03-28 10:02:20 -07003398 GLsizei writeLength = 0;
3399
Geoff Langf41d0ee2016-10-07 13:04:23 -04003400 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003401 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3402 {
3403 return false;
3404 }
3405
3406 SetRobustLengthParam(length, writeLength);
3407
3408 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003409}
3410
3411bool ValidateGetUniformivRobustANGLE(Context *context,
3412 GLuint program,
3413 GLint location,
3414 GLsizei bufSize,
3415 GLsizei *length,
3416 GLint *params)
3417{
3418 if (!ValidateRobustEntryPoint(context, bufSize))
3419 {
3420 return false;
3421 }
3422
Brandon Jonesd1049182018-03-28 10:02:20 -07003423 GLsizei writeLength = 0;
3424
Geoff Langf41d0ee2016-10-07 13:04:23 -04003425 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003426 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3427 {
3428 return false;
3429 }
3430
3431 SetRobustLengthParam(length, writeLength);
3432
3433 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003434}
3435
3436bool ValidateGetUniformuivRobustANGLE(Context *context,
3437 GLuint program,
3438 GLint location,
3439 GLsizei bufSize,
3440 GLsizei *length,
3441 GLuint *params)
3442{
3443 if (!ValidateRobustEntryPoint(context, bufSize))
3444 {
3445 return false;
3446 }
3447
3448 if (context->getClientMajorVersion() < 3)
3449 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003450 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003451 return false;
3452 }
3453
Brandon Jonesd1049182018-03-28 10:02:20 -07003454 GLsizei writeLength = 0;
3455
Geoff Langf41d0ee2016-10-07 13:04:23 -04003456 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003457 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3458 {
3459 return false;
3460 }
3461
3462 SetRobustLengthParam(length, writeLength);
3463
3464 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003465}
3466
He Yunchaoced53ae2016-11-29 15:00:51 +08003467bool ValidateDiscardFramebufferBase(Context *context,
3468 GLenum target,
3469 GLsizei numAttachments,
3470 const GLenum *attachments,
3471 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003472{
3473 if (numAttachments < 0)
3474 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003475 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003476 return false;
3477 }
3478
3479 for (GLsizei i = 0; i < numAttachments; ++i)
3480 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003481 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003482 {
3483 if (defaultFramebuffer)
3484 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003485 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003486 return false;
3487 }
3488
3489 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3490 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003491 context->handleError(InvalidOperation() << "Requested color attachment is "
3492 "greater than the maximum supported "
3493 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003494 return false;
3495 }
3496 }
3497 else
3498 {
3499 switch (attachments[i])
3500 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003501 case GL_DEPTH_ATTACHMENT:
3502 case GL_STENCIL_ATTACHMENT:
3503 case GL_DEPTH_STENCIL_ATTACHMENT:
3504 if (defaultFramebuffer)
3505 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003506 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3507 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003508 return false;
3509 }
3510 break;
3511 case GL_COLOR:
3512 case GL_DEPTH:
3513 case GL_STENCIL:
3514 if (!defaultFramebuffer)
3515 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003516 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3517 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003518 return false;
3519 }
3520 break;
3521 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003522 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003523 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003524 }
3525 }
3526 }
3527
3528 return true;
3529}
3530
Austin Kinross6ee1e782015-05-29 17:05:37 -07003531bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3532{
Jamie Madill007530e2017-12-28 14:27:04 -05003533 if (!context->getExtensions().debugMarker)
3534 {
3535 // The debug marker calls should not set error state
3536 // However, it seems reasonable to set an error state if the extension is not enabled
3537 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3538 return false;
3539 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003540
Jamie Madill007530e2017-12-28 14:27:04 -05003541 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003542 if (length < 0)
3543 {
3544 return false;
3545 }
3546
3547 if (marker == nullptr)
3548 {
3549 return false;
3550 }
3551
3552 return true;
3553}
3554
3555bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3556{
Jamie Madill007530e2017-12-28 14:27:04 -05003557 if (!context->getExtensions().debugMarker)
3558 {
3559 // The debug marker calls should not set error state
3560 // However, it seems reasonable to set an error state if the extension is not enabled
3561 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3562 return false;
3563 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003564
Jamie Madill007530e2017-12-28 14:27:04 -05003565 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003566 if (length < 0)
3567 {
3568 return false;
3569 }
3570
3571 if (length > 0 && marker == nullptr)
3572 {
3573 return false;
3574 }
3575
3576 return true;
3577}
3578
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003579bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003580{
Geoff Langa8406172015-07-21 16:53:39 -04003581 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3582 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003583 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003584 return false;
3585 }
3586
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003587 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003588 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003589 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003590 if (!context->getExtensions().eglImage)
3591 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003592 context->handleError(InvalidEnum()
3593 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003594 }
3595 break;
3596
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003597 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003598 if (!context->getExtensions().eglImageExternal)
3599 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003600 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3601 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003602 }
Geoff Langa8406172015-07-21 16:53:39 -04003603 break;
3604
3605 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003606 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003607 return false;
3608 }
3609
Rafael Cintron05a449a2018-06-20 18:08:04 -07003610 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003611
Jamie Madill61e16b42017-06-19 11:13:23 -04003612 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003613 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003614 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003615 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003616 return false;
3617 }
3618
Jamie Madill007530e2017-12-28 14:27:04 -05003619 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003620 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003621 context->handleError(InvalidOperation()
3622 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003623 return false;
3624 }
3625
Geoff Langca271392017-04-05 12:30:00 -04003626 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003627 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003628 if (!textureCaps.texturable)
3629 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003630 context->handleError(InvalidOperation()
3631 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003632 return false;
3633 }
3634
Geoff Langdcab33b2015-07-21 13:03:16 -04003635 return true;
3636}
3637
3638bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003639 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003640 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003641{
Geoff Langa8406172015-07-21 16:53:39 -04003642 if (!context->getExtensions().eglImage)
3643 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003644 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003645 return false;
3646 }
3647
3648 switch (target)
3649 {
3650 case GL_RENDERBUFFER:
3651 break;
3652
3653 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003654 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003655 return false;
3656 }
3657
Rafael Cintron05a449a2018-06-20 18:08:04 -07003658 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003659
Jamie Madill61e16b42017-06-19 11:13:23 -04003660 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003661 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003662 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003663 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003664 return false;
3665 }
3666
Geoff Langca271392017-04-05 12:30:00 -04003667 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003668 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04003669 if (!textureCaps.renderbuffer)
Geoff Langa8406172015-07-21 16:53:39 -04003670 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003671 context->handleError(InvalidOperation()
3672 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003673 return false;
3674 }
3675
Geoff Langdcab33b2015-07-21 13:03:16 -04003676 return true;
3677}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003678
3679bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3680{
Geoff Lang36167ab2015-12-07 10:27:14 -05003681 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003682 {
3683 // The default VAO should always exist
3684 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003685 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003686 return false;
3687 }
3688
3689 return true;
3690}
3691
Geoff Langc5629752015-12-07 16:29:04 -05003692bool ValidateProgramBinaryBase(Context *context,
3693 GLuint program,
3694 GLenum binaryFormat,
3695 const void *binary,
3696 GLint length)
3697{
3698 Program *programObject = GetValidProgram(context, program);
3699 if (programObject == nullptr)
3700 {
3701 return false;
3702 }
3703
3704 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3705 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3706 programBinaryFormats.end())
3707 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003708 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003709 return false;
3710 }
3711
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003712 if (context->hasActiveTransformFeedback(program))
3713 {
3714 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003715 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3716 "is associated with an active transform "
3717 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003718 return false;
3719 }
3720
Geoff Langc5629752015-12-07 16:29:04 -05003721 return true;
3722}
3723
3724bool ValidateGetProgramBinaryBase(Context *context,
3725 GLuint program,
3726 GLsizei bufSize,
3727 GLsizei *length,
3728 GLenum *binaryFormat,
3729 void *binary)
3730{
3731 Program *programObject = GetValidProgram(context, program);
3732 if (programObject == nullptr)
3733 {
3734 return false;
3735 }
3736
3737 if (!programObject->isLinked())
3738 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003739 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003740 return false;
3741 }
3742
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003743 if (context->getCaps().programBinaryFormats.empty())
3744 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003745 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003746 return false;
3747 }
3748
Geoff Langc5629752015-12-07 16:29:04 -05003749 return true;
3750}
Jamie Madillc29968b2016-01-20 11:17:23 -05003751
Jamie Madill5b772312018-03-08 20:28:32 -05003752bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003753{
3754 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003755 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003756 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003757 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3758 return false;
3759 }
3760 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3761 {
3762 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003763 return false;
3764 }
3765
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003766 ASSERT(context->getGLState().getDrawFramebuffer());
3767 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003768 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3769
3770 // This should come first before the check for the default frame buffer
3771 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3772 // rather than INVALID_OPERATION
3773 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3774 {
3775 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3776
3777 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003778 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3779 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003780 {
3781 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003782 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3783 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3784 // 3.1 is still a bit ambiguous about the error, but future specs are
3785 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003786 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003787 return false;
3788 }
3789 else if (bufs[colorAttachment] >= maxColorAttachment)
3790 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003791 context->handleError(InvalidOperation()
3792 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003793 return false;
3794 }
3795 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3796 frameBufferId != 0)
3797 {
3798 // INVALID_OPERATION-GL is bound to buffer and ith argument
3799 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003800 context->handleError(InvalidOperation()
3801 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003802 return false;
3803 }
3804 }
3805
3806 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3807 // and n is not 1 or bufs is bound to value other than BACK and NONE
3808 if (frameBufferId == 0)
3809 {
3810 if (n != 1)
3811 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003812 context->handleError(InvalidOperation()
3813 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003814 return false;
3815 }
3816
3817 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3818 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003819 context->handleError(
3820 InvalidOperation()
3821 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003822 return false;
3823 }
3824 }
3825
3826 return true;
3827}
3828
Geoff Lang496c02d2016-10-20 11:38:11 -07003829bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003830 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003831 GLenum pname,
3832 GLsizei *length,
3833 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003834{
Geoff Lang496c02d2016-10-20 11:38:11 -07003835 if (length)
3836 {
3837 *length = 0;
3838 }
3839
3840 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3841 {
3842 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003843 InvalidOperation()
3844 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003845 return false;
3846 }
3847
Corentin Walleze4477002017-12-01 14:39:58 -05003848 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003849 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003850 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003851 return false;
3852 }
3853
Geoff Lang496c02d2016-10-20 11:38:11 -07003854 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003855 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003856 case GL_BUFFER_MAP_POINTER:
3857 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003858
Geoff Lang496c02d2016-10-20 11:38:11 -07003859 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003860 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003861 return false;
3862 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003863
3864 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3865 // target bound to zero generate an INVALID_OPERATION error."
3866 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003867 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003868 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003869 context->handleError(InvalidOperation()
3870 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003871 return false;
3872 }
3873
Geoff Lang496c02d2016-10-20 11:38:11 -07003874 if (length)
3875 {
3876 *length = 1;
3877 }
3878
Olli Etuaho4f667482016-03-30 15:56:35 +03003879 return true;
3880}
3881
Corentin Wallez336129f2017-10-17 15:55:40 -04003882bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003883{
Corentin Walleze4477002017-12-01 14:39:58 -05003884 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003885 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003886 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003887 return false;
3888 }
3889
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003890 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003891
3892 if (buffer == nullptr || !buffer->isMapped())
3893 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003894 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003895 return false;
3896 }
3897
3898 return true;
3899}
3900
3901bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003902 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003903 GLintptr offset,
3904 GLsizeiptr length,
3905 GLbitfield access)
3906{
Corentin Walleze4477002017-12-01 14:39:58 -05003907 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003908 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003909 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003910 return false;
3911 }
3912
Brandon Jones6cad5662017-06-14 13:25:13 -07003913 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003914 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003915 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3916 return false;
3917 }
3918
3919 if (length < 0)
3920 {
3921 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003922 return false;
3923 }
3924
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003925 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003926
3927 if (!buffer)
3928 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003929 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003930 return false;
3931 }
3932
3933 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003934 CheckedNumeric<size_t> checkedOffset(offset);
3935 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003936
Jamie Madille2e406c2016-06-02 13:04:10 -04003937 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003938 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003939 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003940 return false;
3941 }
3942
3943 // Check for invalid bits in the mask
3944 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3945 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3946 GL_MAP_UNSYNCHRONIZED_BIT;
3947
3948 if (access & ~(allAccessBits))
3949 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003950 context->handleError(InvalidValue()
3951 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003952 return false;
3953 }
3954
3955 if (length == 0)
3956 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003957 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003958 return false;
3959 }
3960
3961 if (buffer->isMapped())
3962 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003963 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003964 return false;
3965 }
3966
3967 // Check for invalid bit combinations
3968 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3969 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003970 context->handleError(InvalidOperation()
3971 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003972 return false;
3973 }
3974
3975 GLbitfield writeOnlyBits =
3976 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3977
3978 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3979 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003980 context->handleError(InvalidOperation()
3981 << "Invalid access bits when mapping buffer for reading: 0x"
3982 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003983 return false;
3984 }
3985
3986 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3987 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003988 context->handleError(
3989 InvalidOperation()
3990 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003991 return false;
3992 }
Geoff Lang79f71042017-08-14 16:43:43 -04003993
3994 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003995}
3996
3997bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003998 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003999 GLintptr offset,
4000 GLsizeiptr length)
4001{
Brandon Jones6cad5662017-06-14 13:25:13 -07004002 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03004003 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004004 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
4005 return false;
4006 }
4007
4008 if (length < 0)
4009 {
4010 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03004011 return false;
4012 }
4013
Corentin Walleze4477002017-12-01 14:39:58 -05004014 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03004015 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004016 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03004017 return false;
4018 }
4019
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004020 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004021
4022 if (buffer == nullptr)
4023 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004024 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004025 return false;
4026 }
4027
4028 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4029 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004030 context->handleError(InvalidOperation()
4031 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004032 return false;
4033 }
4034
4035 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004036 CheckedNumeric<size_t> checkedOffset(offset);
4037 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004038
Jamie Madille2e406c2016-06-02 13:04:10 -04004039 if (!checkedSize.IsValid() ||
4040 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004041 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004042 context->handleError(InvalidValue()
4043 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004044 return false;
4045 }
4046
4047 return true;
4048}
4049
Olli Etuaho41997e72016-03-10 13:38:39 +02004050bool ValidateGenOrDelete(Context *context, GLint n)
4051{
4052 if (n < 0)
4053 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004054 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02004055 return false;
4056 }
4057 return true;
4058}
4059
Jamie Madill5b772312018-03-08 20:28:32 -05004060bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04004061{
4062 if (!context->getExtensions().robustClientMemory)
4063 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004064 context->handleError(InvalidOperation()
4065 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004066 return false;
4067 }
4068
4069 if (bufSize < 0)
4070 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004071 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004072 return false;
4073 }
4074
4075 return true;
4076}
4077
Jamie Madill5b772312018-03-08 20:28:32 -05004078bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004079{
4080 if (bufSize < numParams)
4081 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004082 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4083 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004084 return false;
4085 }
4086
4087 return true;
4088}
4089
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004090bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004091 GLenum target,
4092 GLenum attachment,
4093 GLenum pname,
4094 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004095{
Geoff Lange8afa902017-09-27 15:00:43 -04004096 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004097 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004098 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004099 return false;
4100 }
4101
4102 int clientVersion = context->getClientMajorVersion();
4103
4104 switch (pname)
4105 {
4106 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4107 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4108 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4109 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4110 break;
4111
Martin Radeve5285d22017-07-14 16:23:53 +03004112 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4113 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4114 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4115 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4116 if (clientVersion < 3 || !context->getExtensions().multiview)
4117 {
4118 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4119 return false;
4120 }
4121 break;
4122
Geoff Langff5b2d52016-09-07 11:32:23 -04004123 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4124 if (clientVersion < 3 && !context->getExtensions().sRGB)
4125 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004126 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004127 return false;
4128 }
4129 break;
4130
4131 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4132 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4133 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4134 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4135 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4136 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4137 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4138 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4139 if (clientVersion < 3)
4140 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004141 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004142 return false;
4143 }
4144 break;
4145
Jiawei Shaoa8802472018-05-28 11:17:47 +08004146 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4147 if (!context->getExtensions().geometryShader)
4148 {
4149 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4150 return false;
4151 }
4152 break;
4153
Geoff Langff5b2d52016-09-07 11:32:23 -04004154 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004155 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004156 return false;
4157 }
4158
4159 // Determine if the attachment is a valid enum
4160 switch (attachment)
4161 {
4162 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004163 case GL_DEPTH:
4164 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004165 if (clientVersion < 3)
4166 {
Geoff Langfa125c92017-10-24 13:01:46 -04004167 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004168 return false;
4169 }
4170 break;
4171
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004172 case GL_DEPTH_STENCIL_ATTACHMENT:
4173 if (clientVersion < 3 && !context->isWebGL1())
4174 {
4175 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4176 return false;
4177 }
4178 break;
4179
Geoff Langfa125c92017-10-24 13:01:46 -04004180 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004181 case GL_DEPTH_ATTACHMENT:
4182 case GL_STENCIL_ATTACHMENT:
4183 break;
4184
4185 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004186 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4187 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004188 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4189 {
Geoff Langfa125c92017-10-24 13:01:46 -04004190 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004191 return false;
4192 }
4193 break;
4194 }
4195
4196 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4197 ASSERT(framebuffer);
4198
4199 if (framebuffer->id() == 0)
4200 {
4201 if (clientVersion < 3)
4202 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004203 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004204 return false;
4205 }
4206
4207 switch (attachment)
4208 {
4209 case GL_BACK:
4210 case GL_DEPTH:
4211 case GL_STENCIL:
4212 break;
4213
4214 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004215 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004216 return false;
4217 }
4218 }
4219 else
4220 {
4221 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4222 {
4223 // Valid attachment query
4224 }
4225 else
4226 {
4227 switch (attachment)
4228 {
4229 case GL_DEPTH_ATTACHMENT:
4230 case GL_STENCIL_ATTACHMENT:
4231 break;
4232
4233 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004234 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004235 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004236 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004237 return false;
4238 }
4239 break;
4240
4241 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004242 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004243 return false;
4244 }
4245 }
4246 }
4247
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004248 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004249 if (attachmentObject)
4250 {
4251 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4252 attachmentObject->type() == GL_TEXTURE ||
4253 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4254
4255 switch (pname)
4256 {
4257 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4258 if (attachmentObject->type() != GL_RENDERBUFFER &&
4259 attachmentObject->type() != GL_TEXTURE)
4260 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004261 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004262 return false;
4263 }
4264 break;
4265
4266 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4267 if (attachmentObject->type() != GL_TEXTURE)
4268 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004269 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004270 return false;
4271 }
4272 break;
4273
4274 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4275 if (attachmentObject->type() != GL_TEXTURE)
4276 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004277 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004278 return false;
4279 }
4280 break;
4281
4282 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4283 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4284 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004285 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004286 return false;
4287 }
4288 break;
4289
4290 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4291 if (attachmentObject->type() != GL_TEXTURE)
4292 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004293 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004294 return false;
4295 }
4296 break;
4297
4298 default:
4299 break;
4300 }
4301 }
4302 else
4303 {
4304 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4305 // is NONE, then querying any other pname will generate INVALID_ENUM.
4306
4307 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4308 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4309 // INVALID_OPERATION for all other pnames
4310
4311 switch (pname)
4312 {
4313 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4314 break;
4315
4316 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4317 if (clientVersion < 3)
4318 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004319 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004320 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004321 return false;
4322 }
4323 break;
4324
4325 default:
4326 if (clientVersion < 3)
4327 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004328 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004329 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004330 return false;
4331 }
4332 else
4333 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004334 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004335 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004336 return false;
4337 }
4338 }
4339 }
4340
Martin Radeve5285d22017-07-14 16:23:53 +03004341 if (numParams)
4342 {
4343 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4344 {
4345 // Only when the viewport offsets are queried we can have a varying number of output
4346 // parameters.
4347 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4348 *numParams = numViews * 2;
4349 }
4350 else
4351 {
4352 // For all other queries we can have only one output parameter.
4353 *numParams = 1;
4354 }
4355 }
4356
Geoff Langff5b2d52016-09-07 11:32:23 -04004357 return true;
4358}
4359
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004360bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004361 GLenum target,
4362 GLenum attachment,
4363 GLenum pname,
4364 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004365 GLsizei *length,
4366 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004367{
4368 if (!ValidateRobustEntryPoint(context, bufSize))
4369 {
4370 return false;
4371 }
4372
Brandon Jonesd1049182018-03-28 10:02:20 -07004373 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004374 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004375 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004376 {
4377 return false;
4378 }
4379
Brandon Jonesd1049182018-03-28 10:02:20 -07004380 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004381 {
4382 return false;
4383 }
4384
Brandon Jonesd1049182018-03-28 10:02:20 -07004385 SetRobustLengthParam(length, numParams);
4386
Geoff Langff5b2d52016-09-07 11:32:23 -04004387 return true;
4388}
4389
Jamie Madill5b772312018-03-08 20:28:32 -05004390bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004391 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004392 GLenum pname,
4393 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004394 GLsizei *length,
4395 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004396{
4397 if (!ValidateRobustEntryPoint(context, bufSize))
4398 {
4399 return false;
4400 }
4401
Brandon Jonesd1049182018-03-28 10:02:20 -07004402 GLsizei numParams = 0;
4403
4404 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004405 {
4406 return false;
4407 }
4408
Brandon Jonesd1049182018-03-28 10:02:20 -07004409 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004410 {
4411 return false;
4412 }
4413
Brandon Jonesd1049182018-03-28 10:02:20 -07004414 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004415 return true;
4416}
4417
Jamie Madill5b772312018-03-08 20:28:32 -05004418bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004419 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004420 GLenum pname,
4421 GLsizei bufSize,
4422 GLsizei *length,
4423 GLint64 *params)
4424{
Brandon Jonesd1049182018-03-28 10:02:20 -07004425 GLsizei numParams = 0;
4426
Geoff Langebebe1c2016-10-14 12:01:31 -04004427 if (!ValidateRobustEntryPoint(context, bufSize))
4428 {
4429 return false;
4430 }
4431
Brandon Jonesd1049182018-03-28 10:02:20 -07004432 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004433 {
4434 return false;
4435 }
4436
Brandon Jonesd1049182018-03-28 10:02:20 -07004437 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004438 {
4439 return false;
4440 }
4441
Brandon Jonesd1049182018-03-28 10:02:20 -07004442 SetRobustLengthParam(length, numParams);
4443
Geoff Langff5b2d52016-09-07 11:32:23 -04004444 return true;
4445}
4446
Jamie Madill5b772312018-03-08 20:28:32 -05004447bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004448{
4449 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004450 if (numParams)
4451 {
4452 *numParams = 1;
4453 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004454
4455 Program *programObject = GetValidProgram(context, program);
4456 if (!programObject)
4457 {
4458 return false;
4459 }
4460
4461 switch (pname)
4462 {
4463 case GL_DELETE_STATUS:
4464 case GL_LINK_STATUS:
4465 case GL_VALIDATE_STATUS:
4466 case GL_INFO_LOG_LENGTH:
4467 case GL_ATTACHED_SHADERS:
4468 case GL_ACTIVE_ATTRIBUTES:
4469 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4470 case GL_ACTIVE_UNIFORMS:
4471 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4472 break;
4473
4474 case GL_PROGRAM_BINARY_LENGTH:
4475 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4476 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004477 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4478 "requires GL_OES_get_program_binary or "
4479 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004480 return false;
4481 }
4482 break;
4483
4484 case GL_ACTIVE_UNIFORM_BLOCKS:
4485 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4486 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4487 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4488 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4489 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4490 if (context->getClientMajorVersion() < 3)
4491 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004492 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004493 return false;
4494 }
4495 break;
4496
Yunchao He61afff12017-03-14 15:34:03 +08004497 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004498 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004499 if (context->getClientVersion() < Version(3, 1))
4500 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004501 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004502 return false;
4503 }
4504 break;
4505
Jiawei Shao6ae51612018-02-23 14:03:25 +08004506 case GL_COMPUTE_WORK_GROUP_SIZE:
4507 if (context->getClientVersion() < Version(3, 1))
4508 {
4509 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4510 return false;
4511 }
4512
4513 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4514 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4515 // program which has not been linked successfully, or which does not contain objects to
4516 // form a compute shader.
4517 if (!programObject->isLinked())
4518 {
4519 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4520 return false;
4521 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004522 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004523 {
4524 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4525 return false;
4526 }
4527 break;
4528
Jiawei Shao447bfac2018-03-14 14:23:40 +08004529 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4530 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4531 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4532 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4533 if (!context->getExtensions().geometryShader)
4534 {
4535 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4536 return false;
4537 }
4538
4539 // [EXT_geometry_shader] Chapter 7.12
4540 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4541 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4542 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4543 // successfully, or which does not contain objects to form a geometry shader.
4544 if (!programObject->isLinked())
4545 {
4546 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4547 return false;
4548 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004549 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004550 {
4551 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4552 return false;
4553 }
4554 break;
4555
Geoff Langff5b2d52016-09-07 11:32:23 -04004556 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004557 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004558 return false;
4559 }
4560
4561 return true;
4562}
4563
4564bool ValidateGetProgramivRobustANGLE(Context *context,
4565 GLuint program,
4566 GLenum pname,
4567 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004568 GLsizei *length,
4569 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004570{
4571 if (!ValidateRobustEntryPoint(context, bufSize))
4572 {
4573 return false;
4574 }
4575
Brandon Jonesd1049182018-03-28 10:02:20 -07004576 GLsizei numParams = 0;
4577
4578 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004579 {
4580 return false;
4581 }
4582
Brandon Jonesd1049182018-03-28 10:02:20 -07004583 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004584 {
4585 return false;
4586 }
4587
Brandon Jonesd1049182018-03-28 10:02:20 -07004588 SetRobustLengthParam(length, numParams);
4589
Geoff Langff5b2d52016-09-07 11:32:23 -04004590 return true;
4591}
4592
Geoff Lang740d9022016-10-07 11:20:52 -04004593bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4594 GLenum target,
4595 GLenum pname,
4596 GLsizei bufSize,
4597 GLsizei *length,
4598 GLint *params)
4599{
4600 if (!ValidateRobustEntryPoint(context, bufSize))
4601 {
4602 return false;
4603 }
4604
Brandon Jonesd1049182018-03-28 10:02:20 -07004605 GLsizei numParams = 0;
4606
4607 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004608 {
4609 return false;
4610 }
4611
Brandon Jonesd1049182018-03-28 10:02:20 -07004612 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004613 {
4614 return false;
4615 }
4616
Brandon Jonesd1049182018-03-28 10:02:20 -07004617 SetRobustLengthParam(length, numParams);
4618
Geoff Lang740d9022016-10-07 11:20:52 -04004619 return true;
4620}
4621
Geoff Langd7d0ed32016-10-07 11:33:51 -04004622bool ValidateGetShaderivRobustANGLE(Context *context,
4623 GLuint shader,
4624 GLenum pname,
4625 GLsizei bufSize,
4626 GLsizei *length,
4627 GLint *params)
4628{
4629 if (!ValidateRobustEntryPoint(context, bufSize))
4630 {
4631 return false;
4632 }
4633
Brandon Jonesd1049182018-03-28 10:02:20 -07004634 GLsizei numParams = 0;
4635
4636 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004637 {
4638 return false;
4639 }
4640
Brandon Jonesd1049182018-03-28 10:02:20 -07004641 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004642 {
4643 return false;
4644 }
4645
Brandon Jonesd1049182018-03-28 10:02:20 -07004646 SetRobustLengthParam(length, numParams);
4647
Geoff Langd7d0ed32016-10-07 11:33:51 -04004648 return true;
4649}
4650
Geoff Langc1984ed2016-10-07 12:41:00 -04004651bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004652 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004653 GLenum pname,
4654 GLsizei bufSize,
4655 GLsizei *length,
4656 GLfloat *params)
4657{
4658 if (!ValidateRobustEntryPoint(context, bufSize))
4659 {
4660 return false;
4661 }
4662
Brandon Jonesd1049182018-03-28 10:02:20 -07004663 GLsizei numParams = 0;
4664
4665 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004666 {
4667 return false;
4668 }
4669
Brandon Jonesd1049182018-03-28 10:02:20 -07004670 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004671 {
4672 return false;
4673 }
4674
Brandon Jonesd1049182018-03-28 10:02:20 -07004675 SetRobustLengthParam(length, numParams);
4676
Geoff Langc1984ed2016-10-07 12:41:00 -04004677 return true;
4678}
4679
Geoff Langc1984ed2016-10-07 12:41:00 -04004680bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004681 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004682 GLenum pname,
4683 GLsizei bufSize,
4684 GLsizei *length,
4685 GLint *params)
4686{
Brandon Jonesd1049182018-03-28 10:02:20 -07004687
Geoff Langc1984ed2016-10-07 12:41:00 -04004688 if (!ValidateRobustEntryPoint(context, bufSize))
4689 {
4690 return false;
4691 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004692 GLsizei numParams = 0;
4693 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004694 {
4695 return false;
4696 }
4697
Brandon Jonesd1049182018-03-28 10:02:20 -07004698 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004699 {
4700 return false;
4701 }
4702
Brandon Jonesd1049182018-03-28 10:02:20 -07004703 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004704 return true;
4705}
4706
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004707bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4708 TextureType target,
4709 GLenum pname,
4710 GLsizei bufSize,
4711 GLsizei *length,
4712 GLint *params)
4713{
4714 UNIMPLEMENTED();
4715 return false;
4716}
4717
4718bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4719 TextureType target,
4720 GLenum pname,
4721 GLsizei bufSize,
4722 GLsizei *length,
4723 GLuint *params)
4724{
4725 UNIMPLEMENTED();
4726 return false;
4727}
4728
Geoff Langc1984ed2016-10-07 12:41:00 -04004729bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004730 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004731 GLenum pname,
4732 GLsizei bufSize,
4733 const GLfloat *params)
4734{
4735 if (!ValidateRobustEntryPoint(context, bufSize))
4736 {
4737 return false;
4738 }
4739
4740 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4741}
4742
Geoff Langc1984ed2016-10-07 12:41:00 -04004743bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004744 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004745 GLenum pname,
4746 GLsizei bufSize,
4747 const GLint *params)
4748{
4749 if (!ValidateRobustEntryPoint(context, bufSize))
4750 {
4751 return false;
4752 }
4753
4754 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4755}
4756
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004757bool ValidateTexParameterIivRobustANGLE(Context *context,
4758 TextureType target,
4759 GLenum pname,
4760 GLsizei bufSize,
4761 const GLint *params)
4762{
4763 UNIMPLEMENTED();
4764 return false;
4765}
4766
4767bool ValidateTexParameterIuivRobustANGLE(Context *context,
4768 TextureType target,
4769 GLenum pname,
4770 GLsizei bufSize,
4771 const GLuint *params)
4772{
4773 UNIMPLEMENTED();
4774 return false;
4775}
4776
Geoff Langc1984ed2016-10-07 12:41:00 -04004777bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4778 GLuint sampler,
4779 GLenum pname,
4780 GLuint bufSize,
4781 GLsizei *length,
4782 GLfloat *params)
4783{
4784 if (!ValidateRobustEntryPoint(context, bufSize))
4785 {
4786 return false;
4787 }
4788
Brandon Jonesd1049182018-03-28 10:02:20 -07004789 GLsizei numParams = 0;
4790
4791 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004792 {
4793 return false;
4794 }
4795
Brandon Jonesd1049182018-03-28 10:02:20 -07004796 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004797 {
4798 return false;
4799 }
4800
Brandon Jonesd1049182018-03-28 10:02:20 -07004801 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004802 return true;
4803}
4804
Geoff Langc1984ed2016-10-07 12:41:00 -04004805bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4806 GLuint sampler,
4807 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004808 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004809 GLsizei *length,
4810 GLint *params)
4811{
4812 if (!ValidateRobustEntryPoint(context, bufSize))
4813 {
4814 return false;
4815 }
4816
Brandon Jonesd1049182018-03-28 10:02:20 -07004817 GLsizei numParams = 0;
4818
4819 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004820 {
4821 return false;
4822 }
4823
Brandon Jonesd1049182018-03-28 10:02:20 -07004824 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004825 {
4826 return false;
4827 }
4828
Brandon Jonesd1049182018-03-28 10:02:20 -07004829 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004830 return true;
4831}
4832
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004833bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4834 GLuint sampler,
4835 GLenum pname,
4836 GLsizei bufSize,
4837 GLsizei *length,
4838 GLint *params)
4839{
4840 UNIMPLEMENTED();
4841 return false;
4842}
4843
4844bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4845 GLuint sampler,
4846 GLenum pname,
4847 GLsizei bufSize,
4848 GLsizei *length,
4849 GLuint *params)
4850{
4851 UNIMPLEMENTED();
4852 return false;
4853}
4854
Geoff Langc1984ed2016-10-07 12:41:00 -04004855bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4856 GLuint sampler,
4857 GLenum pname,
4858 GLsizei bufSize,
4859 const GLfloat *params)
4860{
4861 if (!ValidateRobustEntryPoint(context, bufSize))
4862 {
4863 return false;
4864 }
4865
4866 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4867}
4868
Geoff Langc1984ed2016-10-07 12:41:00 -04004869bool ValidateSamplerParameterivRobustANGLE(Context *context,
4870 GLuint sampler,
4871 GLenum pname,
4872 GLsizei bufSize,
4873 const GLint *params)
4874{
4875 if (!ValidateRobustEntryPoint(context, bufSize))
4876 {
4877 return false;
4878 }
4879
4880 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4881}
4882
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004883bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4884 GLuint sampler,
4885 GLenum pname,
4886 GLsizei bufSize,
4887 const GLint *param)
4888{
4889 UNIMPLEMENTED();
4890 return false;
4891}
4892
4893bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4894 GLuint sampler,
4895 GLenum pname,
4896 GLsizei bufSize,
4897 const GLuint *param)
4898{
4899 UNIMPLEMENTED();
4900 return false;
4901}
4902
Geoff Lang0b031062016-10-13 14:30:04 -04004903bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4904 GLuint index,
4905 GLenum pname,
4906 GLsizei bufSize,
4907 GLsizei *length,
4908 GLfloat *params)
4909{
4910 if (!ValidateRobustEntryPoint(context, bufSize))
4911 {
4912 return false;
4913 }
4914
Brandon Jonesd1049182018-03-28 10:02:20 -07004915 GLsizei writeLength = 0;
4916
4917 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004918 {
4919 return false;
4920 }
4921
Brandon Jonesd1049182018-03-28 10:02:20 -07004922 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004923 {
4924 return false;
4925 }
4926
Brandon Jonesd1049182018-03-28 10:02:20 -07004927 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004928 return true;
4929}
4930
Geoff Lang0b031062016-10-13 14:30:04 -04004931bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4932 GLuint index,
4933 GLenum pname,
4934 GLsizei bufSize,
4935 GLsizei *length,
4936 GLint *params)
4937{
4938 if (!ValidateRobustEntryPoint(context, bufSize))
4939 {
4940 return false;
4941 }
4942
Brandon Jonesd1049182018-03-28 10:02:20 -07004943 GLsizei writeLength = 0;
4944
4945 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004946 {
4947 return false;
4948 }
4949
Brandon Jonesd1049182018-03-28 10:02:20 -07004950 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004951 {
4952 return false;
4953 }
4954
Brandon Jonesd1049182018-03-28 10:02:20 -07004955 SetRobustLengthParam(length, writeLength);
4956
Geoff Lang0b031062016-10-13 14:30:04 -04004957 return true;
4958}
4959
Geoff Lang0b031062016-10-13 14:30:04 -04004960bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4961 GLuint index,
4962 GLenum pname,
4963 GLsizei bufSize,
4964 GLsizei *length,
4965 void **pointer)
4966{
4967 if (!ValidateRobustEntryPoint(context, bufSize))
4968 {
4969 return false;
4970 }
4971
Brandon Jonesd1049182018-03-28 10:02:20 -07004972 GLsizei writeLength = 0;
4973
4974 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004975 {
4976 return false;
4977 }
4978
Brandon Jonesd1049182018-03-28 10:02:20 -07004979 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004980 {
4981 return false;
4982 }
4983
Brandon Jonesd1049182018-03-28 10:02:20 -07004984 SetRobustLengthParam(length, writeLength);
4985
Geoff Lang0b031062016-10-13 14:30:04 -04004986 return true;
4987}
4988
Geoff Lang0b031062016-10-13 14:30:04 -04004989bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4990 GLuint index,
4991 GLenum pname,
4992 GLsizei bufSize,
4993 GLsizei *length,
4994 GLint *params)
4995{
4996 if (!ValidateRobustEntryPoint(context, bufSize))
4997 {
4998 return false;
4999 }
5000
Brandon Jonesd1049182018-03-28 10:02:20 -07005001 GLsizei writeLength = 0;
5002
5003 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04005004 {
5005 return false;
5006 }
5007
Brandon Jonesd1049182018-03-28 10:02:20 -07005008 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04005009 {
5010 return false;
5011 }
5012
Brandon Jonesd1049182018-03-28 10:02:20 -07005013 SetRobustLengthParam(length, writeLength);
5014
Geoff Lang0b031062016-10-13 14:30:04 -04005015 return true;
5016}
5017
Geoff Lang0b031062016-10-13 14:30:04 -04005018bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5019 GLuint index,
5020 GLenum pname,
5021 GLsizei bufSize,
5022 GLsizei *length,
5023 GLuint *params)
5024{
5025 if (!ValidateRobustEntryPoint(context, bufSize))
5026 {
5027 return false;
5028 }
5029
Brandon Jonesd1049182018-03-28 10:02:20 -07005030 GLsizei writeLength = 0;
5031
5032 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04005033 {
5034 return false;
5035 }
5036
Brandon Jonesd1049182018-03-28 10:02:20 -07005037 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04005038 {
5039 return false;
5040 }
5041
Brandon Jonesd1049182018-03-28 10:02:20 -07005042 SetRobustLengthParam(length, writeLength);
5043
Geoff Lang0b031062016-10-13 14:30:04 -04005044 return true;
5045}
5046
Geoff Lang6899b872016-10-14 11:30:13 -04005047bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5048 GLuint program,
5049 GLuint uniformBlockIndex,
5050 GLenum pname,
5051 GLsizei bufSize,
5052 GLsizei *length,
5053 GLint *params)
5054{
5055 if (!ValidateRobustEntryPoint(context, bufSize))
5056 {
5057 return false;
5058 }
5059
Brandon Jonesd1049182018-03-28 10:02:20 -07005060 GLsizei writeLength = 0;
5061
5062 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
5063 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005064 {
5065 return false;
5066 }
5067
Brandon Jonesd1049182018-03-28 10:02:20 -07005068 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005069 {
5070 return false;
5071 }
5072
Brandon Jonesd1049182018-03-28 10:02:20 -07005073 SetRobustLengthParam(length, writeLength);
5074
Geoff Lang6899b872016-10-14 11:30:13 -04005075 return true;
5076}
5077
Brandon Jones416aaf92018-04-10 08:10:16 -07005078bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07005079 GLenum target,
5080 GLenum internalformat,
5081 GLenum pname,
5082 GLsizei bufSize,
5083 GLsizei *length,
5084 GLint *params)
5085{
5086 if (!ValidateRobustEntryPoint(context, bufSize))
5087 {
5088 return false;
5089 }
5090
Brandon Jonesd1049182018-03-28 10:02:20 -07005091 GLsizei numParams = 0;
5092
5093 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5094 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005095 {
5096 return false;
5097 }
5098
Brandon Jonesd1049182018-03-28 10:02:20 -07005099 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005100 {
5101 return false;
5102 }
5103
Brandon Jonesd1049182018-03-28 10:02:20 -07005104 SetRobustLengthParam(length, numParams);
5105
Geoff Lang0a9661f2016-10-20 10:59:20 -07005106 return true;
5107}
5108
Jamie Madill5b772312018-03-08 20:28:32 -05005109bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005110 GLuint attribIndex,
5111 GLint size,
5112 GLenum type,
5113 GLboolean pureInteger)
5114{
5115 const Caps &caps = context->getCaps();
5116 if (attribIndex >= caps.maxVertexAttributes)
5117 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005118 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005119 return false;
5120 }
5121
5122 if (size < 1 || size > 4)
5123 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005124 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005125 return false;
Shao80957d92017-02-20 21:25:59 +08005126 }
5127
5128 switch (type)
5129 {
5130 case GL_BYTE:
5131 case GL_UNSIGNED_BYTE:
5132 case GL_SHORT:
5133 case GL_UNSIGNED_SHORT:
5134 break;
5135
5136 case GL_INT:
5137 case GL_UNSIGNED_INT:
5138 if (context->getClientMajorVersion() < 3)
5139 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005140 context->handleError(InvalidEnum()
5141 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005142 return false;
5143 }
5144 break;
5145
5146 case GL_FIXED:
5147 case GL_FLOAT:
5148 if (pureInteger)
5149 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005150 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005151 return false;
5152 }
5153 break;
5154
5155 case GL_HALF_FLOAT:
5156 if (context->getClientMajorVersion() < 3)
5157 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005158 context->handleError(InvalidEnum()
5159 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005160 return false;
5161 }
5162 if (pureInteger)
5163 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005164 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005165 return false;
5166 }
5167 break;
5168
5169 case GL_INT_2_10_10_10_REV:
5170 case GL_UNSIGNED_INT_2_10_10_10_REV:
5171 if (context->getClientMajorVersion() < 3)
5172 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005173 context->handleError(InvalidEnum()
5174 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005175 return false;
5176 }
5177 if (pureInteger)
5178 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005179 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005180 return false;
5181 }
5182 if (size != 4)
5183 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005184 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5185 "UNSIGNED_INT_2_10_10_10_REV and "
5186 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005187 return false;
5188 }
5189 break;
5190
5191 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005192 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005193 return false;
5194 }
5195
5196 return true;
5197}
5198
Geoff Lang76e65652017-03-27 14:58:02 -04005199// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5200// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5201// specified clear value and the type of a buffer that is being cleared generates an
5202// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005203bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005204 GLint drawbuffer,
5205 const GLenum *validComponentTypes,
5206 size_t validComponentTypeCount)
5207{
5208 const FramebufferAttachment *attachment =
5209 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5210 if (attachment)
5211 {
5212 GLenum componentType = attachment->getFormat().info->componentType;
5213 const GLenum *end = validComponentTypes + validComponentTypeCount;
5214 if (std::find(validComponentTypes, end, componentType) == end)
5215 {
5216 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005217 InvalidOperation()
5218 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005219 return false;
5220 }
5221 }
5222
5223 return true;
5224}
5225
Jamie Madill5b772312018-03-08 20:28:32 -05005226bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005227{
5228 if (!ValidateRobustEntryPoint(context, dataSize))
5229 {
5230 return false;
5231 }
5232
Corentin Wallez336129f2017-10-17 15:55:40 -04005233 gl::Buffer *pixelUnpackBuffer =
5234 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005235 if (pixelUnpackBuffer == nullptr)
5236 {
5237 if (dataSize < imageSize)
5238 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005239 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005240 }
5241 }
5242 return true;
5243}
5244
Jamie Madill5b772312018-03-08 20:28:32 -05005245bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005246 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005247 GLenum pname,
5248 bool pointerVersion,
5249 GLsizei *numParams)
5250{
5251 if (numParams)
5252 {
5253 *numParams = 0;
5254 }
5255
Corentin Walleze4477002017-12-01 14:39:58 -05005256 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005257 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005258 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005259 return false;
5260 }
5261
5262 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5263 if (!buffer)
5264 {
5265 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005266 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005267 return false;
5268 }
5269
5270 const Extensions &extensions = context->getExtensions();
5271
5272 switch (pname)
5273 {
5274 case GL_BUFFER_USAGE:
5275 case GL_BUFFER_SIZE:
5276 break;
5277
5278 case GL_BUFFER_ACCESS_OES:
5279 if (!extensions.mapBuffer)
5280 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005281 context->handleError(InvalidEnum()
5282 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005283 return false;
5284 }
5285 break;
5286
5287 case GL_BUFFER_MAPPED:
5288 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5289 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5290 !extensions.mapBufferRange)
5291 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005292 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5293 "GL_OES_mapbuffer or "
5294 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005295 return false;
5296 }
5297 break;
5298
5299 case GL_BUFFER_MAP_POINTER:
5300 if (!pointerVersion)
5301 {
5302 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005303 InvalidEnum()
5304 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005305 return false;
5306 }
5307 break;
5308
5309 case GL_BUFFER_ACCESS_FLAGS:
5310 case GL_BUFFER_MAP_OFFSET:
5311 case GL_BUFFER_MAP_LENGTH:
5312 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5313 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005314 context->handleError(InvalidEnum()
5315 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005316 return false;
5317 }
5318 break;
5319
5320 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005321 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005322 return false;
5323 }
5324
5325 // All buffer parameter queries return one value.
5326 if (numParams)
5327 {
5328 *numParams = 1;
5329 }
5330
5331 return true;
5332}
5333
5334bool ValidateGetRenderbufferParameterivBase(Context *context,
5335 GLenum target,
5336 GLenum pname,
5337 GLsizei *length)
5338{
5339 if (length)
5340 {
5341 *length = 0;
5342 }
5343
5344 if (target != GL_RENDERBUFFER)
5345 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005346 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005347 return false;
5348 }
5349
5350 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5351 if (renderbuffer == nullptr)
5352 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005353 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005354 return false;
5355 }
5356
5357 switch (pname)
5358 {
5359 case GL_RENDERBUFFER_WIDTH:
5360 case GL_RENDERBUFFER_HEIGHT:
5361 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5362 case GL_RENDERBUFFER_RED_SIZE:
5363 case GL_RENDERBUFFER_GREEN_SIZE:
5364 case GL_RENDERBUFFER_BLUE_SIZE:
5365 case GL_RENDERBUFFER_ALPHA_SIZE:
5366 case GL_RENDERBUFFER_DEPTH_SIZE:
5367 case GL_RENDERBUFFER_STENCIL_SIZE:
5368 break;
5369
5370 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5371 if (!context->getExtensions().framebufferMultisample)
5372 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005373 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005374 return false;
5375 }
5376 break;
5377
5378 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005379 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005380 return false;
5381 }
5382
5383 if (length)
5384 {
5385 *length = 1;
5386 }
5387 return true;
5388}
5389
5390bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5391{
5392 if (length)
5393 {
5394 *length = 0;
5395 }
5396
5397 if (GetValidShader(context, shader) == nullptr)
5398 {
5399 return false;
5400 }
5401
5402 switch (pname)
5403 {
5404 case GL_SHADER_TYPE:
5405 case GL_DELETE_STATUS:
5406 case GL_COMPILE_STATUS:
5407 case GL_INFO_LOG_LENGTH:
5408 case GL_SHADER_SOURCE_LENGTH:
5409 break;
5410
5411 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5412 if (!context->getExtensions().translatedShaderSource)
5413 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005414 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005415 return false;
5416 }
5417 break;
5418
5419 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005420 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005421 return false;
5422 }
5423
5424 if (length)
5425 {
5426 *length = 1;
5427 }
5428 return true;
5429}
5430
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005431bool ValidateGetTexParameterBase(Context *context,
5432 TextureType target,
5433 GLenum pname,
5434 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005435{
5436 if (length)
5437 {
5438 *length = 0;
5439 }
5440
5441 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5442 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005443 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005444 return false;
5445 }
5446
5447 if (context->getTargetTexture(target) == nullptr)
5448 {
5449 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005450 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005451 return false;
5452 }
5453
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005454 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5455 {
5456 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5457 return false;
5458 }
5459
Jamie Madillbe849e42017-05-02 15:49:00 -04005460 switch (pname)
5461 {
5462 case GL_TEXTURE_MAG_FILTER:
5463 case GL_TEXTURE_MIN_FILTER:
5464 case GL_TEXTURE_WRAP_S:
5465 case GL_TEXTURE_WRAP_T:
5466 break;
5467
5468 case GL_TEXTURE_USAGE_ANGLE:
5469 if (!context->getExtensions().textureUsage)
5470 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005471 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005472 return false;
5473 }
5474 break;
5475
5476 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005477 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005478 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005479 return false;
5480 }
5481 break;
5482
5483 case GL_TEXTURE_IMMUTABLE_FORMAT:
5484 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5485 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005486 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005487 return false;
5488 }
5489 break;
5490
5491 case GL_TEXTURE_WRAP_R:
5492 case GL_TEXTURE_IMMUTABLE_LEVELS:
5493 case GL_TEXTURE_SWIZZLE_R:
5494 case GL_TEXTURE_SWIZZLE_G:
5495 case GL_TEXTURE_SWIZZLE_B:
5496 case GL_TEXTURE_SWIZZLE_A:
5497 case GL_TEXTURE_BASE_LEVEL:
5498 case GL_TEXTURE_MAX_LEVEL:
5499 case GL_TEXTURE_MIN_LOD:
5500 case GL_TEXTURE_MAX_LOD:
5501 case GL_TEXTURE_COMPARE_MODE:
5502 case GL_TEXTURE_COMPARE_FUNC:
5503 if (context->getClientMajorVersion() < 3)
5504 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005505 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005506 return false;
5507 }
5508 break;
5509
5510 case GL_TEXTURE_SRGB_DECODE_EXT:
5511 if (!context->getExtensions().textureSRGBDecode)
5512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005513 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005514 return false;
5515 }
5516 break;
5517
Yunchao Hebacaa712018-01-30 14:01:39 +08005518 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5519 if (context->getClientVersion() < Version(3, 1))
5520 {
5521 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5522 return false;
5523 }
5524 break;
5525
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005526 case GL_GENERATE_MIPMAP:
5527 case GL_TEXTURE_CROP_RECT_OES:
5528 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5529 // after GL_OES_draw_texture functionality implemented
5530 if (context->getClientMajorVersion() > 1)
5531 {
5532 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5533 return false;
5534 }
5535 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005536 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005537 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005538 return false;
5539 }
5540
5541 if (length)
5542 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005543 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005544 }
5545 return true;
5546}
5547
5548bool ValidateGetVertexAttribBase(Context *context,
5549 GLuint index,
5550 GLenum pname,
5551 GLsizei *length,
5552 bool pointer,
5553 bool pureIntegerEntryPoint)
5554{
5555 if (length)
5556 {
5557 *length = 0;
5558 }
5559
5560 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5561 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005562 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005563 return false;
5564 }
5565
5566 if (index >= context->getCaps().maxVertexAttributes)
5567 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005568 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005569 return false;
5570 }
5571
5572 if (pointer)
5573 {
5574 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5575 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005576 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005577 return false;
5578 }
5579 }
5580 else
5581 {
5582 switch (pname)
5583 {
5584 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5585 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5586 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5587 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5588 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5589 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5590 case GL_CURRENT_VERTEX_ATTRIB:
5591 break;
5592
5593 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5594 static_assert(
5595 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5596 "ANGLE extension enums not equal to GL enums.");
5597 if (context->getClientMajorVersion() < 3 &&
5598 !context->getExtensions().instancedArrays)
5599 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005600 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5601 "requires OpenGL ES 3.0 or "
5602 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005603 return false;
5604 }
5605 break;
5606
5607 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5608 if (context->getClientMajorVersion() < 3)
5609 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005610 context->handleError(
5611 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005612 return false;
5613 }
5614 break;
5615
5616 case GL_VERTEX_ATTRIB_BINDING:
5617 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5618 if (context->getClientVersion() < ES_3_1)
5619 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005620 context->handleError(InvalidEnum()
5621 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005622 return false;
5623 }
5624 break;
5625
5626 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005627 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005628 return false;
5629 }
5630 }
5631
5632 if (length)
5633 {
5634 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5635 {
5636 *length = 4;
5637 }
5638 else
5639 {
5640 *length = 1;
5641 }
5642 }
5643
5644 return true;
5645}
5646
Jamie Madill4928b7c2017-06-20 12:57:39 -04005647bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005648 GLint x,
5649 GLint y,
5650 GLsizei width,
5651 GLsizei height,
5652 GLenum format,
5653 GLenum type,
5654 GLsizei bufSize,
5655 GLsizei *length,
5656 GLsizei *columns,
5657 GLsizei *rows,
5658 void *pixels)
5659{
5660 if (length != nullptr)
5661 {
5662 *length = 0;
5663 }
5664 if (rows != nullptr)
5665 {
5666 *rows = 0;
5667 }
5668 if (columns != nullptr)
5669 {
5670 *columns = 0;
5671 }
5672
5673 if (width < 0 || height < 0)
5674 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005675 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005676 return false;
5677 }
5678
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005679 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005680
Jamie Madill427064d2018-04-13 16:20:34 -04005681 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005682 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005683 return false;
5684 }
5685
Jamie Madille98b1b52018-03-08 09:47:23 -05005686 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005687 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005688 return false;
5689 }
5690
Jamie Madill690c8eb2018-03-12 15:20:03 -04005691 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005692 ASSERT(framebuffer);
5693
5694 if (framebuffer->getReadBufferState() == GL_NONE)
5695 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005696 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005697 return false;
5698 }
5699
5700 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5701 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5702 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5703 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5704 // situation is an application error that would lead to a crash in ANGLE.
5705 if (readBuffer == nullptr)
5706 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005707 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005708 return false;
5709 }
5710
Martin Radev28031682017-07-28 14:47:56 +03005711 // ANGLE_multiview, Revision 1:
5712 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03005713 // current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
5714 // in the current read framebuffer is more than one.
5715 if (framebuffer->readDisallowedByMultiview())
Martin Radev28031682017-07-28 14:47:56 +03005716 {
5717 context->handleError(InvalidFramebufferOperation()
5718 << "Attempting to read from a multi-view framebuffer.");
5719 return false;
5720 }
5721
Geoff Lang280ba992017-04-18 16:30:58 -04005722 if (context->getExtensions().webglCompatibility)
5723 {
5724 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5725 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5726 // and type before validating the combination of format and type. However, the
5727 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5728 // verifies that GL_INVALID_OPERATION is generated.
5729 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5730 // dEQP/WebGL.
5731 if (!ValidReadPixelsFormatEnum(context, format))
5732 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005733 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005734 return false;
5735 }
5736
5737 if (!ValidReadPixelsTypeEnum(context, type))
5738 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005739 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005740 return false;
5741 }
5742 }
5743
Jamie Madill690c8eb2018-03-12 15:20:03 -04005744 GLenum currentFormat = GL_NONE;
5745 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5746
5747 GLenum currentType = GL_NONE;
5748 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5749
Jamie Madillbe849e42017-05-02 15:49:00 -04005750 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5751
5752 bool validFormatTypeCombination =
5753 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5754
5755 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5756 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005757 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005758 return false;
5759 }
5760
5761 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005762 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005763 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5764 {
5765 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005766 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005767 return false;
5768 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005769 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5770 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5771 {
5772 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5773 return false;
5774 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005775
5776 // .. the data would be packed to the buffer object such that the memory writes required
5777 // would exceed the data store size.
5778 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5779 const gl::Extents size(width, height, 1);
5780 const auto &pack = context->getGLState().getPackState();
5781
Jamie Madillca2ff382018-07-11 09:01:17 -04005782 GLuint endByte = 0;
5783 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005784 {
Jamie Madillca2ff382018-07-11 09:01:17 -04005785 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005786 return false;
5787 }
5788
Jamie Madillbe849e42017-05-02 15:49:00 -04005789 if (bufSize >= 0)
5790 {
5791 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5792 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005793 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005794 return false;
5795 }
5796 }
5797
5798 if (pixelPackBuffer != nullptr)
5799 {
5800 CheckedNumeric<size_t> checkedEndByte(endByte);
5801 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5802 checkedEndByte += checkedOffset;
5803
5804 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5805 {
5806 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005807 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005808 return false;
5809 }
5810 }
5811
5812 if (pixelPackBuffer == nullptr && length != nullptr)
5813 {
5814 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5815 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005816 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005817 return false;
5818 }
5819
5820 *length = static_cast<GLsizei>(endByte);
5821 }
5822
Geoff Langa953b522018-02-21 16:56:23 -05005823 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005824 angle::CheckedNumeric<int> clippedExtent(length);
5825 if (start < 0)
5826 {
5827 // "subtract" the area that is less than 0
5828 clippedExtent += start;
5829 }
5830
Geoff Langa953b522018-02-21 16:56:23 -05005831 angle::CheckedNumeric<int> readExtent = start;
5832 readExtent += length;
5833 if (!readExtent.IsValid())
5834 {
5835 return false;
5836 }
5837
5838 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005839 {
5840 // Subtract the region to the right of the read buffer
5841 clippedExtent -= (readExtent - bufferSize);
5842 }
5843
5844 if (!clippedExtent.IsValid())
5845 {
Geoff Langa953b522018-02-21 16:56:23 -05005846 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005847 }
5848
Geoff Langa953b522018-02-21 16:56:23 -05005849 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5850 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005851 };
5852
Geoff Langa953b522018-02-21 16:56:23 -05005853 GLsizei writtenColumns = 0;
5854 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5855 {
5856 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5857 return false;
5858 }
5859
5860 GLsizei writtenRows = 0;
5861 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5862 {
5863 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5864 return false;
5865 }
5866
Jamie Madillbe849e42017-05-02 15:49:00 -04005867 if (columns != nullptr)
5868 {
Geoff Langa953b522018-02-21 16:56:23 -05005869 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005870 }
5871
5872 if (rows != nullptr)
5873 {
Geoff Langa953b522018-02-21 16:56:23 -05005874 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005875 }
5876
5877 return true;
5878}
5879
5880template <typename ParamType>
5881bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005882 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005883 GLenum pname,
5884 GLsizei bufSize,
5885 const ParamType *params)
5886{
5887 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5888 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005889 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005890 return false;
5891 }
5892
5893 if (context->getTargetTexture(target) == nullptr)
5894 {
5895 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005896 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005897 return false;
5898 }
5899
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005900 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005901 if (bufSize >= 0 && bufSize < minBufSize)
5902 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005903 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005904 return false;
5905 }
5906
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005907 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5908 {
5909 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5910 return false;
5911 }
5912
Jamie Madillbe849e42017-05-02 15:49:00 -04005913 switch (pname)
5914 {
5915 case GL_TEXTURE_WRAP_R:
5916 case GL_TEXTURE_SWIZZLE_R:
5917 case GL_TEXTURE_SWIZZLE_G:
5918 case GL_TEXTURE_SWIZZLE_B:
5919 case GL_TEXTURE_SWIZZLE_A:
5920 case GL_TEXTURE_BASE_LEVEL:
5921 case GL_TEXTURE_MAX_LEVEL:
5922 case GL_TEXTURE_COMPARE_MODE:
5923 case GL_TEXTURE_COMPARE_FUNC:
5924 case GL_TEXTURE_MIN_LOD:
5925 case GL_TEXTURE_MAX_LOD:
5926 if (context->getClientMajorVersion() < 3)
5927 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005928 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005929 return false;
5930 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005931 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005932 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005933 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5934 "available without "
5935 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005936 return false;
5937 }
5938 break;
5939
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005940 case GL_GENERATE_MIPMAP:
5941 case GL_TEXTURE_CROP_RECT_OES:
5942 if (context->getClientMajorVersion() > 1)
5943 {
5944 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5945 return false;
5946 }
5947 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005948 default:
5949 break;
5950 }
5951
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005952 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005953 {
5954 switch (pname)
5955 {
5956 case GL_TEXTURE_MIN_FILTER:
5957 case GL_TEXTURE_MAG_FILTER:
5958 case GL_TEXTURE_WRAP_S:
5959 case GL_TEXTURE_WRAP_T:
5960 case GL_TEXTURE_WRAP_R:
5961 case GL_TEXTURE_MIN_LOD:
5962 case GL_TEXTURE_MAX_LOD:
5963 case GL_TEXTURE_COMPARE_MODE:
5964 case GL_TEXTURE_COMPARE_FUNC:
5965 context->handleError(InvalidEnum()
5966 << "Invalid parameter for 2D multisampled textures.");
5967 return false;
5968 }
5969 }
5970
Jamie Madillbe849e42017-05-02 15:49:00 -04005971 switch (pname)
5972 {
5973 case GL_TEXTURE_WRAP_S:
5974 case GL_TEXTURE_WRAP_T:
5975 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005976 {
5977 bool restrictedWrapModes =
5978 target == TextureType::External || target == TextureType::Rectangle;
5979 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005980 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005981 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005982 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005983 }
5984 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005985
5986 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005987 {
5988 bool restrictedMinFilter =
5989 target == TextureType::External || target == TextureType::Rectangle;
5990 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005991 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005992 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005993 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005994 }
5995 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005996
5997 case GL_TEXTURE_MAG_FILTER:
5998 if (!ValidateTextureMagFilterValue(context, params))
5999 {
6000 return false;
6001 }
6002 break;
6003
6004 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04006005 if (!context->getExtensions().textureUsage)
6006 {
6007 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6008 return false;
6009 }
6010
Jamie Madillbe849e42017-05-02 15:49:00 -04006011 switch (ConvertToGLenum(params[0]))
6012 {
6013 case GL_NONE:
6014 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
6015 break;
6016
6017 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006018 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006019 return false;
6020 }
6021 break;
6022
6023 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07006024 {
6025 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6026 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04006027 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07006028 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04006029 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07006030 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
6031 }
6032 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006033
6034 case GL_TEXTURE_MIN_LOD:
6035 case GL_TEXTURE_MAX_LOD:
6036 // any value is permissible
6037 break;
6038
6039 case GL_TEXTURE_COMPARE_MODE:
6040 if (!ValidateTextureCompareModeValue(context, params))
6041 {
6042 return false;
6043 }
6044 break;
6045
6046 case GL_TEXTURE_COMPARE_FUNC:
6047 if (!ValidateTextureCompareFuncValue(context, params))
6048 {
6049 return false;
6050 }
6051 break;
6052
6053 case GL_TEXTURE_SWIZZLE_R:
6054 case GL_TEXTURE_SWIZZLE_G:
6055 case GL_TEXTURE_SWIZZLE_B:
6056 case GL_TEXTURE_SWIZZLE_A:
6057 switch (ConvertToGLenum(params[0]))
6058 {
6059 case GL_RED:
6060 case GL_GREEN:
6061 case GL_BLUE:
6062 case GL_ALPHA:
6063 case GL_ZERO:
6064 case GL_ONE:
6065 break;
6066
6067 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006068 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006069 return false;
6070 }
6071 break;
6072
6073 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006074 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006075 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006076 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006077 return false;
6078 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006079 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006080 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006081 context->handleError(InvalidOperation()
6082 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006083 return false;
6084 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006085 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08006086 {
6087 context->handleError(InvalidOperation()
6088 << "Base level must be 0 for multisampled textures.");
6089 return false;
6090 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006091 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006092 {
6093 context->handleError(InvalidOperation()
6094 << "Base level must be 0 for rectangle textures.");
6095 return false;
6096 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006097 break;
6098
6099 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006100 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006101 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006102 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006103 return false;
6104 }
6105 break;
6106
6107 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6108 if (context->getClientVersion() < Version(3, 1))
6109 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006110 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006111 return false;
6112 }
6113 switch (ConvertToGLenum(params[0]))
6114 {
6115 case GL_DEPTH_COMPONENT:
6116 case GL_STENCIL_INDEX:
6117 break;
6118
6119 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006120 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006121 return false;
6122 }
6123 break;
6124
6125 case GL_TEXTURE_SRGB_DECODE_EXT:
6126 if (!ValidateTextureSRGBDecodeValue(context, params))
6127 {
6128 return false;
6129 }
6130 break;
6131
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006132 case GL_GENERATE_MIPMAP:
6133 case GL_TEXTURE_CROP_RECT_OES:
6134 if (context->getClientMajorVersion() > 1)
6135 {
6136 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
6137 return false;
6138 }
6139 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006140 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006141 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006142 return false;
6143 }
6144
6145 return true;
6146}
6147
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006148template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6149template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006150
Jamie Madill5b772312018-03-08 20:28:32 -05006151bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006152{
6153 if (index >= MAX_VERTEX_ATTRIBS)
6154 {
6155 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6156 return false;
6157 }
6158
6159 return true;
6160}
6161
6162bool ValidateGetActiveUniformBlockivBase(Context *context,
6163 GLuint program,
6164 GLuint uniformBlockIndex,
6165 GLenum pname,
6166 GLsizei *length)
6167{
6168 if (length)
6169 {
6170 *length = 0;
6171 }
6172
6173 if (context->getClientMajorVersion() < 3)
6174 {
6175 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6176 return false;
6177 }
6178
6179 Program *programObject = GetValidProgram(context, program);
6180 if (!programObject)
6181 {
6182 return false;
6183 }
6184
6185 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6186 {
6187 context->handleError(InvalidValue()
6188 << "uniformBlockIndex exceeds active uniform block count.");
6189 return false;
6190 }
6191
6192 switch (pname)
6193 {
6194 case GL_UNIFORM_BLOCK_BINDING:
6195 case GL_UNIFORM_BLOCK_DATA_SIZE:
6196 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6197 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6198 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6199 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6200 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6201 break;
6202
6203 default:
6204 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6205 return false;
6206 }
6207
6208 if (length)
6209 {
6210 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6211 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006212 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006213 programObject->getUniformBlockByIndex(uniformBlockIndex);
6214 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6215 }
6216 else
6217 {
6218 *length = 1;
6219 }
6220 }
6221
6222 return true;
6223}
6224
Jamie Madill9696d072017-08-26 23:19:57 -04006225template <typename ParamType>
6226bool ValidateSamplerParameterBase(Context *context,
6227 GLuint sampler,
6228 GLenum pname,
6229 GLsizei bufSize,
6230 ParamType *params)
6231{
6232 if (context->getClientMajorVersion() < 3)
6233 {
6234 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6235 return false;
6236 }
6237
6238 if (!context->isSampler(sampler))
6239 {
6240 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6241 return false;
6242 }
6243
6244 const GLsizei minBufSize = 1;
6245 if (bufSize >= 0 && bufSize < minBufSize)
6246 {
6247 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6248 return false;
6249 }
6250
6251 switch (pname)
6252 {
6253 case GL_TEXTURE_WRAP_S:
6254 case GL_TEXTURE_WRAP_T:
6255 case GL_TEXTURE_WRAP_R:
6256 if (!ValidateTextureWrapModeValue(context, params, false))
6257 {
6258 return false;
6259 }
6260 break;
6261
6262 case GL_TEXTURE_MIN_FILTER:
6263 if (!ValidateTextureMinFilterValue(context, params, false))
6264 {
6265 return false;
6266 }
6267 break;
6268
6269 case GL_TEXTURE_MAG_FILTER:
6270 if (!ValidateTextureMagFilterValue(context, params))
6271 {
6272 return false;
6273 }
6274 break;
6275
6276 case GL_TEXTURE_MIN_LOD:
6277 case GL_TEXTURE_MAX_LOD:
6278 // any value is permissible
6279 break;
6280
6281 case GL_TEXTURE_COMPARE_MODE:
6282 if (!ValidateTextureCompareModeValue(context, params))
6283 {
6284 return false;
6285 }
6286 break;
6287
6288 case GL_TEXTURE_COMPARE_FUNC:
6289 if (!ValidateTextureCompareFuncValue(context, params))
6290 {
6291 return false;
6292 }
6293 break;
6294
6295 case GL_TEXTURE_SRGB_DECODE_EXT:
6296 if (!ValidateTextureSRGBDecodeValue(context, params))
6297 {
6298 return false;
6299 }
6300 break;
6301
Luc Ferron1b1a8642018-01-23 15:12:01 -05006302 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6303 {
6304 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6305 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6306 {
6307 return false;
6308 }
6309 }
6310 break;
6311
Jamie Madill9696d072017-08-26 23:19:57 -04006312 default:
6313 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6314 return false;
6315 }
6316
6317 return true;
6318}
6319
6320template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6321template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6322
6323bool ValidateGetSamplerParameterBase(Context *context,
6324 GLuint sampler,
6325 GLenum pname,
6326 GLsizei *length)
6327{
6328 if (length)
6329 {
6330 *length = 0;
6331 }
6332
6333 if (context->getClientMajorVersion() < 3)
6334 {
6335 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6336 return false;
6337 }
6338
6339 if (!context->isSampler(sampler))
6340 {
6341 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6342 return false;
6343 }
6344
6345 switch (pname)
6346 {
6347 case GL_TEXTURE_WRAP_S:
6348 case GL_TEXTURE_WRAP_T:
6349 case GL_TEXTURE_WRAP_R:
6350 case GL_TEXTURE_MIN_FILTER:
6351 case GL_TEXTURE_MAG_FILTER:
6352 case GL_TEXTURE_MIN_LOD:
6353 case GL_TEXTURE_MAX_LOD:
6354 case GL_TEXTURE_COMPARE_MODE:
6355 case GL_TEXTURE_COMPARE_FUNC:
6356 break;
6357
Luc Ferron1b1a8642018-01-23 15:12:01 -05006358 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6359 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6360 {
6361 return false;
6362 }
6363 break;
6364
Jamie Madill9696d072017-08-26 23:19:57 -04006365 case GL_TEXTURE_SRGB_DECODE_EXT:
6366 if (!context->getExtensions().textureSRGBDecode)
6367 {
6368 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6369 return false;
6370 }
6371 break;
6372
6373 default:
6374 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6375 return false;
6376 }
6377
6378 if (length)
6379 {
6380 *length = 1;
6381 }
6382 return true;
6383}
6384
6385bool ValidateGetInternalFormativBase(Context *context,
6386 GLenum target,
6387 GLenum internalformat,
6388 GLenum pname,
6389 GLsizei bufSize,
6390 GLsizei *numParams)
6391{
6392 if (numParams)
6393 {
6394 *numParams = 0;
6395 }
6396
6397 if (context->getClientMajorVersion() < 3)
6398 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006399 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006400 return false;
6401 }
6402
6403 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006404 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006405 {
6406 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6407 return false;
6408 }
6409
6410 switch (target)
6411 {
6412 case GL_RENDERBUFFER:
6413 break;
6414
6415 case GL_TEXTURE_2D_MULTISAMPLE:
6416 if (context->getClientVersion() < ES_3_1)
6417 {
6418 context->handleError(InvalidOperation()
6419 << "Texture target requires at least OpenGL ES 3.1.");
6420 return false;
6421 }
6422 break;
6423
6424 default:
6425 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6426 return false;
6427 }
6428
6429 if (bufSize < 0)
6430 {
6431 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6432 return false;
6433 }
6434
6435 GLsizei maxWriteParams = 0;
6436 switch (pname)
6437 {
6438 case GL_NUM_SAMPLE_COUNTS:
6439 maxWriteParams = 1;
6440 break;
6441
6442 case GL_SAMPLES:
6443 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6444 break;
6445
6446 default:
6447 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6448 return false;
6449 }
6450
6451 if (numParams)
6452 {
6453 // glGetInternalFormativ will not overflow bufSize
6454 *numParams = std::min(bufSize, maxWriteParams);
6455 }
6456
6457 return true;
6458}
6459
Jamie Madille98b1b52018-03-08 09:47:23 -05006460bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6461{
Jamie Madill427064d2018-04-13 16:20:34 -04006462 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006463 {
6464 context->handleError(InvalidOperation());
6465 return false;
6466 }
6467 return true;
6468}
6469
Lingfeng Yang038dd532018-03-29 17:31:52 -07006470bool ValidateMultitextureUnit(Context *context, GLenum texture)
6471{
6472 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6473 {
6474 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6475 return false;
6476 }
6477 return true;
6478}
6479
Jamie Madillc29968b2016-01-20 11:17:23 -05006480} // namespace gl