blob: 41deeb4c4109a36ef90b873f5d4f7ecfc805dd8b [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
1509 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1510 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1511 {
1512 context->handleError(InvalidFramebufferOperation()
1513 << "Attempt to read from a multi-view framebuffer.");
1514 return false;
1515 }
1516 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1517 {
1518 context->handleError(InvalidFramebufferOperation()
1519 << "Attempt to write to a multi-view framebuffer.");
1520 return false;
1521 }
1522
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001523 return true;
1524}
1525
Jamie Madill4928b7c2017-06-20 12:57:39 -04001526bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001527 GLint x,
1528 GLint y,
1529 GLsizei width,
1530 GLsizei height,
1531 GLenum format,
1532 GLenum type,
1533 GLsizei bufSize,
1534 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001535 GLsizei *columns,
1536 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001537 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001538{
1539 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001540 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001541 return false;
1542 }
1543
Brandon Jonesd1049182018-03-28 10:02:20 -07001544 GLsizei writeLength = 0;
1545 GLsizei writeColumns = 0;
1546 GLsizei writeRows = 0;
1547
1548 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1549 &writeColumns, &writeRows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001550 {
Geoff Langb1196682014-07-23 13:47:29 -04001551 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001552 }
1553
Brandon Jonesd1049182018-03-28 10:02:20 -07001554 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Jamie Madill26e91952014-03-05 15:01:27 -05001555 {
Geoff Langb1196682014-07-23 13:47:29 -04001556 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001557 }
1558
Brandon Jonesd1049182018-03-28 10:02:20 -07001559 SetRobustLengthParam(length, writeLength);
1560 SetRobustLengthParam(columns, writeColumns);
1561 SetRobustLengthParam(rows, writeRows);
1562
Jamie Madillc29968b2016-01-20 11:17:23 -05001563 return true;
1564}
1565
1566bool ValidateReadnPixelsEXT(Context *context,
1567 GLint x,
1568 GLint y,
1569 GLsizei width,
1570 GLsizei height,
1571 GLenum format,
1572 GLenum type,
1573 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001574 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001575{
1576 if (bufSize < 0)
1577 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001578 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001579 return false;
1580 }
1581
Geoff Lang62fce5b2016-09-30 10:46:35 -04001582 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001583 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001584}
Jamie Madill26e91952014-03-05 15:01:27 -05001585
Jamie Madill4928b7c2017-06-20 12:57:39 -04001586bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001587 GLint x,
1588 GLint y,
1589 GLsizei width,
1590 GLsizei height,
1591 GLenum format,
1592 GLenum type,
1593 GLsizei bufSize,
1594 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001595 GLsizei *columns,
1596 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001597 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001598{
Brandon Jonesd1049182018-03-28 10:02:20 -07001599 GLsizei writeLength = 0;
1600 GLsizei writeColumns = 0;
1601 GLsizei writeRows = 0;
1602
Geoff Lang62fce5b2016-09-30 10:46:35 -04001603 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001604 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001605 return false;
1606 }
1607
Brandon Jonesd1049182018-03-28 10:02:20 -07001608 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, &writeLength,
1609 &writeColumns, &writeRows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001610 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001611 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001612 }
1613
Brandon Jonesd1049182018-03-28 10:02:20 -07001614 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang62fce5b2016-09-30 10:46:35 -04001615 {
1616 return false;
1617 }
1618
Brandon Jonesd1049182018-03-28 10:02:20 -07001619 SetRobustLengthParam(length, writeLength);
1620 SetRobustLengthParam(columns, writeColumns);
1621 SetRobustLengthParam(rows, writeRows);
1622
Geoff Lang62fce5b2016-09-30 10:46:35 -04001623 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001624}
1625
Jamie Madillf0e04492017-08-26 15:28:42 -04001626bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001627{
1628 if (!context->getExtensions().occlusionQueryBoolean &&
1629 !context->getExtensions().disjointTimerQuery)
1630 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001631 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001632 return false;
1633 }
1634
Olli Etuaho41997e72016-03-10 13:38:39 +02001635 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001636}
1637
Jamie Madillf0e04492017-08-26 15:28:42 -04001638bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001639{
1640 if (!context->getExtensions().occlusionQueryBoolean &&
1641 !context->getExtensions().disjointTimerQuery)
1642 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001643 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001644 return false;
1645 }
1646
Olli Etuaho41997e72016-03-10 13:38:39 +02001647 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001648}
1649
Jamie Madillf0e04492017-08-26 15:28:42 -04001650bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1651{
1652 if (!context->getExtensions().occlusionQueryBoolean &&
1653 !context->getExtensions().disjointTimerQuery)
1654 {
1655 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1656 return false;
1657 }
1658
1659 return true;
1660}
1661
Corentin Wallezad3ae902018-03-09 13:40:42 -05001662bool ValidateBeginQueryBase(gl::Context *context, QueryType target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001663{
1664 if (!ValidQueryType(context, target))
1665 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001666 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001667 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001668 }
1669
1670 if (id == 0)
1671 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001672 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001673 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001674 }
1675
1676 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1677 // of zero, if the active query object name for <target> is non-zero (for the
1678 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1679 // the active query for either target is non-zero), if <id> is the name of an
1680 // existing query object whose type does not match <target>, or if <id> is the
1681 // active query object name for any query type, the error INVALID_OPERATION is
1682 // generated.
1683
1684 // Ensure no other queries are active
1685 // NOTE: If other queries than occlusion are supported, we will need to check
1686 // separately that:
1687 // a) The query ID passed is not the current active query for any target/type
1688 // b) There are no active queries for the requested target (and in the case
1689 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1690 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001691
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001692 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001693 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001694 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001695 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001696 }
1697
1698 Query *queryObject = context->getQuery(id, true, target);
1699
1700 // check that name was obtained with glGenQueries
1701 if (!queryObject)
1702 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001703 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001704 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001705 }
1706
1707 // check for type mismatch
1708 if (queryObject->getType() != target)
1709 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001710 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001711 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001712 }
1713
1714 return true;
1715}
1716
Corentin Wallezad3ae902018-03-09 13:40:42 -05001717bool ValidateBeginQueryEXT(gl::Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001718{
1719 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001720 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001721 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001722 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001723 return false;
1724 }
1725
1726 return ValidateBeginQueryBase(context, target, id);
1727}
1728
Corentin Wallezad3ae902018-03-09 13:40:42 -05001729bool ValidateEndQueryBase(gl::Context *context, QueryType target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001730{
1731 if (!ValidQueryType(context, target))
1732 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001733 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001734 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001735 }
1736
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001737 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001738
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001739 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001740 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001741 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001742 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001743 }
1744
Jamie Madill45c785d2014-05-13 14:09:34 -04001745 return true;
1746}
1747
Corentin Wallezad3ae902018-03-09 13:40:42 -05001748bool ValidateEndQueryEXT(gl::Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001749{
1750 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001751 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001752 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001753 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001754 return false;
1755 }
1756
1757 return ValidateEndQueryBase(context, target);
1758}
1759
Corentin Wallezad3ae902018-03-09 13:40:42 -05001760bool ValidateQueryCounterEXT(Context *context, GLuint id, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001761{
1762 if (!context->getExtensions().disjointTimerQuery)
1763 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001764 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001765 return false;
1766 }
1767
Corentin Wallezad3ae902018-03-09 13:40:42 -05001768 if (target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001769 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001770 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001771 return false;
1772 }
1773
1774 Query *queryObject = context->getQuery(id, true, target);
1775 if (queryObject == nullptr)
1776 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001777 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001778 return false;
1779 }
1780
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001781 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001782 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001783 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001784 return false;
1785 }
1786
1787 return true;
1788}
1789
Corentin Wallezad3ae902018-03-09 13:40:42 -05001790bool ValidateGetQueryivBase(Context *context, QueryType target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001791{
Geoff Lang2186c382016-10-14 10:54:54 -04001792 if (numParams)
1793 {
1794 *numParams = 0;
1795 }
1796
Corentin Wallezad3ae902018-03-09 13:40:42 -05001797 if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001798 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001799 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001800 return false;
1801 }
1802
1803 switch (pname)
1804 {
1805 case GL_CURRENT_QUERY_EXT:
Corentin Wallezad3ae902018-03-09 13:40:42 -05001806 if (target == QueryType::Timestamp)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001807 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001808 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001809 return false;
1810 }
1811 break;
1812 case GL_QUERY_COUNTER_BITS_EXT:
1813 if (!context->getExtensions().disjointTimerQuery ||
Corentin Wallezad3ae902018-03-09 13:40:42 -05001814 (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001815 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001816 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001817 return false;
1818 }
1819 break;
1820 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001821 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001822 return false;
1823 }
1824
Geoff Lang2186c382016-10-14 10:54:54 -04001825 if (numParams)
1826 {
1827 // All queries return only one value
1828 *numParams = 1;
1829 }
1830
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001831 return true;
1832}
1833
Corentin Wallezad3ae902018-03-09 13:40:42 -05001834bool ValidateGetQueryivEXT(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001835{
1836 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001837 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001838 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001839 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001840 return false;
1841 }
1842
Geoff Lang2186c382016-10-14 10:54:54 -04001843 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001844}
1845
Geoff Lang2186c382016-10-14 10:54:54 -04001846bool ValidateGetQueryivRobustANGLE(Context *context,
Corentin Wallezad3ae902018-03-09 13:40:42 -05001847 QueryType target,
Geoff Lang2186c382016-10-14 10:54:54 -04001848 GLenum pname,
1849 GLsizei bufSize,
1850 GLsizei *length,
1851 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001852{
Geoff Lang2186c382016-10-14 10:54:54 -04001853 if (!ValidateRobustEntryPoint(context, bufSize))
1854 {
1855 return false;
1856 }
1857
Brandon Jonesd1049182018-03-28 10:02:20 -07001858 GLsizei numParams = 0;
1859
1860 if (!ValidateGetQueryivBase(context, target, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001861 {
1862 return false;
1863 }
1864
Brandon Jonesd1049182018-03-28 10:02:20 -07001865 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001866 {
1867 return false;
1868 }
1869
Brandon Jonesd1049182018-03-28 10:02:20 -07001870 SetRobustLengthParam(length, numParams);
1871
Geoff Lang2186c382016-10-14 10:54:54 -04001872 return true;
1873}
1874
1875bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1876{
1877 if (numParams)
1878 {
1879 *numParams = 0;
1880 }
1881
Corentin Wallezad3ae902018-03-09 13:40:42 -05001882 Query *queryObject = context->getQuery(id, false, QueryType::InvalidEnum);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001883
1884 if (!queryObject)
1885 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001886 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001887 return false;
1888 }
1889
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001890 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001891 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001892 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001893 return false;
1894 }
1895
1896 switch (pname)
1897 {
1898 case GL_QUERY_RESULT_EXT:
1899 case GL_QUERY_RESULT_AVAILABLE_EXT:
1900 break;
1901
1902 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001903 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001904 return false;
1905 }
1906
Geoff Lang2186c382016-10-14 10:54:54 -04001907 if (numParams)
1908 {
1909 *numParams = 1;
1910 }
1911
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001912 return true;
1913}
1914
1915bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1916{
1917 if (!context->getExtensions().disjointTimerQuery)
1918 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001919 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001920 return false;
1921 }
Geoff Lang2186c382016-10-14 10:54:54 -04001922 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1923}
1924
1925bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1926 GLuint id,
1927 GLenum pname,
1928 GLsizei bufSize,
1929 GLsizei *length,
1930 GLint *params)
1931{
1932 if (!context->getExtensions().disjointTimerQuery)
1933 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001934 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001935 return false;
1936 }
1937
1938 if (!ValidateRobustEntryPoint(context, bufSize))
1939 {
1940 return false;
1941 }
1942
Brandon Jonesd1049182018-03-28 10:02:20 -07001943 GLsizei numParams = 0;
1944
1945 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001946 {
1947 return false;
1948 }
1949
Brandon Jonesd1049182018-03-28 10:02:20 -07001950 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001951 {
1952 return false;
1953 }
1954
Brandon Jonesd1049182018-03-28 10:02:20 -07001955 SetRobustLengthParam(length, numParams);
1956
Geoff Lang2186c382016-10-14 10:54:54 -04001957 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001958}
1959
1960bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1961{
1962 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001963 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001964 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001965 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001966 return false;
1967 }
Geoff Lang2186c382016-10-14 10:54:54 -04001968 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1969}
1970
1971bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1972 GLuint id,
1973 GLenum pname,
1974 GLsizei bufSize,
1975 GLsizei *length,
1976 GLuint *params)
1977{
1978 if (!context->getExtensions().disjointTimerQuery &&
1979 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1980 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001981 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001982 return false;
1983 }
1984
1985 if (!ValidateRobustEntryPoint(context, bufSize))
1986 {
1987 return false;
1988 }
1989
Brandon Jonesd1049182018-03-28 10:02:20 -07001990 GLsizei numParams = 0;
1991
1992 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001993 {
1994 return false;
1995 }
1996
Brandon Jonesd1049182018-03-28 10:02:20 -07001997 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04001998 {
1999 return false;
2000 }
2001
Brandon Jonesd1049182018-03-28 10:02:20 -07002002 SetRobustLengthParam(length, numParams);
2003
Geoff Lang2186c382016-10-14 10:54:54 -04002004 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002005}
2006
2007bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2008{
2009 if (!context->getExtensions().disjointTimerQuery)
2010 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002011 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002012 return false;
2013 }
Geoff Lang2186c382016-10-14 10:54:54 -04002014 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2015}
2016
2017bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2018 GLuint id,
2019 GLenum pname,
2020 GLsizei bufSize,
2021 GLsizei *length,
2022 GLint64 *params)
2023{
2024 if (!context->getExtensions().disjointTimerQuery)
2025 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002026 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002027 return false;
2028 }
2029
2030 if (!ValidateRobustEntryPoint(context, bufSize))
2031 {
2032 return false;
2033 }
2034
Brandon Jonesd1049182018-03-28 10:02:20 -07002035 GLsizei numParams = 0;
2036
2037 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002038 {
2039 return false;
2040 }
2041
Brandon Jonesd1049182018-03-28 10:02:20 -07002042 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002043 {
2044 return false;
2045 }
2046
Brandon Jonesd1049182018-03-28 10:02:20 -07002047 SetRobustLengthParam(length, numParams);
2048
Geoff Lang2186c382016-10-14 10:54:54 -04002049 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002050}
2051
2052bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2053{
2054 if (!context->getExtensions().disjointTimerQuery)
2055 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002056 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002057 return false;
2058 }
Geoff Lang2186c382016-10-14 10:54:54 -04002059 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2060}
2061
2062bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2063 GLuint id,
2064 GLenum pname,
2065 GLsizei bufSize,
2066 GLsizei *length,
2067 GLuint64 *params)
2068{
2069 if (!context->getExtensions().disjointTimerQuery)
2070 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002071 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002072 return false;
2073 }
2074
2075 if (!ValidateRobustEntryPoint(context, bufSize))
2076 {
2077 return false;
2078 }
2079
Brandon Jonesd1049182018-03-28 10:02:20 -07002080 GLsizei numParams = 0;
2081
2082 if (!ValidateGetQueryObjectValueBase(context, id, pname, &numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002083 {
2084 return false;
2085 }
2086
Brandon Jonesd1049182018-03-28 10:02:20 -07002087 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2186c382016-10-14 10:54:54 -04002088 {
2089 return false;
2090 }
2091
Brandon Jonesd1049182018-03-28 10:02:20 -07002092 SetRobustLengthParam(length, numParams);
2093
Geoff Lang2186c382016-10-14 10:54:54 -04002094 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002095}
2096
Jamie Madill5b772312018-03-08 20:28:32 -05002097bool ValidateUniformCommonBase(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002098 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05002099 GLint location,
2100 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08002101 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05002102{
Jiajia Qin5451d532017-11-16 17:16:34 +08002103 // TODO(Jiajia): Add image uniform check in future.
2104 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05002105 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002106 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05002107 return false;
2108 }
2109
Jiajia Qin5451d532017-11-16 17:16:34 +08002110 if (!program)
2111 {
2112 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
2113 return false;
2114 }
2115
2116 if (!program->isLinked())
2117 {
2118 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
2119 return false;
2120 }
2121
2122 if (location == -1)
2123 {
2124 // Silently ignore the uniform command
2125 return false;
2126 }
2127
2128 const auto &uniformLocations = program->getUniformLocations();
2129 size_t castedLocation = static_cast<size_t>(location);
2130 if (castedLocation >= uniformLocations.size())
2131 {
2132 context->handleError(InvalidOperation() << "Invalid uniform location");
2133 return false;
2134 }
2135
2136 const auto &uniformLocation = uniformLocations[castedLocation];
2137 if (uniformLocation.ignored)
2138 {
2139 // Silently ignore the uniform command
2140 return false;
2141 }
2142
2143 if (!uniformLocation.used())
2144 {
2145 context->handleError(InvalidOperation());
2146 return false;
2147 }
2148
2149 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2150
2151 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
Jamie Madill2fc08062018-05-10 15:10:55 -04002152 if (count > 1 && !uniform.isArray())
Jiajia Qin5451d532017-11-16 17:16:34 +08002153 {
2154 context->handleError(InvalidOperation());
2155 return false;
2156 }
2157
2158 *uniformOut = &uniform;
2159 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002160}
2161
Jamie Madill5b772312018-03-08 20:28:32 -05002162bool ValidateUniform1ivValue(Context *context,
Jiajia Qin5451d532017-11-16 17:16:34 +08002163 GLenum uniformType,
2164 GLsizei count,
2165 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002166{
Jiajia Qin5451d532017-11-16 17:16:34 +08002167 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2168 // It is compatible with INT or BOOL.
2169 // Do these cheap tests first, for a little extra speed.
2170 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002171 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002172 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002173 }
2174
Jiajia Qin5451d532017-11-16 17:16:34 +08002175 if (IsSamplerType(uniformType))
2176 {
2177 // Check that the values are in range.
2178 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2179 for (GLsizei i = 0; i < count; ++i)
2180 {
2181 if (value[i] < 0 || value[i] >= max)
2182 {
2183 context->handleError(InvalidValue() << "sampler uniform value out of range");
2184 return false;
2185 }
2186 }
2187 return true;
2188 }
2189
2190 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2191 return false;
2192}
2193
Jamie Madill5b772312018-03-08 20:28:32 -05002194bool ValidateUniformValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002195{
2196 // Check that the value type is compatible with uniform type.
2197 // Do the cheaper test first, for a little extra speed.
2198 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2199 {
2200 return true;
2201 }
2202
2203 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2204 return false;
2205}
2206
Jamie Madill5b772312018-03-08 20:28:32 -05002207bool ValidateUniformMatrixValue(Context *context, GLenum valueType, GLenum uniformType)
Jiajia Qin5451d532017-11-16 17:16:34 +08002208{
2209 // Check that the value type is compatible with uniform type.
2210 if (valueType == uniformType)
2211 {
2212 return true;
2213 }
2214
2215 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2216 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002217}
2218
Jamie Madill5b772312018-03-08 20:28:32 -05002219bool ValidateUniform(Context *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002220{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002221 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002222 gl::Program *programObject = context->getGLState().getProgram();
2223 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2224 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002225}
2226
Jamie Madill5b772312018-03-08 20:28:32 -05002227bool ValidateUniform1iv(Context *context, GLint location, GLsizei count, const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002228{
2229 const LinkedUniform *uniform = nullptr;
2230 gl::Program *programObject = context->getGLState().getProgram();
2231 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2232 ValidateUniform1ivValue(context, uniform->type, count, value);
2233}
2234
Jamie Madill5b772312018-03-08 20:28:32 -05002235bool ValidateUniformMatrix(Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002236 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002237 GLint location,
2238 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002239 GLboolean transpose)
2240{
Geoff Lang92019432017-11-20 13:09:34 -05002241 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002242 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002243 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002244 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002245 }
2246
Jamie Madill62d31cb2015-09-11 13:25:51 -04002247 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002248 gl::Program *programObject = context->getGLState().getProgram();
2249 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2250 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002251}
2252
Jamie Madill5b772312018-03-08 20:28:32 -05002253bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002254{
2255 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2256 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002257 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002258 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002259 }
2260
Jamie Madill0af26e12015-03-05 19:54:33 -05002261 const Caps &caps = context->getCaps();
2262
Jamie Madill893ab082014-05-16 16:56:10 -04002263 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2264 {
2265 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2266
Jamie Madill0af26e12015-03-05 19:54:33 -05002267 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002268 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002269 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002270 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002271 }
2272 }
2273
2274 switch (pname)
2275 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002276 case GL_TEXTURE_BINDING_2D:
2277 case GL_TEXTURE_BINDING_CUBE_MAP:
2278 case GL_TEXTURE_BINDING_3D:
2279 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002280 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002281 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002282 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2283 if (!context->getExtensions().textureRectangle)
2284 {
2285 context->handleError(InvalidEnum()
2286 << "ANGLE_texture_rectangle extension not present");
2287 return false;
2288 }
2289 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002290 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2291 if (!context->getExtensions().eglStreamConsumerExternal &&
2292 !context->getExtensions().eglImageExternal)
2293 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002294 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2295 "nor GL_OES_EGL_image_external "
2296 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002297 return false;
2298 }
2299 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002300
He Yunchaoced53ae2016-11-29 15:00:51 +08002301 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2302 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002303 {
Jamie Madille98b1b52018-03-08 09:47:23 -05002304 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
2305 ASSERT(readFramebuffer);
2306
Jamie Madill427064d2018-04-13 16:20:34 -04002307 if (!ValidateFramebufferComplete<InvalidOperation>(context, readFramebuffer))
Jamie Madill893ab082014-05-16 16:56:10 -04002308 {
Geoff Langb1196682014-07-23 13:47:29 -04002309 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002310 }
2311
Jamie Madille98b1b52018-03-08 09:47:23 -05002312 if (readFramebuffer->getReadBufferState() == GL_NONE)
Martin Radev138064f2016-07-15 12:03:41 +03002313 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002314 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002315 return false;
2316 }
2317
Jamie Madille98b1b52018-03-08 09:47:23 -05002318 const FramebufferAttachment *attachment = readFramebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002319 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002320 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002321 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002322 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002323 }
2324 }
2325 break;
2326
He Yunchaoced53ae2016-11-29 15:00:51 +08002327 default:
2328 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002329 }
2330
2331 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002332 if (*numParams == 0)
2333 {
2334 return false;
2335 }
2336
2337 return true;
2338}
2339
Brandon Jonesd1049182018-03-28 10:02:20 -07002340bool ValidateGetBooleanvRobustANGLE(Context *context,
2341 GLenum pname,
2342 GLsizei bufSize,
2343 GLsizei *length,
2344 GLboolean *params)
2345{
2346 GLenum nativeType;
2347 unsigned int numParams = 0;
2348
2349 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2350 {
2351 return false;
2352 }
2353
2354 SetRobustLengthParam(length, numParams);
2355
2356 return true;
2357}
2358
2359bool ValidateGetFloatvRobustANGLE(Context *context,
2360 GLenum pname,
2361 GLsizei bufSize,
2362 GLsizei *length,
2363 GLfloat *params)
2364{
2365 GLenum nativeType;
2366 unsigned int numParams = 0;
2367
2368 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2369 {
2370 return false;
2371 }
2372
2373 SetRobustLengthParam(length, numParams);
2374
2375 return true;
2376}
2377
2378bool ValidateGetIntegervRobustANGLE(Context *context,
2379 GLenum pname,
2380 GLsizei bufSize,
2381 GLsizei *length,
2382 GLint *data)
2383{
2384 GLenum nativeType;
2385 unsigned int numParams = 0;
2386
2387 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2388 {
2389 return false;
2390 }
2391
2392 SetRobustLengthParam(length, numParams);
2393
2394 return true;
2395}
2396
2397bool ValidateGetInteger64vRobustANGLE(Context *context,
2398 GLenum pname,
2399 GLsizei bufSize,
2400 GLsizei *length,
2401 GLint64 *data)
2402{
2403 GLenum nativeType;
2404 unsigned int numParams = 0;
2405
2406 if (!ValidateRobustStateQuery(context, pname, bufSize, &nativeType, &numParams))
2407 {
2408 return false;
2409 }
2410
2411 if (nativeType == GL_INT_64_ANGLEX)
2412 {
2413 CastStateValues(context, nativeType, pname, numParams, data);
2414 return false;
2415 }
2416
2417 SetRobustLengthParam(length, numParams);
2418 return true;
2419}
2420
Jamie Madill5b772312018-03-08 20:28:32 -05002421bool ValidateRobustStateQuery(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04002422 GLenum pname,
2423 GLsizei bufSize,
2424 GLenum *nativeType,
2425 unsigned int *numParams)
2426{
2427 if (!ValidateRobustEntryPoint(context, bufSize))
2428 {
2429 return false;
2430 }
2431
2432 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2433 {
2434 return false;
2435 }
2436
2437 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002438 {
2439 return false;
2440 }
2441
2442 return true;
2443}
2444
Jamie Madill5b772312018-03-08 20:28:32 -05002445bool ValidateCopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002446 TextureTarget target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002447 GLint level,
2448 GLenum internalformat,
2449 bool isSubImage,
2450 GLint xoffset,
2451 GLint yoffset,
2452 GLint zoffset,
2453 GLint x,
2454 GLint y,
2455 GLsizei width,
2456 GLsizei height,
2457 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002458 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002459{
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002460 TextureType texType = TextureTargetToType(target);
2461
Brandon Jones6cad5662017-06-14 13:25:13 -07002462 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002463 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002464 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2465 return false;
2466 }
2467
2468 if (width < 0 || height < 0)
2469 {
2470 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002471 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002472 }
2473
He Yunchaoced53ae2016-11-29 15:00:51 +08002474 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2475 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002476 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002477 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002478 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002479 }
2480
2481 if (border != 0)
2482 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002483 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002484 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002485 }
2486
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002487 if (!ValidMipLevel(context, texType, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002488 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002489 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002490 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002491 }
2492
Jamie Madille98b1b52018-03-08 09:47:23 -05002493 const gl::State &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002494 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madill427064d2018-04-13 16:20:34 -04002495 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002496 {
Geoff Langb1196682014-07-23 13:47:29 -04002497 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002498 }
2499
Jamie Madille98b1b52018-03-08 09:47:23 -05002500 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madill560a8d82014-05-21 13:06:20 -04002501 {
Geoff Langb1196682014-07-23 13:47:29 -04002502 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002503 }
2504
Martin Radev138064f2016-07-15 12:03:41 +03002505 if (readFramebuffer->getReadBufferState() == GL_NONE)
2506 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002507 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002508 return false;
2509 }
2510
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002511 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2512 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002513 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002514 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002515 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2516 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002517 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002518 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002519 return false;
2520 }
2521
Martin Radev04e2c3b2017-07-27 16:54:35 +03002522 // ANGLE_multiview spec, Revision 1:
2523 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2524 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2525 // is not NONE.
2526 if (source->getMultiviewLayout() != GL_NONE)
2527 {
2528 context->handleError(InvalidFramebufferOperation()
2529 << "The active read framebuffer object has multiview attachments.");
2530 return false;
2531 }
2532
Geoff Langaae65a42014-05-26 12:43:44 -04002533 const gl::Caps &caps = context->getCaps();
2534
Geoff Langaae65a42014-05-26 12:43:44 -04002535 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002536 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002537 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002538 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002539 maxDimension = caps.max2DTextureSize;
2540 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002541
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002542 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002543 maxDimension = caps.maxCubeMapTextureSize;
2544 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002545
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002546 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002547 maxDimension = caps.maxRectangleTextureSize;
2548 break;
2549
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002550 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002551 maxDimension = caps.max2DTextureSize;
2552 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002553
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002554 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002555 maxDimension = caps.max3DTextureSize;
2556 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002557
He Yunchaoced53ae2016-11-29 15:00:51 +08002558 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002559 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002560 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002561 }
2562
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002563 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002564 if (!texture)
2565 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002566 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002567 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002568 }
2569
Geoff Lang69cce582015-09-17 13:20:36 -04002570 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002571 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002572 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002573 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002574 }
2575
Geoff Langca271392017-04-05 12:30:00 -04002576 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002577 isSubImage ? *texture->getFormat(target, level).info
2578 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002579
Geoff Lang966c9402017-04-18 12:38:27 -04002580 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002581 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002582 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002583 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002584 }
2585
2586 if (isSubImage)
2587 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002588 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2589 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2590 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002591 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002592 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002593 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002594 }
2595 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002596 else
2597 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002598 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002599 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002600 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002601 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002602 }
2603
Geoff Langeb66a6e2016-10-31 13:06:12 -04002604 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002605 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002606 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002607 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002608 }
2609
2610 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002611 if (static_cast<int>(width) > maxLevelDimension ||
2612 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002613 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002614 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002615 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002616 }
2617 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002618
Jamie Madill0c8abca2016-07-22 20:21:26 -04002619 if (textureFormatOut)
2620 {
2621 *textureFormatOut = texture->getFormat(target, level);
2622 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002623
2624 // Detect texture copying feedback loops for WebGL.
2625 if (context->getExtensions().webglCompatibility)
2626 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002627 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002628 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002629 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002630 return false;
2631 }
2632 }
2633
Jamie Madill560a8d82014-05-21 13:06:20 -04002634 return true;
2635}
2636
Jamie Madill493f9572018-05-24 19:52:15 -04002637bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002638{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002639 const Extensions &extensions = context->getExtensions();
2640
Jamie Madill1aeb1312014-06-20 13:21:25 -04002641 switch (mode)
2642 {
Jamie Madill493f9572018-05-24 19:52:15 -04002643 case PrimitiveMode::Points:
2644 case PrimitiveMode::Lines:
2645 case PrimitiveMode::LineLoop:
2646 case PrimitiveMode::LineStrip:
2647 case PrimitiveMode::Triangles:
2648 case PrimitiveMode::TriangleStrip:
2649 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002650 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002651
Jamie Madill493f9572018-05-24 19:52:15 -04002652 case PrimitiveMode::LinesAdjacency:
2653 case PrimitiveMode::LineStripAdjacency:
2654 case PrimitiveMode::TrianglesAdjacency:
2655 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002656 if (!extensions.geometryShader)
2657 {
2658 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2659 return false;
2660 }
2661 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002662 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002663 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002664 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002665 }
2666
Jamie Madill250d33f2014-06-06 17:09:03 -04002667 if (count < 0)
2668 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002669 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002670 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002671 }
2672
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002673 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002674
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002675 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2676 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2677 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2678 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002679 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002680 // Check for mapped buffers
2681 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002682 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002683 {
2684 context->handleError(InvalidOperation());
2685 return false;
2686 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002687 }
2688
Jamie Madillcbcde722017-01-06 14:50:00 -05002689 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2690 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002691 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002692 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002693 {
Ken Russellb9f92502018-01-27 19:00:26 -08002694 ASSERT(framebuffer);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002695 const FramebufferAttachment *dsAttachment =
2696 framebuffer->getStencilOrDepthStencilAttachment();
Ken Russellb9f92502018-01-27 19:00:26 -08002697 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2698 ASSERT(stencilBits <= 8);
2699
Jinyoung Hur85769f02015-10-20 17:08:44 -04002700 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Ken Russellb9f92502018-01-27 19:00:26 -08002701 if (depthStencilState.stencilTest && stencilBits > 0)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002702 {
Ken Russellb9f92502018-01-27 19:00:26 -08002703 GLuint maxStencilValue = (1 << stencilBits) - 1;
2704
2705 bool differentRefs =
2706 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2707 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2708 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2709 (depthStencilState.stencilBackWritemask & maxStencilValue);
2710 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2711 (depthStencilState.stencilBackMask & maxStencilValue);
2712
2713 if (differentRefs || differentWritemasks || differentMasks)
Jamie Madillcbcde722017-01-06 14:50:00 -05002714 {
Ken Russellb9f92502018-01-27 19:00:26 -08002715 if (!extensions.webglCompatibility)
2716 {
Jamie Madilla2f043d2018-07-10 17:21:20 -04002717 WARN() << "This ANGLE implementation does not support separate front/back "
2718 "stencil writemasks, reference values, or stencil mask values.";
Ken Russellb9f92502018-01-27 19:00:26 -08002719 }
2720 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
2721 return false;
Jamie Madillcbcde722017-01-06 14:50:00 -05002722 }
Geoff Lang3a86ad32015-09-01 11:47:05 -04002723 }
Jamie Madillac528012014-06-20 13:21:23 -04002724 }
2725
Jamie Madill427064d2018-04-13 16:20:34 -04002726 if (!ValidateFramebufferComplete(context, framebuffer))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002727 {
Geoff Langb1196682014-07-23 13:47:29 -04002728 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002729 }
2730
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002731 // If we are running GLES1, there is no current program.
2732 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002733 {
Jamie Madilld4cfa572014-07-08 10:00:32 -04002734
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002735 gl::Program *program = state.getProgram();
2736 if (!program)
Martin Radev7cf61662017-07-26 17:10:53 +03002737 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002738 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Martin Radev7cf61662017-07-26 17:10:53 +03002739 return false;
2740 }
Martin Radev7e69f762017-07-27 14:54:13 +03002741
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002742 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2743 // vertex shader stage or fragment shader stage is a undefined behaviour.
2744 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2745 // produce undefined result.
2746 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2747 !program->hasLinkedShaderStage(ShaderType::Fragment))
Martin Radev7e69f762017-07-27 14:54:13 +03002748 {
2749 context->handleError(InvalidOperation()
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002750 << "It is a undefined behaviour to render without "
2751 "vertex shader stage or fragment shader stage.");
Martin Radev7e69f762017-07-27 14:54:13 +03002752 return false;
2753 }
Martin Radevffe754b2017-07-31 10:38:07 +03002754
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002755 if (!program->validateSamplers(nullptr, context->getCaps()))
Martin Radevffe754b2017-07-31 10:38:07 +03002756 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002757 context->handleError(InvalidOperation());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002758 return false;
2759 }
2760
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002761 if (extensions.multiview)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002762 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002763 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2764 const int framebufferNumViews = framebuffer->getNumViews();
2765 if (framebufferNumViews != programNumViews)
2766 {
2767 context->handleError(InvalidOperation()
2768 << "The number of views in the active program "
2769 "and draw framebuffer does not match.");
2770 return false;
2771 }
2772
2773 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2774 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2775 framebufferNumViews > 1)
2776 {
2777 context->handleError(InvalidOperation()
2778 << "There is an active transform feedback object "
2779 "when the number of views in the active draw "
2780 "framebuffer is greater than 1.");
2781 return false;
2782 }
2783
2784 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2785 state.isQueryActive(QueryType::TimeElapsed))
2786 {
2787 context->handleError(InvalidOperation()
2788 << "There is an active query for target "
2789 "GL_TIME_ELAPSED_EXT when the number of "
2790 "views in the active draw framebuffer is "
2791 "greater than 1.");
2792 return false;
2793 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002794 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002795
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002796 // Do geometry shader specific validations
2797 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002798 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002799 if (!IsCompatibleDrawModeWithGeometryShader(
2800 mode, program->getGeometryShaderInputPrimitiveType()))
2801 {
2802 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2803 IncompatibleDrawModeAgainstGeometryShader);
2804 return false;
2805 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002806 }
Geoff Lange0cff192017-05-30 13:04:56 -04002807
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002808 // Uniform buffer validation
2809 for (unsigned int uniformBlockIndex = 0;
2810 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Geoff Lang9ab5b822017-05-30 16:19:23 -04002811 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002812 const gl::InterfaceBlock &uniformBlock =
2813 program->getUniformBlockByIndex(uniformBlockIndex);
2814 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
2815 const OffsetBindingPointer<Buffer> &uniformBuffer =
2816 state.getIndexedUniformBuffer(blockBinding);
2817
2818 if (uniformBuffer.get() == nullptr)
2819 {
2820 // undefined behaviour
2821 context->handleError(
2822 InvalidOperation()
2823 << "It is undefined behaviour to have a used but unbound uniform buffer.");
2824 return false;
2825 }
2826
2827 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2828 if (uniformBufferSize < uniformBlock.dataSize)
2829 {
2830 // undefined behaviour
2831 context->handleError(
2832 InvalidOperation()
2833 << "It is undefined behaviour to use a uniform buffer that is too small.");
2834 return false;
2835 }
2836
2837 if (extensions.webglCompatibility &&
2838 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2839 {
2840 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2841 UniformBufferBoundForTransformFeedback);
2842 return false;
2843 }
Geoff Lang9ab5b822017-05-30 16:19:23 -04002844 }
2845
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002846 // Do some additonal WebGL-specific validation
2847 if (extensions.webglCompatibility)
Geoff Lange0cff192017-05-30 13:04:56 -04002848 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002849 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2850 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2851 transformFeedbackObject->buffersBoundForOtherUse())
2852 {
2853 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2854 TransformFeedbackBufferDoubleBound);
2855 return false;
2856 }
2857 // Detect rendering feedback loops for WebGL.
2858 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2859 {
2860 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
2861 return false;
2862 }
2863
2864 // Detect that the vertex shader input types match the attribute types
2865 if (!ValidateVertexShaderAttributeTypeMatch(context))
2866 {
2867 return false;
2868 }
2869
2870 // Detect that the color buffer types match the fragment shader output types
2871 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2872 {
2873 return false;
2874 }
Geoff Lange0cff192017-05-30 13:04:56 -04002875 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002876 }
2877
Jamie Madill9fdaa492018-02-16 10:52:11 -05002878 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002879}
2880
Jamie Madill5b772312018-03-08 20:28:32 -05002881bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002882 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002883 GLint first,
2884 GLsizei count,
2885 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002886{
Jamie Madillfd716582014-06-06 17:09:04 -04002887 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002888 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002889 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002890 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002891 }
2892
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002893 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002894 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002895 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002896 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002897 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002898 if (!ValidateTransformFeedbackPrimitiveMode(context,
2899 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002900 {
James Darpinian30b604d2018-03-12 17:26:57 -07002901 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2902 return false;
2903 }
2904
2905 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2906 {
2907 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2908 return false;
2909 }
Jamie Madillfd716582014-06-06 17:09:04 -04002910 }
2911
Jiajia Qind9671222016-11-29 16:30:31 +08002912 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002913 {
2914 return false;
2915 }
2916
Corentin Wallez71168a02016-12-19 15:11:18 -08002917 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002918 // - first < 0 has been checked as an error condition.
2919 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002920 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002921 ASSERT(first >= 0);
2922 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002923 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002924 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2925 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2926 {
2927 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2928 return false;
2929 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002930
Jamie Madill9fdaa492018-02-16 10:52:11 -05002931 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2932 {
2933 return false;
2934 }
Jamie Madillfd716582014-06-06 17:09:04 -04002935 }
2936
2937 return true;
2938}
2939
He Yunchaoced53ae2016-11-29 15:00:51 +08002940bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002941 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002942 GLint first,
2943 GLsizei count,
2944 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002945{
Geoff Lang63c5a592017-09-27 14:08:16 -04002946 if (!context->getExtensions().instancedArrays)
2947 {
2948 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2949 return false;
2950 }
2951
Corentin Wallez170efbf2017-05-02 13:45:01 -04002952 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002953 {
2954 return false;
2955 }
2956
Corentin Wallez0dc97812017-06-22 14:38:44 -04002957 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002958}
2959
Jamie Madill493f9572018-05-24 19:52:15 -04002960bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002961{
Jamie Madill250d33f2014-06-06 17:09:03 -04002962 switch (type)
2963 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002964 case GL_UNSIGNED_BYTE:
2965 case GL_UNSIGNED_SHORT:
2966 break;
2967 case GL_UNSIGNED_INT:
2968 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2969 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002970 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002971 return false;
2972 }
2973 break;
2974 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002975 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002976 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002977 }
2978
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002979 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002980
2981 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002982 if (curTransformFeedback && curTransformFeedback->isActive() &&
2983 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002984 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002985 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2986 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2987 if (context->getExtensions().geometryShader)
2988 {
2989 if (!ValidateTransformFeedbackPrimitiveMode(
2990 context, curTransformFeedback->getPrimitiveMode(), mode))
2991 {
2992 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2993 return false;
2994 }
2995 }
2996 else
2997 {
2998 // It is an invalid operation to call DrawElements, DrawRangeElements or
2999 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
3000 // 86)
3001 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3002 UnsupportedDrawModeForTransformFeedback);
3003 return false;
3004 }
Jamie Madill250d33f2014-06-06 17:09:03 -04003005 }
3006
Jiajia Qind9671222016-11-29 16:30:31 +08003007 return true;
3008}
3009
Jamie Madill5b772312018-03-08 20:28:32 -05003010bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003011 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003012 GLsizei count,
3013 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003014 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003015 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08003016{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08003017 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08003018 return false;
3019
3020 const State &state = context->getGLState();
3021
Corentin Wallez170efbf2017-05-02 13:45:01 -04003022 if (!ValidateDrawBase(context, mode, count))
3023 {
3024 return false;
3025 }
3026
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003027 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
3028 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
3029 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
3030 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04003031 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003032 // Check for mapped buffers
3033 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04003034 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003035 {
3036 context->handleError(InvalidOperation() << "Index buffer is mapped.");
3037 return false;
3038 }
Jamie Madill250d33f2014-06-06 17:09:03 -04003039 }
3040
He Yunchaoced53ae2016-11-29 15:00:51 +08003041 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003042 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003043
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003044 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3045
3046 if (context->getExtensions().webglCompatibility)
3047 {
3048 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3049 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3050 {
3051 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3052 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3053 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003054 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003055 return false;
3056 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003057
3058 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3059 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3060 // error is generated.
3061 if (reinterpret_cast<intptr_t>(indices) < 0)
3062 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003063 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003064 return false;
3065 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003066 }
3067
3068 if (context->getExtensions().webglCompatibility ||
3069 !context->getGLState().areClientArraysEnabled())
3070 {
Brandon Jones2a018152018-06-08 15:59:26 -07003071 if (!elementArrayBuffer)
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003072 {
3073 // [WebGL 1.0] Section 6.2 No Client Side Arrays
Brandon Jones2a018152018-06-08 15:59:26 -07003074 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3075 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003076 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003077 return false;
3078 }
3079 }
3080
Jamie Madill9fdaa492018-02-16 10:52:11 -05003081 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003082 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003083 // This is an application error that would normally result in a crash, but we catch it and
3084 // return an error
3085 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3086 return false;
3087 }
3088
3089 if (count > 0 && elementArrayBuffer)
3090 {
3091 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3092 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3093 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3094 constexpr uint64_t kMaxTypeSize = 8;
3095 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3096 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3097 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3098
3099 uint64_t typeSize = typeBytes;
3100 uint64_t elementCount = static_cast<uint64_t>(count);
3101 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3102
3103 // Doing the multiplication here is overflow-safe
3104 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3105
3106 // The offset can be any value, check for overflows
3107 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3108 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003109 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003110 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3111 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003112 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003113
3114 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3115 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003116 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003117 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3118 return false;
3119 }
3120
3121 ASSERT(isPow2(typeSize) && typeSize > 0);
3122 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3123 {
3124 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003125 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003126 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003127
3128 if (context->getExtensions().webglCompatibility &&
3129 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3130 {
3131 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3132 ElementArrayBufferBoundForTransformFeedback);
3133 return false;
3134 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003135 }
3136
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003137 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003138 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003139 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
3140 // access is enabled.
3141 if (!ValidateDrawAttribs(context, primcount, 0, 1))
3142 {
3143 return false;
3144 }
3145 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003146 else if (count == 0)
3147 {
3148 // ValidateDrawAttribs also does some extra validation that is independent of the vertex
3149 // count.
3150 if (!ValidateDrawAttribs(context, 0, 0, 0))
3151 {
3152 return false;
3153 }
3154 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003155 else
3156 {
3157 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003158 const DrawCallParams &params = context->getParams<DrawCallParams>();
3159 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3160 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003161
3162 // If we use an index greater than our maximum supported index range, return an error.
3163 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3164 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003165 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003166 {
3167 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3168 return false;
3169 }
3170
Jamie Madill6f5444d2018-03-14 10:08:11 -04003171 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end),
3172 static_cast<GLint>(indexRange.vertexCount())))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003173 {
3174 return false;
3175 }
3176
3177 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003178 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003179 }
3180
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003181 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003182}
3183
Jamie Madill5b772312018-03-08 20:28:32 -05003184bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003185 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003186 GLsizei count,
3187 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003188 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003189 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003190{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003191 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003192}
3193
Geoff Lang3edfe032015-09-04 16:38:24 -04003194bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003195 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003196 GLsizei count,
3197 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003198 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003199 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003200{
Geoff Lang63c5a592017-09-27 14:08:16 -04003201 if (!context->getExtensions().instancedArrays)
3202 {
3203 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3204 return false;
3205 }
3206
Corentin Wallez170efbf2017-05-02 13:45:01 -04003207 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003208 {
3209 return false;
3210 }
3211
Corentin Wallez0dc97812017-06-22 14:38:44 -04003212 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003213}
3214
He Yunchaoced53ae2016-11-29 15:00:51 +08003215bool ValidateFramebufferTextureBase(Context *context,
3216 GLenum target,
3217 GLenum attachment,
3218 GLuint texture,
3219 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003220{
Geoff Lange8afa902017-09-27 15:00:43 -04003221 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003222 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003223 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003224 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003225 }
3226
3227 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003228 {
3229 return false;
3230 }
3231
Jamie Madill55ec3b12014-07-03 10:38:57 -04003232 if (texture != 0)
3233 {
3234 gl::Texture *tex = context->getTexture(texture);
3235
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003236 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003237 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003238 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003239 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003240 }
3241
3242 if (level < 0)
3243 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003244 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003245 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003246 }
3247 }
3248
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003249 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003250 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003251
Jamie Madill84115c92015-04-23 15:00:07 -04003252 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003253 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003254 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003255 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003256 }
3257
3258 return true;
3259}
3260
Geoff Langb1196682014-07-23 13:47:29 -04003261bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003262{
3263 if (program == 0)
3264 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003265 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003266 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003267 }
3268
Dian Xiang769769a2015-09-09 15:20:08 -07003269 gl::Program *programObject = GetValidProgram(context, program);
3270 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003271 {
3272 return false;
3273 }
3274
Jamie Madill0063c512014-08-25 15:47:53 -04003275 if (!programObject || !programObject->isLinked())
3276 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003277 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003278 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003279 }
3280
Geoff Lang7dd2e102014-11-10 15:19:26 -05003281 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003282 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003283 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003284 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003285 }
3286
Jamie Madill0063c512014-08-25 15:47:53 -04003287 return true;
3288}
3289
Geoff Langf41d0ee2016-10-07 13:04:23 -04003290static bool ValidateSizedGetUniform(Context *context,
3291 GLuint program,
3292 GLint location,
3293 GLsizei bufSize,
3294 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003295{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003296 if (length)
3297 {
3298 *length = 0;
3299 }
3300
Jamie Madill78f41802014-08-25 15:47:55 -04003301 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003302 {
Jamie Madill78f41802014-08-25 15:47:55 -04003303 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003304 }
3305
Geoff Langf41d0ee2016-10-07 13:04:23 -04003306 if (bufSize < 0)
3307 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003308 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003309 return false;
3310 }
3311
Jamie Madilla502c742014-08-28 17:19:13 -04003312 gl::Program *programObject = context->getProgram(program);
3313 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003314
Jamie Madill78f41802014-08-25 15:47:55 -04003315 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003316 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003317 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003318 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003319 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003320 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003321 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003322 }
3323
Geoff Langf41d0ee2016-10-07 13:04:23 -04003324 if (length)
3325 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003326 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003327 }
3328
Jamie Madill0063c512014-08-25 15:47:53 -04003329 return true;
3330}
3331
He Yunchaoced53ae2016-11-29 15:00:51 +08003332bool ValidateGetnUniformfvEXT(Context *context,
3333 GLuint program,
3334 GLint location,
3335 GLsizei bufSize,
3336 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003337{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003338 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003339}
3340
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003341bool ValidateGetnUniformfvRobustANGLE(Context *context,
3342 GLuint program,
3343 GLint location,
3344 GLsizei bufSize,
3345 GLsizei *length,
3346 GLfloat *params)
3347{
3348 UNIMPLEMENTED();
3349 return false;
3350}
3351
He Yunchaoced53ae2016-11-29 15:00:51 +08003352bool ValidateGetnUniformivEXT(Context *context,
3353 GLuint program,
3354 GLint location,
3355 GLsizei bufSize,
3356 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003357{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003358 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3359}
3360
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003361bool ValidateGetnUniformivRobustANGLE(Context *context,
3362 GLuint program,
3363 GLint location,
3364 GLsizei bufSize,
3365 GLsizei *length,
3366 GLint *params)
3367{
3368 UNIMPLEMENTED();
3369 return false;
3370}
3371
3372bool ValidateGetnUniformuivRobustANGLE(Context *context,
3373 GLuint program,
3374 GLint location,
3375 GLsizei bufSize,
3376 GLsizei *length,
3377 GLuint *params)
3378{
3379 UNIMPLEMENTED();
3380 return false;
3381}
3382
Geoff Langf41d0ee2016-10-07 13:04:23 -04003383bool ValidateGetUniformfvRobustANGLE(Context *context,
3384 GLuint program,
3385 GLint location,
3386 GLsizei bufSize,
3387 GLsizei *length,
3388 GLfloat *params)
3389{
3390 if (!ValidateRobustEntryPoint(context, bufSize))
3391 {
3392 return false;
3393 }
3394
Brandon Jonesd1049182018-03-28 10:02:20 -07003395 GLsizei writeLength = 0;
3396
Geoff Langf41d0ee2016-10-07 13:04:23 -04003397 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003398 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3399 {
3400 return false;
3401 }
3402
3403 SetRobustLengthParam(length, writeLength);
3404
3405 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003406}
3407
3408bool ValidateGetUniformivRobustANGLE(Context *context,
3409 GLuint program,
3410 GLint location,
3411 GLsizei bufSize,
3412 GLsizei *length,
3413 GLint *params)
3414{
3415 if (!ValidateRobustEntryPoint(context, bufSize))
3416 {
3417 return false;
3418 }
3419
Brandon Jonesd1049182018-03-28 10:02:20 -07003420 GLsizei writeLength = 0;
3421
Geoff Langf41d0ee2016-10-07 13:04:23 -04003422 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003423 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3424 {
3425 return false;
3426 }
3427
3428 SetRobustLengthParam(length, writeLength);
3429
3430 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003431}
3432
3433bool ValidateGetUniformuivRobustANGLE(Context *context,
3434 GLuint program,
3435 GLint location,
3436 GLsizei bufSize,
3437 GLsizei *length,
3438 GLuint *params)
3439{
3440 if (!ValidateRobustEntryPoint(context, bufSize))
3441 {
3442 return false;
3443 }
3444
3445 if (context->getClientMajorVersion() < 3)
3446 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003447 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003448 return false;
3449 }
3450
Brandon Jonesd1049182018-03-28 10:02:20 -07003451 GLsizei writeLength = 0;
3452
Geoff Langf41d0ee2016-10-07 13:04:23 -04003453 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003454 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3455 {
3456 return false;
3457 }
3458
3459 SetRobustLengthParam(length, writeLength);
3460
3461 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003462}
3463
He Yunchaoced53ae2016-11-29 15:00:51 +08003464bool ValidateDiscardFramebufferBase(Context *context,
3465 GLenum target,
3466 GLsizei numAttachments,
3467 const GLenum *attachments,
3468 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003469{
3470 if (numAttachments < 0)
3471 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003472 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003473 return false;
3474 }
3475
3476 for (GLsizei i = 0; i < numAttachments; ++i)
3477 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003478 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003479 {
3480 if (defaultFramebuffer)
3481 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003482 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003483 return false;
3484 }
3485
3486 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003488 context->handleError(InvalidOperation() << "Requested color attachment is "
3489 "greater than the maximum supported "
3490 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003491 return false;
3492 }
3493 }
3494 else
3495 {
3496 switch (attachments[i])
3497 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003498 case GL_DEPTH_ATTACHMENT:
3499 case GL_STENCIL_ATTACHMENT:
3500 case GL_DEPTH_STENCIL_ATTACHMENT:
3501 if (defaultFramebuffer)
3502 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003503 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3504 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003505 return false;
3506 }
3507 break;
3508 case GL_COLOR:
3509 case GL_DEPTH:
3510 case GL_STENCIL:
3511 if (!defaultFramebuffer)
3512 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003513 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3514 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003515 return false;
3516 }
3517 break;
3518 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003519 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003520 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003521 }
3522 }
3523 }
3524
3525 return true;
3526}
3527
Austin Kinross6ee1e782015-05-29 17:05:37 -07003528bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3529{
Jamie Madill007530e2017-12-28 14:27:04 -05003530 if (!context->getExtensions().debugMarker)
3531 {
3532 // The debug marker calls should not set error state
3533 // However, it seems reasonable to set an error state if the extension is not enabled
3534 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3535 return false;
3536 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003537
Jamie Madill007530e2017-12-28 14:27:04 -05003538 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003539 if (length < 0)
3540 {
3541 return false;
3542 }
3543
3544 if (marker == nullptr)
3545 {
3546 return false;
3547 }
3548
3549 return true;
3550}
3551
3552bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3553{
Jamie Madill007530e2017-12-28 14:27:04 -05003554 if (!context->getExtensions().debugMarker)
3555 {
3556 // The debug marker calls should not set error state
3557 // However, it seems reasonable to set an error state if the extension is not enabled
3558 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3559 return false;
3560 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003561
Jamie Madill007530e2017-12-28 14:27:04 -05003562 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003563 if (length < 0)
3564 {
3565 return false;
3566 }
3567
3568 if (length > 0 && marker == nullptr)
3569 {
3570 return false;
3571 }
3572
3573 return true;
3574}
3575
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003576bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003577{
Geoff Langa8406172015-07-21 16:53:39 -04003578 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3579 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003580 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003581 return false;
3582 }
3583
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003584 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003585 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003586 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003587 if (!context->getExtensions().eglImage)
3588 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003589 context->handleError(InvalidEnum()
3590 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003591 }
3592 break;
3593
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003594 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003595 if (!context->getExtensions().eglImageExternal)
3596 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003597 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3598 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003599 }
Geoff Langa8406172015-07-21 16:53:39 -04003600 break;
3601
3602 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003603 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003604 return false;
3605 }
3606
Rafael Cintron05a449a2018-06-20 18:08:04 -07003607 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003608
Jamie Madill61e16b42017-06-19 11:13:23 -04003609 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003610 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003611 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003612 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003613 return false;
3614 }
3615
Jamie Madill007530e2017-12-28 14:27:04 -05003616 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003617 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003618 context->handleError(InvalidOperation()
3619 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003620 return false;
3621 }
3622
Geoff Langca271392017-04-05 12:30:00 -04003623 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003624 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003625 if (!textureCaps.texturable)
3626 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003627 context->handleError(InvalidOperation()
3628 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003629 return false;
3630 }
3631
Geoff Langdcab33b2015-07-21 13:03:16 -04003632 return true;
3633}
3634
3635bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003636 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003637 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003638{
Geoff Langa8406172015-07-21 16:53:39 -04003639 if (!context->getExtensions().eglImage)
3640 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003641 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003642 return false;
3643 }
3644
3645 switch (target)
3646 {
3647 case GL_RENDERBUFFER:
3648 break;
3649
3650 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003651 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003652 return false;
3653 }
3654
Rafael Cintron05a449a2018-06-20 18:08:04 -07003655 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003656
Jamie Madill61e16b42017-06-19 11:13:23 -04003657 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003658 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003659 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003660 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003661 return false;
3662 }
3663
Geoff Langca271392017-04-05 12:30:00 -04003664 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003665 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04003666 if (!textureCaps.renderbuffer)
Geoff Langa8406172015-07-21 16:53:39 -04003667 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003668 context->handleError(InvalidOperation()
3669 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003670 return false;
3671 }
3672
Geoff Langdcab33b2015-07-21 13:03:16 -04003673 return true;
3674}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003675
3676bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3677{
Geoff Lang36167ab2015-12-07 10:27:14 -05003678 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003679 {
3680 // The default VAO should always exist
3681 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003682 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003683 return false;
3684 }
3685
3686 return true;
3687}
3688
Geoff Langc5629752015-12-07 16:29:04 -05003689bool ValidateProgramBinaryBase(Context *context,
3690 GLuint program,
3691 GLenum binaryFormat,
3692 const void *binary,
3693 GLint length)
3694{
3695 Program *programObject = GetValidProgram(context, program);
3696 if (programObject == nullptr)
3697 {
3698 return false;
3699 }
3700
3701 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3702 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3703 programBinaryFormats.end())
3704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003705 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003706 return false;
3707 }
3708
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003709 if (context->hasActiveTransformFeedback(program))
3710 {
3711 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003712 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3713 "is associated with an active transform "
3714 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003715 return false;
3716 }
3717
Geoff Langc5629752015-12-07 16:29:04 -05003718 return true;
3719}
3720
3721bool ValidateGetProgramBinaryBase(Context *context,
3722 GLuint program,
3723 GLsizei bufSize,
3724 GLsizei *length,
3725 GLenum *binaryFormat,
3726 void *binary)
3727{
3728 Program *programObject = GetValidProgram(context, program);
3729 if (programObject == nullptr)
3730 {
3731 return false;
3732 }
3733
3734 if (!programObject->isLinked())
3735 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003736 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003737 return false;
3738 }
3739
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003740 if (context->getCaps().programBinaryFormats.empty())
3741 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003742 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003743 return false;
3744 }
3745
Geoff Langc5629752015-12-07 16:29:04 -05003746 return true;
3747}
Jamie Madillc29968b2016-01-20 11:17:23 -05003748
Jamie Madill5b772312018-03-08 20:28:32 -05003749bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003750{
3751 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003752 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003753 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003754 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3755 return false;
3756 }
3757 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3758 {
3759 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003760 return false;
3761 }
3762
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003763 ASSERT(context->getGLState().getDrawFramebuffer());
3764 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003765 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3766
3767 // This should come first before the check for the default frame buffer
3768 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3769 // rather than INVALID_OPERATION
3770 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3771 {
3772 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3773
3774 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003775 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3776 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003777 {
3778 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003779 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3780 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3781 // 3.1 is still a bit ambiguous about the error, but future specs are
3782 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003783 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003784 return false;
3785 }
3786 else if (bufs[colorAttachment] >= maxColorAttachment)
3787 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003788 context->handleError(InvalidOperation()
3789 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003790 return false;
3791 }
3792 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3793 frameBufferId != 0)
3794 {
3795 // INVALID_OPERATION-GL is bound to buffer and ith argument
3796 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003797 context->handleError(InvalidOperation()
3798 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003799 return false;
3800 }
3801 }
3802
3803 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3804 // and n is not 1 or bufs is bound to value other than BACK and NONE
3805 if (frameBufferId == 0)
3806 {
3807 if (n != 1)
3808 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003809 context->handleError(InvalidOperation()
3810 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003811 return false;
3812 }
3813
3814 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3815 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003816 context->handleError(
3817 InvalidOperation()
3818 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003819 return false;
3820 }
3821 }
3822
3823 return true;
3824}
3825
Geoff Lang496c02d2016-10-20 11:38:11 -07003826bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003827 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003828 GLenum pname,
3829 GLsizei *length,
3830 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003831{
Geoff Lang496c02d2016-10-20 11:38:11 -07003832 if (length)
3833 {
3834 *length = 0;
3835 }
3836
3837 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3838 {
3839 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003840 InvalidOperation()
3841 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003842 return false;
3843 }
3844
Corentin Walleze4477002017-12-01 14:39:58 -05003845 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003846 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003847 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003848 return false;
3849 }
3850
Geoff Lang496c02d2016-10-20 11:38:11 -07003851 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003852 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003853 case GL_BUFFER_MAP_POINTER:
3854 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003855
Geoff Lang496c02d2016-10-20 11:38:11 -07003856 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003857 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003858 return false;
3859 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003860
3861 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3862 // target bound to zero generate an INVALID_OPERATION error."
3863 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003864 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003865 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003866 context->handleError(InvalidOperation()
3867 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003868 return false;
3869 }
3870
Geoff Lang496c02d2016-10-20 11:38:11 -07003871 if (length)
3872 {
3873 *length = 1;
3874 }
3875
Olli Etuaho4f667482016-03-30 15:56:35 +03003876 return true;
3877}
3878
Corentin Wallez336129f2017-10-17 15:55:40 -04003879bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003880{
Corentin Walleze4477002017-12-01 14:39:58 -05003881 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003882 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003883 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003884 return false;
3885 }
3886
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003887 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003888
3889 if (buffer == nullptr || !buffer->isMapped())
3890 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003891 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003892 return false;
3893 }
3894
3895 return true;
3896}
3897
3898bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003899 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003900 GLintptr offset,
3901 GLsizeiptr length,
3902 GLbitfield access)
3903{
Corentin Walleze4477002017-12-01 14:39:58 -05003904 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003905 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003906 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003907 return false;
3908 }
3909
Brandon Jones6cad5662017-06-14 13:25:13 -07003910 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003911 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003912 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3913 return false;
3914 }
3915
3916 if (length < 0)
3917 {
3918 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003919 return false;
3920 }
3921
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003922 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003923
3924 if (!buffer)
3925 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003926 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003927 return false;
3928 }
3929
3930 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003931 CheckedNumeric<size_t> checkedOffset(offset);
3932 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003933
Jamie Madille2e406c2016-06-02 13:04:10 -04003934 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003935 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003936 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003937 return false;
3938 }
3939
3940 // Check for invalid bits in the mask
3941 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3942 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3943 GL_MAP_UNSYNCHRONIZED_BIT;
3944
3945 if (access & ~(allAccessBits))
3946 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003947 context->handleError(InvalidValue()
3948 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003949 return false;
3950 }
3951
3952 if (length == 0)
3953 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003954 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003955 return false;
3956 }
3957
3958 if (buffer->isMapped())
3959 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003960 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003961 return false;
3962 }
3963
3964 // Check for invalid bit combinations
3965 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3966 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003967 context->handleError(InvalidOperation()
3968 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003969 return false;
3970 }
3971
3972 GLbitfield writeOnlyBits =
3973 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3974
3975 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3976 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003977 context->handleError(InvalidOperation()
3978 << "Invalid access bits when mapping buffer for reading: 0x"
3979 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003980 return false;
3981 }
3982
3983 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3984 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003985 context->handleError(
3986 InvalidOperation()
3987 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003988 return false;
3989 }
Geoff Lang79f71042017-08-14 16:43:43 -04003990
3991 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003992}
3993
3994bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003995 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003996 GLintptr offset,
3997 GLsizeiptr length)
3998{
Brandon Jones6cad5662017-06-14 13:25:13 -07003999 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03004000 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004001 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
4002 return false;
4003 }
4004
4005 if (length < 0)
4006 {
4007 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03004008 return false;
4009 }
4010
Corentin Walleze4477002017-12-01 14:39:58 -05004011 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03004012 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004013 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03004014 return false;
4015 }
4016
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004017 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004018
4019 if (buffer == nullptr)
4020 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004021 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004022 return false;
4023 }
4024
4025 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4026 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004027 context->handleError(InvalidOperation()
4028 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004029 return false;
4030 }
4031
4032 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004033 CheckedNumeric<size_t> checkedOffset(offset);
4034 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004035
Jamie Madille2e406c2016-06-02 13:04:10 -04004036 if (!checkedSize.IsValid() ||
4037 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004038 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004039 context->handleError(InvalidValue()
4040 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004041 return false;
4042 }
4043
4044 return true;
4045}
4046
Olli Etuaho41997e72016-03-10 13:38:39 +02004047bool ValidateGenOrDelete(Context *context, GLint n)
4048{
4049 if (n < 0)
4050 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004051 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02004052 return false;
4053 }
4054 return true;
4055}
4056
Jamie Madill5b772312018-03-08 20:28:32 -05004057bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04004058{
4059 if (!context->getExtensions().robustClientMemory)
4060 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004061 context->handleError(InvalidOperation()
4062 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004063 return false;
4064 }
4065
4066 if (bufSize < 0)
4067 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004068 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004069 return false;
4070 }
4071
4072 return true;
4073}
4074
Jamie Madill5b772312018-03-08 20:28:32 -05004075bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004076{
4077 if (bufSize < numParams)
4078 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004079 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4080 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004081 return false;
4082 }
4083
4084 return true;
4085}
4086
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004087bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004088 GLenum target,
4089 GLenum attachment,
4090 GLenum pname,
4091 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004092{
Geoff Lange8afa902017-09-27 15:00:43 -04004093 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004094 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004095 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004096 return false;
4097 }
4098
4099 int clientVersion = context->getClientMajorVersion();
4100
4101 switch (pname)
4102 {
4103 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4104 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4105 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4106 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4107 break;
4108
Martin Radeve5285d22017-07-14 16:23:53 +03004109 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4110 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4111 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4112 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4113 if (clientVersion < 3 || !context->getExtensions().multiview)
4114 {
4115 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4116 return false;
4117 }
4118 break;
4119
Geoff Langff5b2d52016-09-07 11:32:23 -04004120 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4121 if (clientVersion < 3 && !context->getExtensions().sRGB)
4122 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004123 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004124 return false;
4125 }
4126 break;
4127
4128 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4129 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4130 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4131 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4132 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4133 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4134 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4135 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4136 if (clientVersion < 3)
4137 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004138 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004139 return false;
4140 }
4141 break;
4142
Jiawei Shaoa8802472018-05-28 11:17:47 +08004143 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4144 if (!context->getExtensions().geometryShader)
4145 {
4146 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4147 return false;
4148 }
4149 break;
4150
Geoff Langff5b2d52016-09-07 11:32:23 -04004151 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004152 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004153 return false;
4154 }
4155
4156 // Determine if the attachment is a valid enum
4157 switch (attachment)
4158 {
4159 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004160 case GL_DEPTH:
4161 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004162 if (clientVersion < 3)
4163 {
Geoff Langfa125c92017-10-24 13:01:46 -04004164 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004165 return false;
4166 }
4167 break;
4168
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004169 case GL_DEPTH_STENCIL_ATTACHMENT:
4170 if (clientVersion < 3 && !context->isWebGL1())
4171 {
4172 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4173 return false;
4174 }
4175 break;
4176
Geoff Langfa125c92017-10-24 13:01:46 -04004177 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004178 case GL_DEPTH_ATTACHMENT:
4179 case GL_STENCIL_ATTACHMENT:
4180 break;
4181
4182 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004183 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4184 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004185 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4186 {
Geoff Langfa125c92017-10-24 13:01:46 -04004187 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004188 return false;
4189 }
4190 break;
4191 }
4192
4193 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4194 ASSERT(framebuffer);
4195
4196 if (framebuffer->id() == 0)
4197 {
4198 if (clientVersion < 3)
4199 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004200 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004201 return false;
4202 }
4203
4204 switch (attachment)
4205 {
4206 case GL_BACK:
4207 case GL_DEPTH:
4208 case GL_STENCIL:
4209 break;
4210
4211 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004212 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004213 return false;
4214 }
4215 }
4216 else
4217 {
4218 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4219 {
4220 // Valid attachment query
4221 }
4222 else
4223 {
4224 switch (attachment)
4225 {
4226 case GL_DEPTH_ATTACHMENT:
4227 case GL_STENCIL_ATTACHMENT:
4228 break;
4229
4230 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004231 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004232 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004233 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004234 return false;
4235 }
4236 break;
4237
4238 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004239 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004240 return false;
4241 }
4242 }
4243 }
4244
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004245 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004246 if (attachmentObject)
4247 {
4248 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4249 attachmentObject->type() == GL_TEXTURE ||
4250 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4251
4252 switch (pname)
4253 {
4254 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4255 if (attachmentObject->type() != GL_RENDERBUFFER &&
4256 attachmentObject->type() != GL_TEXTURE)
4257 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004258 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004259 return false;
4260 }
4261 break;
4262
4263 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4264 if (attachmentObject->type() != GL_TEXTURE)
4265 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004266 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004267 return false;
4268 }
4269 break;
4270
4271 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4272 if (attachmentObject->type() != GL_TEXTURE)
4273 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004274 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004275 return false;
4276 }
4277 break;
4278
4279 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4280 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4281 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004282 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004283 return false;
4284 }
4285 break;
4286
4287 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4288 if (attachmentObject->type() != GL_TEXTURE)
4289 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004290 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004291 return false;
4292 }
4293 break;
4294
4295 default:
4296 break;
4297 }
4298 }
4299 else
4300 {
4301 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4302 // is NONE, then querying any other pname will generate INVALID_ENUM.
4303
4304 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4305 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4306 // INVALID_OPERATION for all other pnames
4307
4308 switch (pname)
4309 {
4310 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4311 break;
4312
4313 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4314 if (clientVersion < 3)
4315 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004316 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004317 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004318 return false;
4319 }
4320 break;
4321
4322 default:
4323 if (clientVersion < 3)
4324 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004325 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004326 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004327 return false;
4328 }
4329 else
4330 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004331 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004332 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004333 return false;
4334 }
4335 }
4336 }
4337
Martin Radeve5285d22017-07-14 16:23:53 +03004338 if (numParams)
4339 {
4340 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4341 {
4342 // Only when the viewport offsets are queried we can have a varying number of output
4343 // parameters.
4344 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4345 *numParams = numViews * 2;
4346 }
4347 else
4348 {
4349 // For all other queries we can have only one output parameter.
4350 *numParams = 1;
4351 }
4352 }
4353
Geoff Langff5b2d52016-09-07 11:32:23 -04004354 return true;
4355}
4356
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004357bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004358 GLenum target,
4359 GLenum attachment,
4360 GLenum pname,
4361 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004362 GLsizei *length,
4363 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004364{
4365 if (!ValidateRobustEntryPoint(context, bufSize))
4366 {
4367 return false;
4368 }
4369
Brandon Jonesd1049182018-03-28 10:02:20 -07004370 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004371 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004372 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004373 {
4374 return false;
4375 }
4376
Brandon Jonesd1049182018-03-28 10:02:20 -07004377 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004378 {
4379 return false;
4380 }
4381
Brandon Jonesd1049182018-03-28 10:02:20 -07004382 SetRobustLengthParam(length, numParams);
4383
Geoff Langff5b2d52016-09-07 11:32:23 -04004384 return true;
4385}
4386
Jamie Madill5b772312018-03-08 20:28:32 -05004387bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004388 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004389 GLenum pname,
4390 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004391 GLsizei *length,
4392 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004393{
4394 if (!ValidateRobustEntryPoint(context, bufSize))
4395 {
4396 return false;
4397 }
4398
Brandon Jonesd1049182018-03-28 10:02:20 -07004399 GLsizei numParams = 0;
4400
4401 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004402 {
4403 return false;
4404 }
4405
Brandon Jonesd1049182018-03-28 10:02:20 -07004406 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004407 {
4408 return false;
4409 }
4410
Brandon Jonesd1049182018-03-28 10:02:20 -07004411 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004412 return true;
4413}
4414
Jamie Madill5b772312018-03-08 20:28:32 -05004415bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004416 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004417 GLenum pname,
4418 GLsizei bufSize,
4419 GLsizei *length,
4420 GLint64 *params)
4421{
Brandon Jonesd1049182018-03-28 10:02:20 -07004422 GLsizei numParams = 0;
4423
Geoff Langebebe1c2016-10-14 12:01:31 -04004424 if (!ValidateRobustEntryPoint(context, bufSize))
4425 {
4426 return false;
4427 }
4428
Brandon Jonesd1049182018-03-28 10:02:20 -07004429 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004430 {
4431 return false;
4432 }
4433
Brandon Jonesd1049182018-03-28 10:02:20 -07004434 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004435 {
4436 return false;
4437 }
4438
Brandon Jonesd1049182018-03-28 10:02:20 -07004439 SetRobustLengthParam(length, numParams);
4440
Geoff Langff5b2d52016-09-07 11:32:23 -04004441 return true;
4442}
4443
Jamie Madill5b772312018-03-08 20:28:32 -05004444bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004445{
4446 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004447 if (numParams)
4448 {
4449 *numParams = 1;
4450 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004451
4452 Program *programObject = GetValidProgram(context, program);
4453 if (!programObject)
4454 {
4455 return false;
4456 }
4457
4458 switch (pname)
4459 {
4460 case GL_DELETE_STATUS:
4461 case GL_LINK_STATUS:
4462 case GL_VALIDATE_STATUS:
4463 case GL_INFO_LOG_LENGTH:
4464 case GL_ATTACHED_SHADERS:
4465 case GL_ACTIVE_ATTRIBUTES:
4466 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4467 case GL_ACTIVE_UNIFORMS:
4468 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4469 break;
4470
4471 case GL_PROGRAM_BINARY_LENGTH:
4472 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4473 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004474 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4475 "requires GL_OES_get_program_binary or "
4476 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004477 return false;
4478 }
4479 break;
4480
4481 case GL_ACTIVE_UNIFORM_BLOCKS:
4482 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4483 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4484 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4485 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4486 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4487 if (context->getClientMajorVersion() < 3)
4488 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004489 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004490 return false;
4491 }
4492 break;
4493
Yunchao He61afff12017-03-14 15:34:03 +08004494 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004495 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004496 if (context->getClientVersion() < Version(3, 1))
4497 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004498 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004499 return false;
4500 }
4501 break;
4502
Jiawei Shao6ae51612018-02-23 14:03:25 +08004503 case GL_COMPUTE_WORK_GROUP_SIZE:
4504 if (context->getClientVersion() < Version(3, 1))
4505 {
4506 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4507 return false;
4508 }
4509
4510 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4511 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4512 // program which has not been linked successfully, or which does not contain objects to
4513 // form a compute shader.
4514 if (!programObject->isLinked())
4515 {
4516 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4517 return false;
4518 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004519 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004520 {
4521 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4522 return false;
4523 }
4524 break;
4525
Jiawei Shao447bfac2018-03-14 14:23:40 +08004526 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4527 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4528 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4529 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4530 if (!context->getExtensions().geometryShader)
4531 {
4532 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4533 return false;
4534 }
4535
4536 // [EXT_geometry_shader] Chapter 7.12
4537 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4538 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4539 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4540 // successfully, or which does not contain objects to form a geometry shader.
4541 if (!programObject->isLinked())
4542 {
4543 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4544 return false;
4545 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004546 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004547 {
4548 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4549 return false;
4550 }
4551 break;
4552
Geoff Langff5b2d52016-09-07 11:32:23 -04004553 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004554 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004555 return false;
4556 }
4557
4558 return true;
4559}
4560
4561bool ValidateGetProgramivRobustANGLE(Context *context,
4562 GLuint program,
4563 GLenum pname,
4564 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004565 GLsizei *length,
4566 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004567{
4568 if (!ValidateRobustEntryPoint(context, bufSize))
4569 {
4570 return false;
4571 }
4572
Brandon Jonesd1049182018-03-28 10:02:20 -07004573 GLsizei numParams = 0;
4574
4575 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004576 {
4577 return false;
4578 }
4579
Brandon Jonesd1049182018-03-28 10:02:20 -07004580 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004581 {
4582 return false;
4583 }
4584
Brandon Jonesd1049182018-03-28 10:02:20 -07004585 SetRobustLengthParam(length, numParams);
4586
Geoff Langff5b2d52016-09-07 11:32:23 -04004587 return true;
4588}
4589
Geoff Lang740d9022016-10-07 11:20:52 -04004590bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4591 GLenum target,
4592 GLenum pname,
4593 GLsizei bufSize,
4594 GLsizei *length,
4595 GLint *params)
4596{
4597 if (!ValidateRobustEntryPoint(context, bufSize))
4598 {
4599 return false;
4600 }
4601
Brandon Jonesd1049182018-03-28 10:02:20 -07004602 GLsizei numParams = 0;
4603
4604 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004605 {
4606 return false;
4607 }
4608
Brandon Jonesd1049182018-03-28 10:02:20 -07004609 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004610 {
4611 return false;
4612 }
4613
Brandon Jonesd1049182018-03-28 10:02:20 -07004614 SetRobustLengthParam(length, numParams);
4615
Geoff Lang740d9022016-10-07 11:20:52 -04004616 return true;
4617}
4618
Geoff Langd7d0ed32016-10-07 11:33:51 -04004619bool ValidateGetShaderivRobustANGLE(Context *context,
4620 GLuint shader,
4621 GLenum pname,
4622 GLsizei bufSize,
4623 GLsizei *length,
4624 GLint *params)
4625{
4626 if (!ValidateRobustEntryPoint(context, bufSize))
4627 {
4628 return false;
4629 }
4630
Brandon Jonesd1049182018-03-28 10:02:20 -07004631 GLsizei numParams = 0;
4632
4633 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004634 {
4635 return false;
4636 }
4637
Brandon Jonesd1049182018-03-28 10:02:20 -07004638 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004639 {
4640 return false;
4641 }
4642
Brandon Jonesd1049182018-03-28 10:02:20 -07004643 SetRobustLengthParam(length, numParams);
4644
Geoff Langd7d0ed32016-10-07 11:33:51 -04004645 return true;
4646}
4647
Geoff Langc1984ed2016-10-07 12:41:00 -04004648bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004649 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004650 GLenum pname,
4651 GLsizei bufSize,
4652 GLsizei *length,
4653 GLfloat *params)
4654{
4655 if (!ValidateRobustEntryPoint(context, bufSize))
4656 {
4657 return false;
4658 }
4659
Brandon Jonesd1049182018-03-28 10:02:20 -07004660 GLsizei numParams = 0;
4661
4662 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004663 {
4664 return false;
4665 }
4666
Brandon Jonesd1049182018-03-28 10:02:20 -07004667 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004668 {
4669 return false;
4670 }
4671
Brandon Jonesd1049182018-03-28 10:02:20 -07004672 SetRobustLengthParam(length, numParams);
4673
Geoff Langc1984ed2016-10-07 12:41:00 -04004674 return true;
4675}
4676
Geoff Langc1984ed2016-10-07 12:41:00 -04004677bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004678 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004679 GLenum pname,
4680 GLsizei bufSize,
4681 GLsizei *length,
4682 GLint *params)
4683{
Brandon Jonesd1049182018-03-28 10:02:20 -07004684
Geoff Langc1984ed2016-10-07 12:41:00 -04004685 if (!ValidateRobustEntryPoint(context, bufSize))
4686 {
4687 return false;
4688 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004689 GLsizei numParams = 0;
4690 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004691 {
4692 return false;
4693 }
4694
Brandon Jonesd1049182018-03-28 10:02:20 -07004695 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004696 {
4697 return false;
4698 }
4699
Brandon Jonesd1049182018-03-28 10:02:20 -07004700 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004701 return true;
4702}
4703
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004704bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4705 TextureType target,
4706 GLenum pname,
4707 GLsizei bufSize,
4708 GLsizei *length,
4709 GLint *params)
4710{
4711 UNIMPLEMENTED();
4712 return false;
4713}
4714
4715bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4716 TextureType target,
4717 GLenum pname,
4718 GLsizei bufSize,
4719 GLsizei *length,
4720 GLuint *params)
4721{
4722 UNIMPLEMENTED();
4723 return false;
4724}
4725
Geoff Langc1984ed2016-10-07 12:41:00 -04004726bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004727 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004728 GLenum pname,
4729 GLsizei bufSize,
4730 const GLfloat *params)
4731{
4732 if (!ValidateRobustEntryPoint(context, bufSize))
4733 {
4734 return false;
4735 }
4736
4737 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4738}
4739
Geoff Langc1984ed2016-10-07 12:41:00 -04004740bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004741 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004742 GLenum pname,
4743 GLsizei bufSize,
4744 const GLint *params)
4745{
4746 if (!ValidateRobustEntryPoint(context, bufSize))
4747 {
4748 return false;
4749 }
4750
4751 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4752}
4753
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004754bool ValidateTexParameterIivRobustANGLE(Context *context,
4755 TextureType target,
4756 GLenum pname,
4757 GLsizei bufSize,
4758 const GLint *params)
4759{
4760 UNIMPLEMENTED();
4761 return false;
4762}
4763
4764bool ValidateTexParameterIuivRobustANGLE(Context *context,
4765 TextureType target,
4766 GLenum pname,
4767 GLsizei bufSize,
4768 const GLuint *params)
4769{
4770 UNIMPLEMENTED();
4771 return false;
4772}
4773
Geoff Langc1984ed2016-10-07 12:41:00 -04004774bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4775 GLuint sampler,
4776 GLenum pname,
4777 GLuint bufSize,
4778 GLsizei *length,
4779 GLfloat *params)
4780{
4781 if (!ValidateRobustEntryPoint(context, bufSize))
4782 {
4783 return false;
4784 }
4785
Brandon Jonesd1049182018-03-28 10:02:20 -07004786 GLsizei numParams = 0;
4787
4788 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004789 {
4790 return false;
4791 }
4792
Brandon Jonesd1049182018-03-28 10:02:20 -07004793 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004794 {
4795 return false;
4796 }
4797
Brandon Jonesd1049182018-03-28 10:02:20 -07004798 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004799 return true;
4800}
4801
Geoff Langc1984ed2016-10-07 12:41:00 -04004802bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4803 GLuint sampler,
4804 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004805 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004806 GLsizei *length,
4807 GLint *params)
4808{
4809 if (!ValidateRobustEntryPoint(context, bufSize))
4810 {
4811 return false;
4812 }
4813
Brandon Jonesd1049182018-03-28 10:02:20 -07004814 GLsizei numParams = 0;
4815
4816 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004817 {
4818 return false;
4819 }
4820
Brandon Jonesd1049182018-03-28 10:02:20 -07004821 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004822 {
4823 return false;
4824 }
4825
Brandon Jonesd1049182018-03-28 10:02:20 -07004826 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004827 return true;
4828}
4829
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004830bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4831 GLuint sampler,
4832 GLenum pname,
4833 GLsizei bufSize,
4834 GLsizei *length,
4835 GLint *params)
4836{
4837 UNIMPLEMENTED();
4838 return false;
4839}
4840
4841bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4842 GLuint sampler,
4843 GLenum pname,
4844 GLsizei bufSize,
4845 GLsizei *length,
4846 GLuint *params)
4847{
4848 UNIMPLEMENTED();
4849 return false;
4850}
4851
Geoff Langc1984ed2016-10-07 12:41:00 -04004852bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4853 GLuint sampler,
4854 GLenum pname,
4855 GLsizei bufSize,
4856 const GLfloat *params)
4857{
4858 if (!ValidateRobustEntryPoint(context, bufSize))
4859 {
4860 return false;
4861 }
4862
4863 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4864}
4865
Geoff Langc1984ed2016-10-07 12:41:00 -04004866bool ValidateSamplerParameterivRobustANGLE(Context *context,
4867 GLuint sampler,
4868 GLenum pname,
4869 GLsizei bufSize,
4870 const GLint *params)
4871{
4872 if (!ValidateRobustEntryPoint(context, bufSize))
4873 {
4874 return false;
4875 }
4876
4877 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4878}
4879
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004880bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4881 GLuint sampler,
4882 GLenum pname,
4883 GLsizei bufSize,
4884 const GLint *param)
4885{
4886 UNIMPLEMENTED();
4887 return false;
4888}
4889
4890bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4891 GLuint sampler,
4892 GLenum pname,
4893 GLsizei bufSize,
4894 const GLuint *param)
4895{
4896 UNIMPLEMENTED();
4897 return false;
4898}
4899
Geoff Lang0b031062016-10-13 14:30:04 -04004900bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4901 GLuint index,
4902 GLenum pname,
4903 GLsizei bufSize,
4904 GLsizei *length,
4905 GLfloat *params)
4906{
4907 if (!ValidateRobustEntryPoint(context, bufSize))
4908 {
4909 return false;
4910 }
4911
Brandon Jonesd1049182018-03-28 10:02:20 -07004912 GLsizei writeLength = 0;
4913
4914 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004915 {
4916 return false;
4917 }
4918
Brandon Jonesd1049182018-03-28 10:02:20 -07004919 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004920 {
4921 return false;
4922 }
4923
Brandon Jonesd1049182018-03-28 10:02:20 -07004924 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004925 return true;
4926}
4927
Geoff Lang0b031062016-10-13 14:30:04 -04004928bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4929 GLuint index,
4930 GLenum pname,
4931 GLsizei bufSize,
4932 GLsizei *length,
4933 GLint *params)
4934{
4935 if (!ValidateRobustEntryPoint(context, bufSize))
4936 {
4937 return false;
4938 }
4939
Brandon Jonesd1049182018-03-28 10:02:20 -07004940 GLsizei writeLength = 0;
4941
4942 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004943 {
4944 return false;
4945 }
4946
Brandon Jonesd1049182018-03-28 10:02:20 -07004947 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004948 {
4949 return false;
4950 }
4951
Brandon Jonesd1049182018-03-28 10:02:20 -07004952 SetRobustLengthParam(length, writeLength);
4953
Geoff Lang0b031062016-10-13 14:30:04 -04004954 return true;
4955}
4956
Geoff Lang0b031062016-10-13 14:30:04 -04004957bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4958 GLuint index,
4959 GLenum pname,
4960 GLsizei bufSize,
4961 GLsizei *length,
4962 void **pointer)
4963{
4964 if (!ValidateRobustEntryPoint(context, bufSize))
4965 {
4966 return false;
4967 }
4968
Brandon Jonesd1049182018-03-28 10:02:20 -07004969 GLsizei writeLength = 0;
4970
4971 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004972 {
4973 return false;
4974 }
4975
Brandon Jonesd1049182018-03-28 10:02:20 -07004976 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004977 {
4978 return false;
4979 }
4980
Brandon Jonesd1049182018-03-28 10:02:20 -07004981 SetRobustLengthParam(length, writeLength);
4982
Geoff Lang0b031062016-10-13 14:30:04 -04004983 return true;
4984}
4985
Geoff Lang0b031062016-10-13 14:30:04 -04004986bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4987 GLuint index,
4988 GLenum pname,
4989 GLsizei bufSize,
4990 GLsizei *length,
4991 GLint *params)
4992{
4993 if (!ValidateRobustEntryPoint(context, bufSize))
4994 {
4995 return false;
4996 }
4997
Brandon Jonesd1049182018-03-28 10:02:20 -07004998 GLsizei writeLength = 0;
4999
5000 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04005001 {
5002 return false;
5003 }
5004
Brandon Jonesd1049182018-03-28 10:02:20 -07005005 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04005006 {
5007 return false;
5008 }
5009
Brandon Jonesd1049182018-03-28 10:02:20 -07005010 SetRobustLengthParam(length, writeLength);
5011
Geoff Lang0b031062016-10-13 14:30:04 -04005012 return true;
5013}
5014
Geoff Lang0b031062016-10-13 14:30:04 -04005015bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5016 GLuint index,
5017 GLenum pname,
5018 GLsizei bufSize,
5019 GLsizei *length,
5020 GLuint *params)
5021{
5022 if (!ValidateRobustEntryPoint(context, bufSize))
5023 {
5024 return false;
5025 }
5026
Brandon Jonesd1049182018-03-28 10:02:20 -07005027 GLsizei writeLength = 0;
5028
5029 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04005030 {
5031 return false;
5032 }
5033
Brandon Jonesd1049182018-03-28 10:02:20 -07005034 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04005035 {
5036 return false;
5037 }
5038
Brandon Jonesd1049182018-03-28 10:02:20 -07005039 SetRobustLengthParam(length, writeLength);
5040
Geoff Lang0b031062016-10-13 14:30:04 -04005041 return true;
5042}
5043
Geoff Lang6899b872016-10-14 11:30:13 -04005044bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5045 GLuint program,
5046 GLuint uniformBlockIndex,
5047 GLenum pname,
5048 GLsizei bufSize,
5049 GLsizei *length,
5050 GLint *params)
5051{
5052 if (!ValidateRobustEntryPoint(context, bufSize))
5053 {
5054 return false;
5055 }
5056
Brandon Jonesd1049182018-03-28 10:02:20 -07005057 GLsizei writeLength = 0;
5058
5059 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
5060 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005061 {
5062 return false;
5063 }
5064
Brandon Jonesd1049182018-03-28 10:02:20 -07005065 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005066 {
5067 return false;
5068 }
5069
Brandon Jonesd1049182018-03-28 10:02:20 -07005070 SetRobustLengthParam(length, writeLength);
5071
Geoff Lang6899b872016-10-14 11:30:13 -04005072 return true;
5073}
5074
Brandon Jones416aaf92018-04-10 08:10:16 -07005075bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07005076 GLenum target,
5077 GLenum internalformat,
5078 GLenum pname,
5079 GLsizei bufSize,
5080 GLsizei *length,
5081 GLint *params)
5082{
5083 if (!ValidateRobustEntryPoint(context, bufSize))
5084 {
5085 return false;
5086 }
5087
Brandon Jonesd1049182018-03-28 10:02:20 -07005088 GLsizei numParams = 0;
5089
5090 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5091 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005092 {
5093 return false;
5094 }
5095
Brandon Jonesd1049182018-03-28 10:02:20 -07005096 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005097 {
5098 return false;
5099 }
5100
Brandon Jonesd1049182018-03-28 10:02:20 -07005101 SetRobustLengthParam(length, numParams);
5102
Geoff Lang0a9661f2016-10-20 10:59:20 -07005103 return true;
5104}
5105
Jamie Madill5b772312018-03-08 20:28:32 -05005106bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005107 GLuint attribIndex,
5108 GLint size,
5109 GLenum type,
5110 GLboolean pureInteger)
5111{
5112 const Caps &caps = context->getCaps();
5113 if (attribIndex >= caps.maxVertexAttributes)
5114 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005115 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005116 return false;
5117 }
5118
5119 if (size < 1 || size > 4)
5120 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005121 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005122 return false;
Shao80957d92017-02-20 21:25:59 +08005123 }
5124
5125 switch (type)
5126 {
5127 case GL_BYTE:
5128 case GL_UNSIGNED_BYTE:
5129 case GL_SHORT:
5130 case GL_UNSIGNED_SHORT:
5131 break;
5132
5133 case GL_INT:
5134 case GL_UNSIGNED_INT:
5135 if (context->getClientMajorVersion() < 3)
5136 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005137 context->handleError(InvalidEnum()
5138 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005139 return false;
5140 }
5141 break;
5142
5143 case GL_FIXED:
5144 case GL_FLOAT:
5145 if (pureInteger)
5146 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005147 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005148 return false;
5149 }
5150 break;
5151
5152 case GL_HALF_FLOAT:
5153 if (context->getClientMajorVersion() < 3)
5154 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005155 context->handleError(InvalidEnum()
5156 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005157 return false;
5158 }
5159 if (pureInteger)
5160 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005161 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005162 return false;
5163 }
5164 break;
5165
5166 case GL_INT_2_10_10_10_REV:
5167 case GL_UNSIGNED_INT_2_10_10_10_REV:
5168 if (context->getClientMajorVersion() < 3)
5169 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005170 context->handleError(InvalidEnum()
5171 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005172 return false;
5173 }
5174 if (pureInteger)
5175 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005176 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005177 return false;
5178 }
5179 if (size != 4)
5180 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005181 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5182 "UNSIGNED_INT_2_10_10_10_REV and "
5183 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005184 return false;
5185 }
5186 break;
5187
5188 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005189 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005190 return false;
5191 }
5192
5193 return true;
5194}
5195
Geoff Lang76e65652017-03-27 14:58:02 -04005196// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5197// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5198// specified clear value and the type of a buffer that is being cleared generates an
5199// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005200bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005201 GLint drawbuffer,
5202 const GLenum *validComponentTypes,
5203 size_t validComponentTypeCount)
5204{
5205 const FramebufferAttachment *attachment =
5206 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5207 if (attachment)
5208 {
5209 GLenum componentType = attachment->getFormat().info->componentType;
5210 const GLenum *end = validComponentTypes + validComponentTypeCount;
5211 if (std::find(validComponentTypes, end, componentType) == end)
5212 {
5213 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005214 InvalidOperation()
5215 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005216 return false;
5217 }
5218 }
5219
5220 return true;
5221}
5222
Jamie Madill5b772312018-03-08 20:28:32 -05005223bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005224{
5225 if (!ValidateRobustEntryPoint(context, dataSize))
5226 {
5227 return false;
5228 }
5229
Corentin Wallez336129f2017-10-17 15:55:40 -04005230 gl::Buffer *pixelUnpackBuffer =
5231 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005232 if (pixelUnpackBuffer == nullptr)
5233 {
5234 if (dataSize < imageSize)
5235 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005236 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005237 }
5238 }
5239 return true;
5240}
5241
Jamie Madill5b772312018-03-08 20:28:32 -05005242bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005243 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005244 GLenum pname,
5245 bool pointerVersion,
5246 GLsizei *numParams)
5247{
5248 if (numParams)
5249 {
5250 *numParams = 0;
5251 }
5252
Corentin Walleze4477002017-12-01 14:39:58 -05005253 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005254 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005255 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005256 return false;
5257 }
5258
5259 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5260 if (!buffer)
5261 {
5262 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005263 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005264 return false;
5265 }
5266
5267 const Extensions &extensions = context->getExtensions();
5268
5269 switch (pname)
5270 {
5271 case GL_BUFFER_USAGE:
5272 case GL_BUFFER_SIZE:
5273 break;
5274
5275 case GL_BUFFER_ACCESS_OES:
5276 if (!extensions.mapBuffer)
5277 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005278 context->handleError(InvalidEnum()
5279 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005280 return false;
5281 }
5282 break;
5283
5284 case GL_BUFFER_MAPPED:
5285 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5286 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5287 !extensions.mapBufferRange)
5288 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005289 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5290 "GL_OES_mapbuffer or "
5291 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005292 return false;
5293 }
5294 break;
5295
5296 case GL_BUFFER_MAP_POINTER:
5297 if (!pointerVersion)
5298 {
5299 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005300 InvalidEnum()
5301 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005302 return false;
5303 }
5304 break;
5305
5306 case GL_BUFFER_ACCESS_FLAGS:
5307 case GL_BUFFER_MAP_OFFSET:
5308 case GL_BUFFER_MAP_LENGTH:
5309 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5310 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005311 context->handleError(InvalidEnum()
5312 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005313 return false;
5314 }
5315 break;
5316
5317 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005318 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005319 return false;
5320 }
5321
5322 // All buffer parameter queries return one value.
5323 if (numParams)
5324 {
5325 *numParams = 1;
5326 }
5327
5328 return true;
5329}
5330
5331bool ValidateGetRenderbufferParameterivBase(Context *context,
5332 GLenum target,
5333 GLenum pname,
5334 GLsizei *length)
5335{
5336 if (length)
5337 {
5338 *length = 0;
5339 }
5340
5341 if (target != GL_RENDERBUFFER)
5342 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005343 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005344 return false;
5345 }
5346
5347 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5348 if (renderbuffer == nullptr)
5349 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005350 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005351 return false;
5352 }
5353
5354 switch (pname)
5355 {
5356 case GL_RENDERBUFFER_WIDTH:
5357 case GL_RENDERBUFFER_HEIGHT:
5358 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5359 case GL_RENDERBUFFER_RED_SIZE:
5360 case GL_RENDERBUFFER_GREEN_SIZE:
5361 case GL_RENDERBUFFER_BLUE_SIZE:
5362 case GL_RENDERBUFFER_ALPHA_SIZE:
5363 case GL_RENDERBUFFER_DEPTH_SIZE:
5364 case GL_RENDERBUFFER_STENCIL_SIZE:
5365 break;
5366
5367 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5368 if (!context->getExtensions().framebufferMultisample)
5369 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005370 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005371 return false;
5372 }
5373 break;
5374
5375 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005376 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005377 return false;
5378 }
5379
5380 if (length)
5381 {
5382 *length = 1;
5383 }
5384 return true;
5385}
5386
5387bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5388{
5389 if (length)
5390 {
5391 *length = 0;
5392 }
5393
5394 if (GetValidShader(context, shader) == nullptr)
5395 {
5396 return false;
5397 }
5398
5399 switch (pname)
5400 {
5401 case GL_SHADER_TYPE:
5402 case GL_DELETE_STATUS:
5403 case GL_COMPILE_STATUS:
5404 case GL_INFO_LOG_LENGTH:
5405 case GL_SHADER_SOURCE_LENGTH:
5406 break;
5407
5408 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5409 if (!context->getExtensions().translatedShaderSource)
5410 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005411 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005412 return false;
5413 }
5414 break;
5415
5416 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005417 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005418 return false;
5419 }
5420
5421 if (length)
5422 {
5423 *length = 1;
5424 }
5425 return true;
5426}
5427
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005428bool ValidateGetTexParameterBase(Context *context,
5429 TextureType target,
5430 GLenum pname,
5431 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005432{
5433 if (length)
5434 {
5435 *length = 0;
5436 }
5437
5438 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5439 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005440 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005441 return false;
5442 }
5443
5444 if (context->getTargetTexture(target) == nullptr)
5445 {
5446 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005447 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005448 return false;
5449 }
5450
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005451 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5452 {
5453 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5454 return false;
5455 }
5456
Jamie Madillbe849e42017-05-02 15:49:00 -04005457 switch (pname)
5458 {
5459 case GL_TEXTURE_MAG_FILTER:
5460 case GL_TEXTURE_MIN_FILTER:
5461 case GL_TEXTURE_WRAP_S:
5462 case GL_TEXTURE_WRAP_T:
5463 break;
5464
5465 case GL_TEXTURE_USAGE_ANGLE:
5466 if (!context->getExtensions().textureUsage)
5467 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005468 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005469 return false;
5470 }
5471 break;
5472
5473 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005474 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005475 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005476 return false;
5477 }
5478 break;
5479
5480 case GL_TEXTURE_IMMUTABLE_FORMAT:
5481 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5482 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005483 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005484 return false;
5485 }
5486 break;
5487
5488 case GL_TEXTURE_WRAP_R:
5489 case GL_TEXTURE_IMMUTABLE_LEVELS:
5490 case GL_TEXTURE_SWIZZLE_R:
5491 case GL_TEXTURE_SWIZZLE_G:
5492 case GL_TEXTURE_SWIZZLE_B:
5493 case GL_TEXTURE_SWIZZLE_A:
5494 case GL_TEXTURE_BASE_LEVEL:
5495 case GL_TEXTURE_MAX_LEVEL:
5496 case GL_TEXTURE_MIN_LOD:
5497 case GL_TEXTURE_MAX_LOD:
5498 case GL_TEXTURE_COMPARE_MODE:
5499 case GL_TEXTURE_COMPARE_FUNC:
5500 if (context->getClientMajorVersion() < 3)
5501 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005502 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005503 return false;
5504 }
5505 break;
5506
5507 case GL_TEXTURE_SRGB_DECODE_EXT:
5508 if (!context->getExtensions().textureSRGBDecode)
5509 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005510 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005511 return false;
5512 }
5513 break;
5514
Yunchao Hebacaa712018-01-30 14:01:39 +08005515 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5516 if (context->getClientVersion() < Version(3, 1))
5517 {
5518 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5519 return false;
5520 }
5521 break;
5522
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005523 case GL_GENERATE_MIPMAP:
5524 case GL_TEXTURE_CROP_RECT_OES:
5525 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5526 // after GL_OES_draw_texture functionality implemented
5527 if (context->getClientMajorVersion() > 1)
5528 {
5529 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5530 return false;
5531 }
5532 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005533 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005534 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005535 return false;
5536 }
5537
5538 if (length)
5539 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005540 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005541 }
5542 return true;
5543}
5544
5545bool ValidateGetVertexAttribBase(Context *context,
5546 GLuint index,
5547 GLenum pname,
5548 GLsizei *length,
5549 bool pointer,
5550 bool pureIntegerEntryPoint)
5551{
5552 if (length)
5553 {
5554 *length = 0;
5555 }
5556
5557 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005559 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005560 return false;
5561 }
5562
5563 if (index >= context->getCaps().maxVertexAttributes)
5564 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005565 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005566 return false;
5567 }
5568
5569 if (pointer)
5570 {
5571 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5572 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005573 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005574 return false;
5575 }
5576 }
5577 else
5578 {
5579 switch (pname)
5580 {
5581 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5582 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5583 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5584 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5585 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5586 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5587 case GL_CURRENT_VERTEX_ATTRIB:
5588 break;
5589
5590 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5591 static_assert(
5592 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5593 "ANGLE extension enums not equal to GL enums.");
5594 if (context->getClientMajorVersion() < 3 &&
5595 !context->getExtensions().instancedArrays)
5596 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005597 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5598 "requires OpenGL ES 3.0 or "
5599 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005600 return false;
5601 }
5602 break;
5603
5604 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5605 if (context->getClientMajorVersion() < 3)
5606 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005607 context->handleError(
5608 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005609 return false;
5610 }
5611 break;
5612
5613 case GL_VERTEX_ATTRIB_BINDING:
5614 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5615 if (context->getClientVersion() < ES_3_1)
5616 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005617 context->handleError(InvalidEnum()
5618 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005619 return false;
5620 }
5621 break;
5622
5623 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005624 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005625 return false;
5626 }
5627 }
5628
5629 if (length)
5630 {
5631 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5632 {
5633 *length = 4;
5634 }
5635 else
5636 {
5637 *length = 1;
5638 }
5639 }
5640
5641 return true;
5642}
5643
Jamie Madill4928b7c2017-06-20 12:57:39 -04005644bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005645 GLint x,
5646 GLint y,
5647 GLsizei width,
5648 GLsizei height,
5649 GLenum format,
5650 GLenum type,
5651 GLsizei bufSize,
5652 GLsizei *length,
5653 GLsizei *columns,
5654 GLsizei *rows,
5655 void *pixels)
5656{
5657 if (length != nullptr)
5658 {
5659 *length = 0;
5660 }
5661 if (rows != nullptr)
5662 {
5663 *rows = 0;
5664 }
5665 if (columns != nullptr)
5666 {
5667 *columns = 0;
5668 }
5669
5670 if (width < 0 || height < 0)
5671 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005672 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005673 return false;
5674 }
5675
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005676 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005677
Jamie Madill427064d2018-04-13 16:20:34 -04005678 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005679 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005680 return false;
5681 }
5682
Jamie Madille98b1b52018-03-08 09:47:23 -05005683 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005684 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005685 return false;
5686 }
5687
Jamie Madill690c8eb2018-03-12 15:20:03 -04005688 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005689 ASSERT(framebuffer);
5690
5691 if (framebuffer->getReadBufferState() == GL_NONE)
5692 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005693 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005694 return false;
5695 }
5696
5697 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5698 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5699 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5700 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5701 // situation is an application error that would lead to a crash in ANGLE.
5702 if (readBuffer == nullptr)
5703 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005704 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005705 return false;
5706 }
5707
Martin Radev28031682017-07-28 14:47:56 +03005708 // ANGLE_multiview, Revision 1:
5709 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5710 // current read framebuffer is not NONE.
5711 if (readBuffer->getMultiviewLayout() != GL_NONE)
5712 {
5713 context->handleError(InvalidFramebufferOperation()
5714 << "Attempting to read from a multi-view framebuffer.");
5715 return false;
5716 }
5717
Geoff Lang280ba992017-04-18 16:30:58 -04005718 if (context->getExtensions().webglCompatibility)
5719 {
5720 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5721 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5722 // and type before validating the combination of format and type. However, the
5723 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5724 // verifies that GL_INVALID_OPERATION is generated.
5725 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5726 // dEQP/WebGL.
5727 if (!ValidReadPixelsFormatEnum(context, format))
5728 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005729 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005730 return false;
5731 }
5732
5733 if (!ValidReadPixelsTypeEnum(context, type))
5734 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005735 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005736 return false;
5737 }
5738 }
5739
Jamie Madill690c8eb2018-03-12 15:20:03 -04005740 GLenum currentFormat = GL_NONE;
5741 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5742
5743 GLenum currentType = GL_NONE;
5744 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5745
Jamie Madillbe849e42017-05-02 15:49:00 -04005746 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5747
5748 bool validFormatTypeCombination =
5749 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5750
5751 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5752 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005753 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005754 return false;
5755 }
5756
5757 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005758 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005759 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5760 {
5761 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005762 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005763 return false;
5764 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005765 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5766 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5767 {
5768 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5769 return false;
5770 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005771
5772 // .. the data would be packed to the buffer object such that the memory writes required
5773 // would exceed the data store size.
5774 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5775 const gl::Extents size(width, height, 1);
5776 const auto &pack = context->getGLState().getPackState();
5777
Jamie Madillca2ff382018-07-11 09:01:17 -04005778 GLuint endByte = 0;
5779 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005780 {
Jamie Madillca2ff382018-07-11 09:01:17 -04005781 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005782 return false;
5783 }
5784
Jamie Madillbe849e42017-05-02 15:49:00 -04005785 if (bufSize >= 0)
5786 {
5787 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5788 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005789 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005790 return false;
5791 }
5792 }
5793
5794 if (pixelPackBuffer != nullptr)
5795 {
5796 CheckedNumeric<size_t> checkedEndByte(endByte);
5797 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5798 checkedEndByte += checkedOffset;
5799
5800 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5801 {
5802 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005803 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005804 return false;
5805 }
5806 }
5807
5808 if (pixelPackBuffer == nullptr && length != nullptr)
5809 {
5810 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5811 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005812 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005813 return false;
5814 }
5815
5816 *length = static_cast<GLsizei>(endByte);
5817 }
5818
Geoff Langa953b522018-02-21 16:56:23 -05005819 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005820 angle::CheckedNumeric<int> clippedExtent(length);
5821 if (start < 0)
5822 {
5823 // "subtract" the area that is less than 0
5824 clippedExtent += start;
5825 }
5826
Geoff Langa953b522018-02-21 16:56:23 -05005827 angle::CheckedNumeric<int> readExtent = start;
5828 readExtent += length;
5829 if (!readExtent.IsValid())
5830 {
5831 return false;
5832 }
5833
5834 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005835 {
5836 // Subtract the region to the right of the read buffer
5837 clippedExtent -= (readExtent - bufferSize);
5838 }
5839
5840 if (!clippedExtent.IsValid())
5841 {
Geoff Langa953b522018-02-21 16:56:23 -05005842 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005843 }
5844
Geoff Langa953b522018-02-21 16:56:23 -05005845 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5846 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005847 };
5848
Geoff Langa953b522018-02-21 16:56:23 -05005849 GLsizei writtenColumns = 0;
5850 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5851 {
5852 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5853 return false;
5854 }
5855
5856 GLsizei writtenRows = 0;
5857 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5858 {
5859 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5860 return false;
5861 }
5862
Jamie Madillbe849e42017-05-02 15:49:00 -04005863 if (columns != nullptr)
5864 {
Geoff Langa953b522018-02-21 16:56:23 -05005865 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005866 }
5867
5868 if (rows != nullptr)
5869 {
Geoff Langa953b522018-02-21 16:56:23 -05005870 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005871 }
5872
5873 return true;
5874}
5875
5876template <typename ParamType>
5877bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005878 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005879 GLenum pname,
5880 GLsizei bufSize,
5881 const ParamType *params)
5882{
5883 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5884 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005885 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005886 return false;
5887 }
5888
5889 if (context->getTargetTexture(target) == nullptr)
5890 {
5891 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005892 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005893 return false;
5894 }
5895
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005896 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005897 if (bufSize >= 0 && bufSize < minBufSize)
5898 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005899 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005900 return false;
5901 }
5902
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005903 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5904 {
5905 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5906 return false;
5907 }
5908
Jamie Madillbe849e42017-05-02 15:49:00 -04005909 switch (pname)
5910 {
5911 case GL_TEXTURE_WRAP_R:
5912 case GL_TEXTURE_SWIZZLE_R:
5913 case GL_TEXTURE_SWIZZLE_G:
5914 case GL_TEXTURE_SWIZZLE_B:
5915 case GL_TEXTURE_SWIZZLE_A:
5916 case GL_TEXTURE_BASE_LEVEL:
5917 case GL_TEXTURE_MAX_LEVEL:
5918 case GL_TEXTURE_COMPARE_MODE:
5919 case GL_TEXTURE_COMPARE_FUNC:
5920 case GL_TEXTURE_MIN_LOD:
5921 case GL_TEXTURE_MAX_LOD:
5922 if (context->getClientMajorVersion() < 3)
5923 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005924 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005925 return false;
5926 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005927 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005928 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005929 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5930 "available without "
5931 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005932 return false;
5933 }
5934 break;
5935
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005936 case GL_GENERATE_MIPMAP:
5937 case GL_TEXTURE_CROP_RECT_OES:
5938 if (context->getClientMajorVersion() > 1)
5939 {
5940 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5941 return false;
5942 }
5943 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005944 default:
5945 break;
5946 }
5947
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005948 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005949 {
5950 switch (pname)
5951 {
5952 case GL_TEXTURE_MIN_FILTER:
5953 case GL_TEXTURE_MAG_FILTER:
5954 case GL_TEXTURE_WRAP_S:
5955 case GL_TEXTURE_WRAP_T:
5956 case GL_TEXTURE_WRAP_R:
5957 case GL_TEXTURE_MIN_LOD:
5958 case GL_TEXTURE_MAX_LOD:
5959 case GL_TEXTURE_COMPARE_MODE:
5960 case GL_TEXTURE_COMPARE_FUNC:
5961 context->handleError(InvalidEnum()
5962 << "Invalid parameter for 2D multisampled textures.");
5963 return false;
5964 }
5965 }
5966
Jamie Madillbe849e42017-05-02 15:49:00 -04005967 switch (pname)
5968 {
5969 case GL_TEXTURE_WRAP_S:
5970 case GL_TEXTURE_WRAP_T:
5971 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005972 {
5973 bool restrictedWrapModes =
5974 target == TextureType::External || target == TextureType::Rectangle;
5975 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005976 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005977 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005978 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005979 }
5980 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005981
5982 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005983 {
5984 bool restrictedMinFilter =
5985 target == TextureType::External || target == TextureType::Rectangle;
5986 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005987 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005988 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005989 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005990 }
5991 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005992
5993 case GL_TEXTURE_MAG_FILTER:
5994 if (!ValidateTextureMagFilterValue(context, params))
5995 {
5996 return false;
5997 }
5998 break;
5999
6000 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04006001 if (!context->getExtensions().textureUsage)
6002 {
6003 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6004 return false;
6005 }
6006
Jamie Madillbe849e42017-05-02 15:49:00 -04006007 switch (ConvertToGLenum(params[0]))
6008 {
6009 case GL_NONE:
6010 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
6011 break;
6012
6013 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006014 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006015 return false;
6016 }
6017 break;
6018
6019 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07006020 {
6021 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6022 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04006023 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07006024 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04006025 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07006026 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
6027 }
6028 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006029
6030 case GL_TEXTURE_MIN_LOD:
6031 case GL_TEXTURE_MAX_LOD:
6032 // any value is permissible
6033 break;
6034
6035 case GL_TEXTURE_COMPARE_MODE:
6036 if (!ValidateTextureCompareModeValue(context, params))
6037 {
6038 return false;
6039 }
6040 break;
6041
6042 case GL_TEXTURE_COMPARE_FUNC:
6043 if (!ValidateTextureCompareFuncValue(context, params))
6044 {
6045 return false;
6046 }
6047 break;
6048
6049 case GL_TEXTURE_SWIZZLE_R:
6050 case GL_TEXTURE_SWIZZLE_G:
6051 case GL_TEXTURE_SWIZZLE_B:
6052 case GL_TEXTURE_SWIZZLE_A:
6053 switch (ConvertToGLenum(params[0]))
6054 {
6055 case GL_RED:
6056 case GL_GREEN:
6057 case GL_BLUE:
6058 case GL_ALPHA:
6059 case GL_ZERO:
6060 case GL_ONE:
6061 break;
6062
6063 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006064 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006065 return false;
6066 }
6067 break;
6068
6069 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006070 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006071 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006072 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006073 return false;
6074 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006075 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006076 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006077 context->handleError(InvalidOperation()
6078 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006079 return false;
6080 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006081 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08006082 {
6083 context->handleError(InvalidOperation()
6084 << "Base level must be 0 for multisampled textures.");
6085 return false;
6086 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006087 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006088 {
6089 context->handleError(InvalidOperation()
6090 << "Base level must be 0 for rectangle textures.");
6091 return false;
6092 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006093 break;
6094
6095 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006096 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006097 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006098 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006099 return false;
6100 }
6101 break;
6102
6103 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6104 if (context->getClientVersion() < Version(3, 1))
6105 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006106 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006107 return false;
6108 }
6109 switch (ConvertToGLenum(params[0]))
6110 {
6111 case GL_DEPTH_COMPONENT:
6112 case GL_STENCIL_INDEX:
6113 break;
6114
6115 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006116 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006117 return false;
6118 }
6119 break;
6120
6121 case GL_TEXTURE_SRGB_DECODE_EXT:
6122 if (!ValidateTextureSRGBDecodeValue(context, params))
6123 {
6124 return false;
6125 }
6126 break;
6127
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006128 case GL_GENERATE_MIPMAP:
6129 case GL_TEXTURE_CROP_RECT_OES:
6130 if (context->getClientMajorVersion() > 1)
6131 {
6132 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
6133 return false;
6134 }
6135 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006136 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006137 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006138 return false;
6139 }
6140
6141 return true;
6142}
6143
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006144template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6145template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006146
Jamie Madill5b772312018-03-08 20:28:32 -05006147bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006148{
6149 if (index >= MAX_VERTEX_ATTRIBS)
6150 {
6151 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6152 return false;
6153 }
6154
6155 return true;
6156}
6157
6158bool ValidateGetActiveUniformBlockivBase(Context *context,
6159 GLuint program,
6160 GLuint uniformBlockIndex,
6161 GLenum pname,
6162 GLsizei *length)
6163{
6164 if (length)
6165 {
6166 *length = 0;
6167 }
6168
6169 if (context->getClientMajorVersion() < 3)
6170 {
6171 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6172 return false;
6173 }
6174
6175 Program *programObject = GetValidProgram(context, program);
6176 if (!programObject)
6177 {
6178 return false;
6179 }
6180
6181 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6182 {
6183 context->handleError(InvalidValue()
6184 << "uniformBlockIndex exceeds active uniform block count.");
6185 return false;
6186 }
6187
6188 switch (pname)
6189 {
6190 case GL_UNIFORM_BLOCK_BINDING:
6191 case GL_UNIFORM_BLOCK_DATA_SIZE:
6192 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6193 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6194 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6195 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6196 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6197 break;
6198
6199 default:
6200 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6201 return false;
6202 }
6203
6204 if (length)
6205 {
6206 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6207 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006208 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006209 programObject->getUniformBlockByIndex(uniformBlockIndex);
6210 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6211 }
6212 else
6213 {
6214 *length = 1;
6215 }
6216 }
6217
6218 return true;
6219}
6220
Jamie Madill9696d072017-08-26 23:19:57 -04006221template <typename ParamType>
6222bool ValidateSamplerParameterBase(Context *context,
6223 GLuint sampler,
6224 GLenum pname,
6225 GLsizei bufSize,
6226 ParamType *params)
6227{
6228 if (context->getClientMajorVersion() < 3)
6229 {
6230 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6231 return false;
6232 }
6233
6234 if (!context->isSampler(sampler))
6235 {
6236 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6237 return false;
6238 }
6239
6240 const GLsizei minBufSize = 1;
6241 if (bufSize >= 0 && bufSize < minBufSize)
6242 {
6243 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6244 return false;
6245 }
6246
6247 switch (pname)
6248 {
6249 case GL_TEXTURE_WRAP_S:
6250 case GL_TEXTURE_WRAP_T:
6251 case GL_TEXTURE_WRAP_R:
6252 if (!ValidateTextureWrapModeValue(context, params, false))
6253 {
6254 return false;
6255 }
6256 break;
6257
6258 case GL_TEXTURE_MIN_FILTER:
6259 if (!ValidateTextureMinFilterValue(context, params, false))
6260 {
6261 return false;
6262 }
6263 break;
6264
6265 case GL_TEXTURE_MAG_FILTER:
6266 if (!ValidateTextureMagFilterValue(context, params))
6267 {
6268 return false;
6269 }
6270 break;
6271
6272 case GL_TEXTURE_MIN_LOD:
6273 case GL_TEXTURE_MAX_LOD:
6274 // any value is permissible
6275 break;
6276
6277 case GL_TEXTURE_COMPARE_MODE:
6278 if (!ValidateTextureCompareModeValue(context, params))
6279 {
6280 return false;
6281 }
6282 break;
6283
6284 case GL_TEXTURE_COMPARE_FUNC:
6285 if (!ValidateTextureCompareFuncValue(context, params))
6286 {
6287 return false;
6288 }
6289 break;
6290
6291 case GL_TEXTURE_SRGB_DECODE_EXT:
6292 if (!ValidateTextureSRGBDecodeValue(context, params))
6293 {
6294 return false;
6295 }
6296 break;
6297
Luc Ferron1b1a8642018-01-23 15:12:01 -05006298 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6299 {
6300 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6301 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6302 {
6303 return false;
6304 }
6305 }
6306 break;
6307
Jamie Madill9696d072017-08-26 23:19:57 -04006308 default:
6309 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6310 return false;
6311 }
6312
6313 return true;
6314}
6315
6316template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6317template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6318
6319bool ValidateGetSamplerParameterBase(Context *context,
6320 GLuint sampler,
6321 GLenum pname,
6322 GLsizei *length)
6323{
6324 if (length)
6325 {
6326 *length = 0;
6327 }
6328
6329 if (context->getClientMajorVersion() < 3)
6330 {
6331 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6332 return false;
6333 }
6334
6335 if (!context->isSampler(sampler))
6336 {
6337 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6338 return false;
6339 }
6340
6341 switch (pname)
6342 {
6343 case GL_TEXTURE_WRAP_S:
6344 case GL_TEXTURE_WRAP_T:
6345 case GL_TEXTURE_WRAP_R:
6346 case GL_TEXTURE_MIN_FILTER:
6347 case GL_TEXTURE_MAG_FILTER:
6348 case GL_TEXTURE_MIN_LOD:
6349 case GL_TEXTURE_MAX_LOD:
6350 case GL_TEXTURE_COMPARE_MODE:
6351 case GL_TEXTURE_COMPARE_FUNC:
6352 break;
6353
Luc Ferron1b1a8642018-01-23 15:12:01 -05006354 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6355 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6356 {
6357 return false;
6358 }
6359 break;
6360
Jamie Madill9696d072017-08-26 23:19:57 -04006361 case GL_TEXTURE_SRGB_DECODE_EXT:
6362 if (!context->getExtensions().textureSRGBDecode)
6363 {
6364 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6365 return false;
6366 }
6367 break;
6368
6369 default:
6370 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6371 return false;
6372 }
6373
6374 if (length)
6375 {
6376 *length = 1;
6377 }
6378 return true;
6379}
6380
6381bool ValidateGetInternalFormativBase(Context *context,
6382 GLenum target,
6383 GLenum internalformat,
6384 GLenum pname,
6385 GLsizei bufSize,
6386 GLsizei *numParams)
6387{
6388 if (numParams)
6389 {
6390 *numParams = 0;
6391 }
6392
6393 if (context->getClientMajorVersion() < 3)
6394 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006395 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006396 return false;
6397 }
6398
6399 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006400 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006401 {
6402 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6403 return false;
6404 }
6405
6406 switch (target)
6407 {
6408 case GL_RENDERBUFFER:
6409 break;
6410
6411 case GL_TEXTURE_2D_MULTISAMPLE:
6412 if (context->getClientVersion() < ES_3_1)
6413 {
6414 context->handleError(InvalidOperation()
6415 << "Texture target requires at least OpenGL ES 3.1.");
6416 return false;
6417 }
6418 break;
6419
6420 default:
6421 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6422 return false;
6423 }
6424
6425 if (bufSize < 0)
6426 {
6427 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6428 return false;
6429 }
6430
6431 GLsizei maxWriteParams = 0;
6432 switch (pname)
6433 {
6434 case GL_NUM_SAMPLE_COUNTS:
6435 maxWriteParams = 1;
6436 break;
6437
6438 case GL_SAMPLES:
6439 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6440 break;
6441
6442 default:
6443 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6444 return false;
6445 }
6446
6447 if (numParams)
6448 {
6449 // glGetInternalFormativ will not overflow bufSize
6450 *numParams = std::min(bufSize, maxWriteParams);
6451 }
6452
6453 return true;
6454}
6455
Jamie Madille98b1b52018-03-08 09:47:23 -05006456bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6457{
Jamie Madill427064d2018-04-13 16:20:34 -04006458 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006459 {
6460 context->handleError(InvalidOperation());
6461 return false;
6462 }
6463 return true;
6464}
6465
Lingfeng Yang038dd532018-03-29 17:31:52 -07006466bool ValidateMultitextureUnit(Context *context, GLenum texture)
6467{
6468 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6469 {
6470 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6471 return false;
6472 }
6473 return true;
6474}
6475
Jamie Madillc29968b2016-01-20 11:17:23 -05006476} // namespace gl