blob: a3e2c62c89c613a93afc8483b7f7632daf07ebd1 [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();
Jamie Madilldc358af2018-07-31 11:22:13 -040086 const VertexArray *vao = state.getVertexArray();
Jamie Madill1ca74672015-07-21 15:14:11 -040087
Corentin Wallez327411e2016-12-09 11:09:17 -050088 bool webglCompatibility = context->getExtensions().webglCompatibility;
89
Jamie Madilldc358af2018-07-31 11:22:13 -040090 if (context->getStateCache().hasAnyEnabledClientAttrib())
Jamie Madill51af38b2018-04-15 08:50:56 -040091 {
92 if (webglCompatibility || !state.areClientArraysEnabled())
93 {
94 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
95 // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
96 // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
97 // to drawArrays or drawElements will generate an INVALID_OPERATION error.
98 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
99 return false;
100 }
101 else if (vao->hasEnabledNullPointerClientArray())
102 {
103 // This is an application error that would normally result in a crash, but we catch it
104 // and return an error
105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
106 return false;
107 }
108 }
109
110 // If we're drawing zero vertices, we have enough data.
111 if (vertexCount <= 0 || primcount <= 0)
112 {
113 return true;
114 }
115
Jamie Madill231c7f52017-04-26 13:45:37 -0400116 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800117 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madill51af38b2018-04-15 08:50:56 -0400118
Jamie Madilldc358af2018-07-31 11:22:13 -0400119 const AttributesMask &activeAttribs = context->getStateCache().getActiveBufferedAttribsMask();
Jamie Madill51af38b2018-04-15 08:50:56 -0400120
121 for (size_t attributeIndex : activeAttribs)
Jamie Madill1ca74672015-07-21 15:14:11 -0400122 {
123 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Jamie Madill51af38b2018-04-15 08:50:56 -0400124 ASSERT(attrib.enabled);
Corentin Wallez672f7f32017-06-15 17:42:17 -0400125
Lingfeng Yang038dd532018-03-29 17:31:52 -0700126 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
Jamie Madill2eb65032018-07-30 10:25:57 -0400127 ASSERT(context->isGLES1() || program->isAttribLocationActive(attributeIndex));
Corentin Wallezfd456442016-12-21 17:57:00 -0500128
Jamie Madill02c9c042018-04-17 13:43:48 -0400129 GLint maxVertexElement = maxVertex;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300130 GLuint divisor = binding.getDivisor();
Jamie Madill02c9c042018-04-17 13:43:48 -0400131 if (divisor != 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500132 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300133 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500134 }
135
136 // We do manual overflow checks here instead of using safe_math.h because it was
137 // a bottleneck. Thanks to some properties of GL we know inequalities that can
138 // help us make the overflow checks faster.
139
140 // The max possible attribSize is 16 for a vector of 4 32 bit values.
141 constexpr uint64_t kMaxAttribSize = 16;
142 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
143 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
144
145 // We know attribStride is given as a GLsizei which is typedefed to int.
146 // We also know an upper bound for attribSize.
Jamie Madill02c9c042018-04-17 13:43:48 -0400147 static_assert(std::is_same<int, GLsizei>::value, "Unexpected type");
148 ASSERT(ComputeVertexAttributeStride(attrib, binding) == binding.getStride());
149 uint64_t attribStride = binding.getStride();
150 ASSERT(attribStride <= kIntMax && ComputeVertexAttributeTypeSize(attrib) <= kMaxAttribSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500151
Jamie Madill02c9c042018-04-17 13:43:48 -0400152 // Computing the product of two 32-bit ints will fit in 64 bits without overflow.
153 static_assert(kIntMax * kIntMax < kUint64Max, "Unexpected overflow");
154 uint64_t attribDataSizeMinusAttribSize = maxVertexElement * attribStride;
Corentin Wallezfd456442016-12-21 17:57:00 -0500155
156 // An overflow can happen when adding the offset, check for it.
Jamie Madill02c9c042018-04-17 13:43:48 -0400157 if (attribDataSizeMinusAttribSize > kUint64Max - attrib.cachedSizePlusRelativeOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500158 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700159 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500160 return false;
161 }
Corentin Wallezfd456442016-12-21 17:57:00 -0500162
163 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
Jamie Madill02c9c042018-04-17 13:43:48 -0400164 // We can return INVALID_OPERATION if our array buffer does not have enough backing data.
165 if (attribDataSizeMinusAttribSize + attrib.cachedSizePlusRelativeOffset >
166 binding.getCachedBufferSizeMinusOffset())
Corentin Wallezfd456442016-12-21 17:57:00 -0500167 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700168 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500169 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400170 }
Jamie Madill02c9c042018-04-17 13:43:48 -0400171 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800172
Jamie Madill7267aa62018-04-17 15:28:21 -0400173 if (webglCompatibility && vao->hasTransformFeedbackBindingConflict(activeAttribs))
Jamie Madill02c9c042018-04-17 13:43:48 -0400174 {
Jamie Madill7267aa62018-04-17 15:28:21 -0400175 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexBufferBoundForTransformFeedback);
176 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400177 }
178
179 return true;
180}
181
Jamie Madill5b772312018-03-08 20:28:32 -0500182bool ValidReadPixelsTypeEnum(Context *context, GLenum type)
Geoff Lang280ba992017-04-18 16:30:58 -0400183{
184 switch (type)
185 {
186 // Types referenced in Table 3.4 of the ES 2.0.25 spec
187 case GL_UNSIGNED_BYTE:
188 case GL_UNSIGNED_SHORT_4_4_4_4:
189 case GL_UNSIGNED_SHORT_5_5_5_1:
190 case GL_UNSIGNED_SHORT_5_6_5:
191 return context->getClientVersion() >= ES_2_0;
192
193 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
194 case GL_BYTE:
195 case GL_INT:
196 case GL_SHORT:
197 case GL_UNSIGNED_INT:
198 case GL_UNSIGNED_INT_10F_11F_11F_REV:
199 case GL_UNSIGNED_INT_24_8:
200 case GL_UNSIGNED_INT_2_10_10_10_REV:
201 case GL_UNSIGNED_INT_5_9_9_9_REV:
202 case GL_UNSIGNED_SHORT:
203 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
204 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
205 return context->getClientVersion() >= ES_3_0;
206
207 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400208 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
209 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400210
211 case GL_HALF_FLOAT:
212 return context->getClientVersion() >= ES_3_0 ||
213 context->getExtensions().textureHalfFloat;
214
215 case GL_HALF_FLOAT_OES:
216 return context->getExtensions().colorBufferHalfFloat;
217
218 default:
219 return false;
220 }
221}
222
Jamie Madill5b772312018-03-08 20:28:32 -0500223bool ValidReadPixelsFormatEnum(Context *context, GLenum format)
Geoff Lang280ba992017-04-18 16:30:58 -0400224{
225 switch (format)
226 {
227 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
228 case GL_RGBA:
229 case GL_RGB:
230 case GL_ALPHA:
231 return context->getClientVersion() >= ES_2_0;
232
233 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
234 case GL_RG:
235 case GL_RED:
236 case GL_RGBA_INTEGER:
237 case GL_RGB_INTEGER:
238 case GL_RG_INTEGER:
239 case GL_RED_INTEGER:
240 return context->getClientVersion() >= ES_3_0;
241
242 case GL_SRGB_ALPHA_EXT:
243 case GL_SRGB_EXT:
244 return context->getExtensions().sRGB;
245
246 case GL_BGRA_EXT:
247 return context->getExtensions().readFormatBGRA;
248
249 default:
250 return false;
251 }
252}
253
Jamie Madill5b772312018-03-08 20:28:32 -0500254bool ValidReadPixelsFormatType(Context *context,
Geoff Langf607c602016-09-21 11:46:48 -0400255 GLenum framebufferComponentType,
256 GLenum format,
257 GLenum type)
258{
259 switch (framebufferComponentType)
260 {
261 case GL_UNSIGNED_NORMALIZED:
262 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
263 // ReadPixels with BGRA even if the extension is not present
264 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
265 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
266 type == GL_UNSIGNED_BYTE);
267
268 case GL_SIGNED_NORMALIZED:
269 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
270
271 case GL_INT:
272 return (format == GL_RGBA_INTEGER && type == GL_INT);
273
274 case GL_UNSIGNED_INT:
275 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
276
277 case GL_FLOAT:
278 return (format == GL_RGBA && type == GL_FLOAT);
279
280 default:
281 UNREACHABLE();
282 return false;
283 }
284}
285
Geoff Langc1984ed2016-10-07 12:41:00 -0400286template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400287bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400288{
289 switch (ConvertToGLenum(params[0]))
290 {
291 case GL_CLAMP_TO_EDGE:
292 break;
293
294 case GL_REPEAT:
295 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400296 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400297 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400298 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700299 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400300 return false;
301 }
302 break;
303
304 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700305 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400306 return false;
307 }
308
309 return true;
310}
311
312template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400313bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400314{
315 switch (ConvertToGLenum(params[0]))
316 {
317 case GL_NEAREST:
318 case GL_LINEAR:
319 break;
320
321 case GL_NEAREST_MIPMAP_NEAREST:
322 case GL_LINEAR_MIPMAP_NEAREST:
323 case GL_NEAREST_MIPMAP_LINEAR:
324 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400325 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400326 {
327 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700328 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400329 return false;
330 }
331 break;
332
333 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700334 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400335 return false;
336 }
337
338 return true;
339}
340
341template <typename ParamType>
342bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
343{
344 switch (ConvertToGLenum(params[0]))
345 {
346 case GL_NEAREST:
347 case GL_LINEAR:
348 break;
349
350 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700351 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400352 return false;
353 }
354
355 return true;
356}
357
358template <typename ParamType>
359bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
360{
361 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
362 switch (ConvertToGLenum(params[0]))
363 {
364 case GL_NONE:
365 case GL_COMPARE_REF_TO_TEXTURE:
366 break;
367
368 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700369 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400370 return false;
371 }
372
373 return true;
374}
375
376template <typename ParamType>
377bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
378{
379 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
380 switch (ConvertToGLenum(params[0]))
381 {
382 case GL_LEQUAL:
383 case GL_GEQUAL:
384 case GL_LESS:
385 case GL_GREATER:
386 case GL_EQUAL:
387 case GL_NOTEQUAL:
388 case GL_ALWAYS:
389 case GL_NEVER:
390 break;
391
392 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700393 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400394 return false;
395 }
396
397 return true;
398}
399
400template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700401bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
402{
403 if (!context->getExtensions().textureSRGBDecode)
404 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700405 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700406 return false;
407 }
408
409 switch (ConvertToGLenum(params[0]))
410 {
411 case GL_DECODE_EXT:
412 case GL_SKIP_DECODE_EXT:
413 break;
414
415 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700416 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700417 return false;
418 }
419
420 return true;
421}
422
Luc Ferron1b1a8642018-01-23 15:12:01 -0500423bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
424{
425 if (!context->getExtensions().textureFilterAnisotropic)
426 {
427 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
428 return false;
429 }
430
431 return true;
432}
433
434bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
435{
436 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
437 {
438 return false;
439 }
440
441 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
442
443 if (paramValue < 1 || paramValue > largest)
444 {
445 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
446 return false;
447 }
448
449 return true;
450}
451
Jamie Madill5b772312018-03-08 20:28:32 -0500452bool ValidateFragmentShaderColorBufferTypeMatch(Context *context)
Geoff Lange0cff192017-05-30 13:04:56 -0400453{
454 const Program *program = context->getGLState().getProgram();
455 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
456
Brandon Jonesc405ae72017-12-06 14:15:03 -0800457 if (!ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
458 framebuffer->getDrawBufferTypeMask().to_ulong(),
459 program->getActiveOutputVariables().to_ulong(),
460 framebuffer->getDrawBufferMask().to_ulong()))
Geoff Lange0cff192017-05-30 13:04:56 -0400461 {
Brandon Jones76746f92017-11-22 11:44:41 -0800462 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
463 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400464 }
465
466 return true;
467}
468
Jamie Madill5b772312018-03-08 20:28:32 -0500469bool ValidateVertexShaderAttributeTypeMatch(Context *context)
Geoff Lang9ab5b822017-05-30 16:19:23 -0400470{
Lingfeng Yang038dd532018-03-29 17:31:52 -0700471 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400472 const Program *program = context->getGLState().getProgram();
473 const VertexArray *vao = context->getGLState().getVertexArray();
474
Brandon Jonesc405ae72017-12-06 14:15:03 -0800475 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
476 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
477 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
478
479 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
480 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
481 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
482
483 if (!ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
484 program->getAttributesMask().to_ulong(), 0xFFFF))
Geoff Lang9ab5b822017-05-30 16:19:23 -0400485 {
Brandon Jonesc405ae72017-12-06 14:15:03 -0800486 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexShaderTypeMismatch);
487 return false;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400488 }
Geoff Lang9ab5b822017-05-30 16:19:23 -0400489 return true;
490}
491
Jamie Madill493f9572018-05-24 19:52:15 -0400492bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
493 PrimitiveMode geometryShaderInputPrimitiveType)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800494{
495 // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
Jamie Madill493f9572018-05-24 19:52:15 -0400496 switch (drawMode)
Jiawei Shaofccebff2018-03-08 13:51:02 +0800497 {
Jamie Madill493f9572018-05-24 19:52:15 -0400498 case PrimitiveMode::Points:
499 return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
500 case PrimitiveMode::Lines:
501 case PrimitiveMode::LineStrip:
502 case PrimitiveMode::LineLoop:
503 return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
504 case PrimitiveMode::LinesAdjacency:
505 case PrimitiveMode::LineStripAdjacency:
506 return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
507 case PrimitiveMode::Triangles:
508 case PrimitiveMode::TriangleFan:
509 case PrimitiveMode::TriangleStrip:
510 return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
511 case PrimitiveMode::TrianglesAdjacency:
512 case PrimitiveMode::TriangleStripAdjacency:
513 return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
Jiawei Shaofccebff2018-03-08 13:51:02 +0800514 default:
515 UNREACHABLE();
516 return false;
517 }
518}
519
Lingfeng Yangf97641c2018-06-21 19:22:45 -0700520// GLES1 texture parameters are a small subset of the others
521bool IsValidGLES1TextureParameter(GLenum pname)
522{
523 switch (pname)
524 {
525 case GL_TEXTURE_MAG_FILTER:
526 case GL_TEXTURE_MIN_FILTER:
527 case GL_TEXTURE_WRAP_S:
528 case GL_TEXTURE_WRAP_T:
529 case GL_TEXTURE_WRAP_R:
530 case GL_GENERATE_MIPMAP:
531 case GL_TEXTURE_CROP_RECT_OES:
532 return true;
533 default:
534 return false;
535 }
536}
537
Geoff Langf41a7152016-09-19 15:11:17 -0400538} // anonymous namespace
539
Brandon Jonesd1049182018-03-28 10:02:20 -0700540void SetRobustLengthParam(GLsizei *length, GLsizei value)
541{
542 if (length)
543 {
544 *length = value;
545 }
546}
547
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500548bool IsETC2EACFormat(const GLenum format)
549{
550 // ES 3.1, Table 8.19
551 switch (format)
552 {
553 case GL_COMPRESSED_R11_EAC:
554 case GL_COMPRESSED_SIGNED_R11_EAC:
555 case GL_COMPRESSED_RG11_EAC:
556 case GL_COMPRESSED_SIGNED_RG11_EAC:
557 case GL_COMPRESSED_RGB8_ETC2:
558 case GL_COMPRESSED_SRGB8_ETC2:
559 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
560 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
561 case GL_COMPRESSED_RGBA8_ETC2_EAC:
562 case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
563 return true;
564
565 default:
566 return false;
567 }
568}
569
Jamie Madill5b772312018-03-08 20:28:32 -0500570bool ValidTextureTarget(const Context *context, TextureType type)
Jamie Madill35d15012013-10-07 10:46:37 -0400571{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800572 switch (type)
Jamie Madill35d15012013-10-07 10:46:37 -0400573 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800574 case TextureType::_2D:
575 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800576 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400577
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800578 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400579 return context->getExtensions().textureRectangle;
580
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800581 case TextureType::_3D:
582 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800583 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500584
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800585 case TextureType::_2DMultisample:
He Yunchaoced53ae2016-11-29 15:00:51 +0800586 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400587
He Yunchaoced53ae2016-11-29 15:00:51 +0800588 default:
589 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500590 }
Jamie Madill35d15012013-10-07 10:46:37 -0400591}
592
Jamie Madill5b772312018-03-08 20:28:32 -0500593bool ValidTexture2DTarget(const Context *context, TextureType type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500594{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800595 switch (type)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500596 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800597 case TextureType::_2D:
598 case TextureType::CubeMap:
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500599 return true;
600
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800601 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400602 return context->getExtensions().textureRectangle;
603
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500604 default:
605 return false;
606 }
607}
608
Jamie Madill5b772312018-03-08 20:28:32 -0500609bool ValidTexture3DTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500610{
611 switch (target)
612 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800613 case TextureType::_3D:
614 case TextureType::_2DArray:
Martin Radev1be913c2016-07-11 17:59:16 +0300615 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500616
617 default:
618 return false;
619 }
620}
621
Ian Ewellbda75592016-04-18 17:25:54 -0400622// Most texture GL calls are not compatible with external textures, so we have a separate validation
623// function for use in the GL calls that do
Jamie Madill5b772312018-03-08 20:28:32 -0500624bool ValidTextureExternalTarget(const Context *context, TextureType target)
Ian Ewellbda75592016-04-18 17:25:54 -0400625{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800626 return (target == TextureType::External) &&
Ian Ewellbda75592016-04-18 17:25:54 -0400627 (context->getExtensions().eglImageExternal ||
628 context->getExtensions().eglStreamConsumerExternal);
629}
630
Shannon Woods4dfed832014-03-17 20:03:39 -0400631// This function differs from ValidTextureTarget in that the target must be
632// usable as the destination of a 2D operation-- so a cube face is valid, but
633// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400634// Note: duplicate of IsInternalTextureTarget
Jamie Madill5b772312018-03-08 20:28:32 -0500635bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400636{
637 switch (target)
638 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800639 case TextureTarget::_2D:
640 case TextureTarget::CubeMapNegativeX:
641 case TextureTarget::CubeMapNegativeY:
642 case TextureTarget::CubeMapNegativeZ:
643 case TextureTarget::CubeMapPositiveX:
644 case TextureTarget::CubeMapPositiveY:
645 case TextureTarget::CubeMapPositiveZ:
He Yunchaoced53ae2016-11-29 15:00:51 +0800646 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800647 case TextureTarget::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400648 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800649 default:
650 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500651 }
652}
653
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800654bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400655 PrimitiveMode transformFeedbackPrimitiveMode,
656 PrimitiveMode renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800657{
658 ASSERT(context);
659
660 if (!context->getExtensions().geometryShader)
661 {
662 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
663 // that does not match the current transform feedback object's draw mode (if transform
664 // feedback is active), (3.0.2, section 2.14, pg 86)
665 return transformFeedbackPrimitiveMode == renderPrimitiveMode;
666 }
667
668 // [GL_EXT_geometry_shader] Table 12.1gs
Jamie Madill493f9572018-05-24 19:52:15 -0400669 switch (renderPrimitiveMode)
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800670 {
Jamie Madill493f9572018-05-24 19:52:15 -0400671 case PrimitiveMode::Points:
672 return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
673 case PrimitiveMode::Lines:
674 case PrimitiveMode::LineStrip:
675 case PrimitiveMode::LineLoop:
676 return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
677 case PrimitiveMode::Triangles:
678 case PrimitiveMode::TriangleFan:
679 case PrimitiveMode::TriangleStrip:
680 return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
Jiawei Shao80c32cc2018-04-25 09:48:36 +0800681 default:
682 UNREACHABLE();
683 return false;
684 }
685}
686
Jamie Madill5b772312018-03-08 20:28:32 -0500687bool ValidateDrawElementsInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400688 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400689 GLsizei count,
690 GLenum type,
691 const GLvoid *indices,
692 GLsizei primcount)
693{
694 if (primcount < 0)
695 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700696 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400697 return false;
698 }
699
700 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
701 {
702 return false;
703 }
704
Jamie Madill9fdaa492018-02-16 10:52:11 -0500705 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400706}
707
708bool ValidateDrawArraysInstancedBase(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -0400709 PrimitiveMode mode,
Jamie Madillbe849e42017-05-02 15:49:00 -0400710 GLint first,
711 GLsizei count,
712 GLsizei primcount)
713{
714 if (primcount < 0)
715 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700716 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400717 return false;
718 }
719
720 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
721 {
722 return false;
723 }
724
Jamie Madill9fdaa492018-02-16 10:52:11 -0500725 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -0400726}
727
Jamie Madill5b772312018-03-08 20:28:32 -0500728bool ValidateDrawInstancedANGLE(Context *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400729{
730 // Verify there is at least one active attribute with a divisor of zero
731 const State &state = context->getGLState();
732
733 Program *program = state.getProgram();
734
735 const auto &attribs = state.getVertexArray()->getVertexAttributes();
736 const auto &bindings = state.getVertexArray()->getVertexBindings();
737 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
738 {
739 const VertexAttribute &attrib = attribs[attributeIndex];
740 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300741 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400742 {
743 return true;
744 }
745 }
746
Brandon Jonesafa75152017-07-21 13:11:29 -0700747 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400748 return false;
749}
750
Jamie Madill5b772312018-03-08 20:28:32 -0500751bool ValidTexture3DDestinationTarget(const Context *context, TextureType target)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500752{
753 switch (target)
754 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800755 case TextureType::_3D:
756 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800757 return true;
758 default:
759 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400760 }
761}
762
Jamie Madill5b772312018-03-08 20:28:32 -0500763bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
He Yunchao11b038b2016-11-22 21:24:04 +0800764{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800765 switch (type)
He Yunchao11b038b2016-11-22 21:24:04 +0800766 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800767 case TextureType::_2D:
768 case TextureType::_2DArray:
769 case TextureType::_2DMultisample:
770 case TextureType::CubeMap:
771 case TextureType::_3D:
He Yunchao11b038b2016-11-22 21:24:04 +0800772 return true;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800773 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400774 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800775 default:
776 return false;
777 }
778}
779
Jamie Madill5b772312018-03-08 20:28:32 -0500780bool ValidFramebufferTarget(const Context *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500781{
He Yunchaoced53ae2016-11-29 15:00:51 +0800782 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
783 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400784 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500785
786 switch (target)
787 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800788 case GL_FRAMEBUFFER:
789 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400790
He Yunchaoced53ae2016-11-29 15:00:51 +0800791 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800792 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400793 return (context->getExtensions().framebufferBlit ||
794 context->getClientMajorVersion() >= 3);
795
He Yunchaoced53ae2016-11-29 15:00:51 +0800796 default:
797 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500798 }
799}
800
Jamie Madill5b772312018-03-08 20:28:32 -0500801bool ValidMipLevel(const Context *context, TextureType type, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400802{
Jamie Madillc29968b2016-01-20 11:17:23 -0500803 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400804 size_t maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800805 switch (type)
Geoff Langce635692013-09-24 13:56:32 -0400806 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800807 case TextureType::_2D:
808 case TextureType::_2DArray:
809 case TextureType::_2DMultisample:
Jamie Madillc29968b2016-01-20 11:17:23 -0500810 maxDimension = caps.max2DTextureSize;
811 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800812 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800813 maxDimension = caps.maxCubeMapTextureSize;
814 break;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800815 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400816 return level == 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800817 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800818 maxDimension = caps.max3DTextureSize;
819 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800820 default:
821 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400822 }
823
Brandon Jones6cad5662017-06-14 13:25:13 -0700824 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400825}
826
Jamie Madill5b772312018-03-08 20:28:32 -0500827bool ValidImageSizeParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800828 TextureType target,
Austin Kinross08528e12015-10-07 16:24:40 -0700829 GLint level,
830 GLsizei width,
831 GLsizei height,
832 GLsizei depth,
833 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400834{
Brandon Jones6cad5662017-06-14 13:25:13 -0700835 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400836 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700837 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400838 return false;
839 }
Austin Kinross08528e12015-10-07 16:24:40 -0700840 // TexSubImage parameters can be NPOT without textureNPOT extension,
841 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500842 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500843 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500844 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400845 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400846 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700847 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400848 return false;
849 }
850
851 if (!ValidMipLevel(context, target, level))
852 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700853 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400854 return false;
855 }
856
857 return true;
858}
859
Geoff Lang966c9402017-04-18 12:38:27 -0400860bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
861{
862 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
863 (size % blockSize == 0);
864}
865
Jamie Madill5b772312018-03-08 20:28:32 -0500866bool ValidCompressedImageSize(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500867 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400868 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500869 GLsizei width,
870 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400871{
Geoff Langca271392017-04-05 12:30:00 -0400872 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400873 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400874 {
875 return false;
876 }
877
Geoff Lang966c9402017-04-18 12:38:27 -0400878 if (width < 0 || height < 0)
879 {
880 return false;
881 }
882
883 if (CompressedTextureFormatRequiresExactSize(internalFormat))
884 {
885 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
886 // block size for level 0 but WebGL disallows this.
887 bool smallerThanBlockSizeAllowed =
888 level > 0 || !context->getExtensions().webglCompatibility;
889
890 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
891 smallerThanBlockSizeAllowed) ||
892 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
893 smallerThanBlockSizeAllowed))
894 {
895 return false;
896 }
897 }
898
899 return true;
900}
901
Jamie Madill5b772312018-03-08 20:28:32 -0500902bool ValidCompressedSubImageSize(const Context *context,
Geoff Lang966c9402017-04-18 12:38:27 -0400903 GLenum internalFormat,
904 GLint xoffset,
905 GLint yoffset,
906 GLsizei width,
907 GLsizei height,
908 size_t textureWidth,
909 size_t textureHeight)
910{
911 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
912 if (!formatInfo.compressed)
913 {
914 return false;
915 }
916
Geoff Lang44ff5a72017-02-03 15:15:43 -0500917 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400918 {
919 return false;
920 }
921
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500922 if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
Geoff Lang0d8b7242015-09-09 14:56:53 -0400923 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500924 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400925 yoffset % formatInfo.compressedBlockHeight != 0)
926 {
927 return false;
928 }
929
930 // Allowed to either have data that is a multiple of block size or is smaller than the block
931 // size but fills the entire mip
932 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
933 static_cast<size_t>(width) == textureWidth &&
934 static_cast<size_t>(height) == textureHeight;
935 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
936 (height % formatInfo.compressedBlockHeight) == 0;
937 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400938 {
939 return false;
940 }
941 }
942
Geoff Langd4f180b2013-09-24 13:57:44 -0400943 return true;
944}
945
Jamie Madill5b772312018-03-08 20:28:32 -0500946bool ValidImageDataSize(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800947 TextureType texType,
Geoff Langff5b2d52016-09-07 11:32:23 -0400948 GLsizei width,
949 GLsizei height,
950 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400951 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400952 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400953 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400954 GLsizei imageSize)
955{
Corentin Wallez336129f2017-10-17 15:55:40 -0400956 gl::Buffer *pixelUnpackBuffer =
957 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400958 if (pixelUnpackBuffer == nullptr && imageSize < 0)
959 {
960 // Checks are not required
961 return true;
962 }
963
964 // ...the data would be unpacked from the buffer object such that the memory reads required
965 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400966 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
967 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400968 const gl::Extents size(width, height, depth);
969 const auto &unpack = context->getGLState().getUnpackState();
970
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800971 bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
Jamie Madillca2ff382018-07-11 09:01:17 -0400972 GLuint endByte = 0;
973 if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
Geoff Langff5b2d52016-09-07 11:32:23 -0400974 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400975 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400976 return false;
977 }
978
Geoff Langff5b2d52016-09-07 11:32:23 -0400979 if (pixelUnpackBuffer)
980 {
Jamie Madillca2ff382018-07-11 09:01:17 -0400981 CheckedNumeric<size_t> checkedEndByte(endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400982 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
983 checkedEndByte += checkedOffset;
984
985 if (!checkedEndByte.IsValid() ||
986 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
987 {
988 // Overflow past the end of the buffer
Jamie Madillca2ff382018-07-11 09:01:17 -0400989 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Geoff Langff5b2d52016-09-07 11:32:23 -0400990 return false;
991 }
James Darpiniane8a93c62018-01-04 18:02:24 -0800992 if (context->getExtensions().webglCompatibility &&
993 pixelUnpackBuffer->isBoundForTransformFeedbackAndOtherUse())
994 {
995 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
996 PixelUnpackBufferBoundForTransformFeedback);
997 return false;
998 }
Geoff Langff5b2d52016-09-07 11:32:23 -0400999 }
1000 else
1001 {
1002 ASSERT(imageSize >= 0);
1003 if (pixels == nullptr && imageSize != 0)
1004 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001005 context->handleError(InvalidOperation()
1006 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001007 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001008 }
1009
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001010 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001011 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001012 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001013 return false;
1014 }
1015 }
1016
1017 return true;
1018}
1019
Corentin Wallezad3ae902018-03-09 13:40:42 -05001020bool ValidQueryType(const Context *context, QueryType queryType)
Geoff Lang37dde692014-01-31 16:34:54 -05001021{
Geoff Lang37dde692014-01-31 16:34:54 -05001022 switch (queryType)
1023 {
Corentin Wallezad3ae902018-03-09 13:40:42 -05001024 case QueryType::AnySamples:
1025 case QueryType::AnySamplesConservative:
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001026 return context->getClientMajorVersion() >= 3 ||
1027 context->getExtensions().occlusionQueryBoolean;
Corentin Wallezad3ae902018-03-09 13:40:42 -05001028 case QueryType::TransformFeedbackPrimitivesWritten:
He Yunchaoced53ae2016-11-29 15:00:51 +08001029 return (context->getClientMajorVersion() >= 3);
Corentin Wallezad3ae902018-03-09 13:40:42 -05001030 case QueryType::TimeElapsed:
He Yunchaoced53ae2016-11-29 15:00:51 +08001031 return context->getExtensions().disjointTimerQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -05001032 case QueryType::CommandsCompleted:
He Yunchaoced53ae2016-11-29 15:00:51 +08001033 return context->getExtensions().syncQuery;
Corentin Wallezad3ae902018-03-09 13:40:42 -05001034 case QueryType::PrimitivesGenerated:
Jiawei Shaod2fa07e2018-03-15 09:20:25 +08001035 return context->getExtensions().geometryShader;
He Yunchaoced53ae2016-11-29 15:00:51 +08001036 default:
1037 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001038 }
1039}
1040
Jamie Madill5b772312018-03-08 20:28:32 -05001041bool ValidateWebGLVertexAttribPointer(Context *context,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001042 GLenum type,
1043 GLboolean normalized,
1044 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001045 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001046 bool pureInteger)
1047{
1048 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001049 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1050 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1051 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1052 // parameter exceeds 255.
1053 constexpr GLsizei kMaxWebGLStride = 255;
1054 if (stride > kMaxWebGLStride)
1055 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001056 context->handleError(InvalidValue()
1057 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001058 return false;
1059 }
1060
1061 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1062 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1063 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1064 // or an INVALID_OPERATION error is generated.
1065 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1066 size_t typeSize = GetVertexFormatTypeSize(internalType);
1067
1068 ASSERT(isPow2(typeSize) && typeSize > 0);
1069 size_t sizeMask = (typeSize - 1);
1070 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1071 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001072 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001073 return false;
1074 }
1075
1076 if ((stride & sizeMask) != 0)
1077 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001078 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001079 return false;
1080 }
1081
1082 return true;
1083}
1084
Jamie Madill5b772312018-03-08 20:28:32 -05001085Program *GetValidProgram(Context *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001086{
He Yunchaoced53ae2016-11-29 15:00:51 +08001087 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1088 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1089 // or program object and INVALID_OPERATION if the provided name identifies an object
1090 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001091
Dian Xiang769769a2015-09-09 15:20:08 -07001092 Program *validProgram = context->getProgram(id);
1093
1094 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001095 {
Dian Xiang769769a2015-09-09 15:20:08 -07001096 if (context->getShader(id))
1097 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001098 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001099 }
1100 else
1101 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001102 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001103 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001104 }
Dian Xiang769769a2015-09-09 15:20:08 -07001105
1106 return validProgram;
1107}
1108
Jamie Madill5b772312018-03-08 20:28:32 -05001109Shader *GetValidShader(Context *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001110{
1111 // See ValidProgram for spec details.
1112
1113 Shader *validShader = context->getShader(id);
1114
1115 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001116 {
Dian Xiang769769a2015-09-09 15:20:08 -07001117 if (context->getProgram(id))
1118 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001119 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001120 }
1121 else
1122 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001123 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001124 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001125 }
Dian Xiang769769a2015-09-09 15:20:08 -07001126
1127 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001128}
1129
Geoff Langb1196682014-07-23 13:47:29 -04001130bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001131{
Geoff Langfa125c92017-10-24 13:01:46 -04001132 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001133 {
Geoff Langfa125c92017-10-24 13:01:46 -04001134 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1135 {
1136 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1137 return false;
1138 }
Jamie Madillb4472272014-07-03 10:38:55 -04001139
Geoff Langfa125c92017-10-24 13:01:46 -04001140 // Color attachment 0 is validated below because it is always valid
1141 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001142 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001143 {
Geoff Langfa125c92017-10-24 13:01:46 -04001144 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001145 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001146 }
1147 }
1148 else
1149 {
1150 switch (attachment)
1151 {
Geoff Langfa125c92017-10-24 13:01:46 -04001152 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001153 case GL_DEPTH_ATTACHMENT:
1154 case GL_STENCIL_ATTACHMENT:
1155 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001156
He Yunchaoced53ae2016-11-29 15:00:51 +08001157 case GL_DEPTH_STENCIL_ATTACHMENT:
1158 if (!context->getExtensions().webglCompatibility &&
1159 context->getClientMajorVersion() < 3)
1160 {
Geoff Langfa125c92017-10-24 13:01:46 -04001161 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001162 return false;
1163 }
1164 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001165
He Yunchaoced53ae2016-11-29 15:00:51 +08001166 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001167 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001168 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001169 }
1170 }
1171
1172 return true;
1173}
1174
Jamie Madill5b772312018-03-08 20:28:32 -05001175bool ValidateRenderbufferStorageParametersBase(Context *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001176 GLenum target,
1177 GLsizei samples,
1178 GLenum internalformat,
1179 GLsizei width,
1180 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001181{
1182 switch (target)
1183 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001184 case GL_RENDERBUFFER:
1185 break;
1186 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001187 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001188 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001189 }
1190
1191 if (width < 0 || height < 0 || samples < 0)
1192 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001193 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001194 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001195 }
1196
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001197 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1198 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1199
1200 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04001201 if (!formatCaps.renderbuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001202 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001203 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001204 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001205 }
1206
1207 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1208 // 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 -08001209 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001210 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1211 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001212 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001213 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001214 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001215 }
1216
Geoff Langaae65a42014-05-26 12:43:44 -04001217 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001218 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001219 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001220 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001221 }
1222
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001223 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001224 if (handle == 0)
1225 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001226 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001227 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001228 }
1229
1230 return true;
1231}
1232
He Yunchaoced53ae2016-11-29 15:00:51 +08001233bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1234 GLenum target,
1235 GLenum attachment,
1236 GLenum renderbuffertarget,
1237 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001238{
Geoff Lange8afa902017-09-27 15:00:43 -04001239 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001240 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001241 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001242 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001243 }
1244
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001245 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001246
Jamie Madill84115c92015-04-23 15:00:07 -04001247 ASSERT(framebuffer);
1248 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001249 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001250 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001251 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001252 }
1253
Jamie Madillb4472272014-07-03 10:38:55 -04001254 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001255 {
Jamie Madillb4472272014-07-03 10:38:55 -04001256 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001257 }
1258
Jamie Madillab9d82c2014-01-21 16:38:14 -05001259 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1260 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1261 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1262 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1263 if (renderbuffer != 0)
1264 {
1265 if (!context->getRenderbuffer(renderbuffer))
1266 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001267 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001268 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001269 }
1270 }
1271
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001272 return true;
1273}
1274
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001275bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001276 GLint srcX0,
1277 GLint srcY0,
1278 GLint srcX1,
1279 GLint srcY1,
1280 GLint dstX0,
1281 GLint dstY0,
1282 GLint dstX1,
1283 GLint dstY1,
1284 GLbitfield mask,
1285 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001286{
1287 switch (filter)
1288 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001289 case GL_NEAREST:
1290 break;
1291 case GL_LINEAR:
1292 break;
1293 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001294 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001295 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001296 }
1297
1298 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1299 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001300 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001301 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001302 }
1303
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001304 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1305 // color buffer, leaving only nearest being unfiltered from above
1306 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1307 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001308 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001309 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001310 }
1311
Jamie Madill51f40ec2016-06-15 14:06:00 -04001312 const auto &glState = context->getGLState();
1313 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1314 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001315
1316 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001318 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001319 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001320 }
1321
Jamie Madill427064d2018-04-13 16:20:34 -04001322 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001323 {
Jamie Madill48faf802014-11-06 15:27:22 -05001324 return false;
1325 }
1326
Jamie Madill427064d2018-04-13 16:20:34 -04001327 if (!ValidateFramebufferComplete(context, drawFramebuffer))
Jamie Madill48faf802014-11-06 15:27:22 -05001328 {
Jamie Madill48faf802014-11-06 15:27:22 -05001329 return false;
1330 }
1331
Qin Jiajiaaef92162018-02-27 13:51:44 +08001332 if (readFramebuffer->id() == drawFramebuffer->id())
1333 {
1334 context->handleError(InvalidOperation());
1335 return false;
1336 }
1337
Jamie Madille98b1b52018-03-08 09:47:23 -05001338 if (!ValidateFramebufferNotMultisampled(context, drawFramebuffer))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001339 {
Geoff Langb1196682014-07-23 13:47:29 -04001340 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001341 }
1342
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001343 // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
1344 // always run it in order to avoid triggering driver bugs.
1345 if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
1346 DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001347 {
Olli Etuaho9aef81c2018-04-30 14:56:15 +03001348 ANGLE_VALIDATION_ERR(context, InvalidValue(), BlitDimensionsOutOfRange);
1349 return false;
Olli Etuaho8d5571a2018-04-23 12:29:31 +03001350 }
1351
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001352 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1353
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001354 if (mask & GL_COLOR_BUFFER_BIT)
1355 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001356 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001357 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001358
He Yunchao66a41a22016-12-15 16:45:05 +08001359 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001360 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001361 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001362
Geoff Langa15472a2015-08-11 11:48:03 -04001363 for (size_t drawbufferIdx = 0;
1364 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001365 {
Geoff Langa15472a2015-08-11 11:48:03 -04001366 const FramebufferAttachment *attachment =
1367 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1368 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001369 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001370 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001371
Geoff Langb2f3d052013-08-13 12:49:27 -04001372 // The GL ES 3.0.2 spec (pg 193) states that:
1373 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001374 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1375 // as well
1376 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1377 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001378 // Changes with EXT_color_buffer_float:
1379 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001380 GLenum readComponentType = readFormat.info->componentType;
1381 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001382 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001383 readComponentType == GL_SIGNED_NORMALIZED);
Lingfeng Yang038dd532018-03-29 17:31:52 -07001384 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001385 drawComponentType == GL_SIGNED_NORMALIZED);
1386
1387 if (extensions.colorBufferFloat)
1388 {
1389 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1390 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1391
1392 if (readFixedOrFloat != drawFixedOrFloat)
1393 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001394 context->handleError(InvalidOperation()
1395 << "If the read buffer contains fixed-point or "
1396 "floating-point values, the draw buffer must "
1397 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001398 return false;
1399 }
1400 }
1401 else if (readFixedPoint != drawFixedPoint)
1402 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001403 context->handleError(InvalidOperation()
1404 << "If the read buffer contains fixed-point values, "
1405 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001406 return false;
1407 }
1408
1409 if (readComponentType == GL_UNSIGNED_INT &&
1410 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001411 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001412 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001413 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001414 }
1415
Jamie Madill6163c752015-12-07 16:32:59 -05001416 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001417 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001418 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001419 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001420 }
1421
Jamie Madilla3944d42016-07-22 22:13:26 -04001422 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001423 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001424 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001425 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001426 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001427 }
Geoff Lange4915782017-04-12 15:19:07 -04001428
1429 if (context->getExtensions().webglCompatibility &&
1430 *readColorBuffer == *attachment)
1431 {
1432 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001433 InvalidOperation()
1434 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001435 return false;
1436 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001437 }
1438 }
1439
Jamie Madilla3944d42016-07-22 22:13:26 -04001440 if ((readFormat.info->componentType == GL_INT ||
1441 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1442 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001443 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001444 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001445 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001446 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001447 }
He Yunchao66a41a22016-12-15 16:45:05 +08001448 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1449 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1450 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1451 // situation is an application error that would lead to a crash in ANGLE.
1452 else if (drawFramebuffer->hasEnabledDrawBuffer())
1453 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001454 context->handleError(
1455 InvalidOperation()
1456 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001457 return false;
1458 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001459 }
1460
He Yunchaoced53ae2016-11-29 15:00:51 +08001461 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001462 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1463 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001464 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001465 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001466 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001467 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001468 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001469 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001470 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001471
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001472 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001473 {
Kenneth Russell69382852017-07-21 16:38:44 -04001474 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001475 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001476 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001477 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001478 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001479
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001480 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001481 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001482 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001483 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001484 }
Geoff Lange4915782017-04-12 15:19:07 -04001485
1486 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001488 context->handleError(
1489 InvalidOperation()
1490 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001491 return false;
1492 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001493 }
He Yunchao66a41a22016-12-15 16:45:05 +08001494 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1495 else if (drawBuffer)
1496 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001497 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1498 "depth/stencil attachment of a "
1499 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001500 return false;
1501 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001502 }
1503 }
1504
Martin Radeva3ed4572017-07-27 18:29:37 +03001505 // ANGLE_multiview, Revision 1:
1506 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03001507 // multi-view layout of the current draw framebuffer is not NONE, or if the multi-view layout of
1508 // the current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of
1509 // views in the current read framebuffer is more than one.
1510 if (readFramebuffer->readDisallowedByMultiview())
Martin Radeva3ed4572017-07-27 18:29:37 +03001511 {
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
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002525 // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
2526 // framebuffer is more than one.
2527 if (readFramebuffer->readDisallowedByMultiview())
Martin Radev04e2c3b2017-07-27 16:54:35 +03002528 {
2529 context->handleError(InvalidFramebufferOperation()
2530 << "The active read framebuffer object has multiview attachments.");
2531 return false;
2532 }
2533
Geoff Langaae65a42014-05-26 12:43:44 -04002534 const gl::Caps &caps = context->getCaps();
2535
Geoff Langaae65a42014-05-26 12:43:44 -04002536 GLuint maxDimension = 0;
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002537 switch (texType)
Jamie Madill560a8d82014-05-21 13:06:20 -04002538 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002539 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002540 maxDimension = caps.max2DTextureSize;
2541 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002542
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002543 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +08002544 maxDimension = caps.maxCubeMapTextureSize;
2545 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002546
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002547 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002548 maxDimension = caps.maxRectangleTextureSize;
2549 break;
2550
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002551 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +08002552 maxDimension = caps.max2DTextureSize;
2553 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002554
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002555 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +08002556 maxDimension = caps.max3DTextureSize;
2557 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002558
He Yunchaoced53ae2016-11-29 15:00:51 +08002559 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002560 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002561 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002562 }
2563
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002564 gl::Texture *texture = state.getTargetTexture(texType);
Jamie Madill560a8d82014-05-21 13:06:20 -04002565 if (!texture)
2566 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002567 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002568 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002569 }
2570
Geoff Lang69cce582015-09-17 13:20:36 -04002571 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002572 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002573 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002574 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002575 }
2576
Geoff Langca271392017-04-05 12:30:00 -04002577 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002578 isSubImage ? *texture->getFormat(target, level).info
2579 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002580
Geoff Lang966c9402017-04-18 12:38:27 -04002581 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002582 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002583 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002584 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002585 }
2586
2587 if (isSubImage)
2588 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002589 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2590 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2591 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002592 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002593 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002594 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002595 }
2596 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002597 else
2598 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002599 if (texType == TextureType::CubeMap && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002600 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002601 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002602 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002603 }
2604
Geoff Langeb66a6e2016-10-31 13:06:12 -04002605 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002606 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002607 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002608 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002609 }
2610
2611 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002612 if (static_cast<int>(width) > maxLevelDimension ||
2613 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002614 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002615 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002616 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002617 }
2618 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002619
Jamie Madill0c8abca2016-07-22 20:21:26 -04002620 if (textureFormatOut)
2621 {
2622 *textureFormatOut = texture->getFormat(target, level);
2623 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002624
2625 // Detect texture copying feedback loops for WebGL.
2626 if (context->getExtensions().webglCompatibility)
2627 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002628 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002629 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002630 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002631 return false;
2632 }
2633 }
2634
Jamie Madill560a8d82014-05-21 13:06:20 -04002635 return true;
2636}
2637
Jamie Madill493f9572018-05-24 19:52:15 -04002638bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002639{
Jiawei Shaofccebff2018-03-08 13:51:02 +08002640 const Extensions &extensions = context->getExtensions();
2641
Jamie Madill1aeb1312014-06-20 13:21:25 -04002642 switch (mode)
2643 {
Jamie Madill493f9572018-05-24 19:52:15 -04002644 case PrimitiveMode::Points:
2645 case PrimitiveMode::Lines:
2646 case PrimitiveMode::LineLoop:
2647 case PrimitiveMode::LineStrip:
2648 case PrimitiveMode::Triangles:
2649 case PrimitiveMode::TriangleStrip:
2650 case PrimitiveMode::TriangleFan:
He Yunchaoced53ae2016-11-29 15:00:51 +08002651 break;
Jiawei Shaofccebff2018-03-08 13:51:02 +08002652
Jamie Madill493f9572018-05-24 19:52:15 -04002653 case PrimitiveMode::LinesAdjacency:
2654 case PrimitiveMode::LineStripAdjacency:
2655 case PrimitiveMode::TrianglesAdjacency:
2656 case PrimitiveMode::TriangleStripAdjacency:
Jiawei Shaofccebff2018-03-08 13:51:02 +08002657 if (!extensions.geometryShader)
2658 {
2659 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
2660 return false;
2661 }
2662 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002663 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002664 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002665 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002666 }
2667
Jamie Madill250d33f2014-06-06 17:09:03 -04002668 if (count < 0)
2669 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002670 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002671 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002672 }
2673
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002674 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002675
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002676 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2677 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2678 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2679 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002680 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002681 // Check for mapped buffers
2682 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002683 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002684 {
2685 context->handleError(InvalidOperation());
2686 return false;
2687 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002688 }
2689
Jamie Madillcbcde722017-01-06 14:50:00 -05002690 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2691 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002692 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002693 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002694 {
Ken Russellb9f92502018-01-27 19:00:26 -08002695 ASSERT(framebuffer);
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002696 const FramebufferAttachment *dsAttachment =
2697 framebuffer->getStencilOrDepthStencilAttachment();
Ken Russellb9f92502018-01-27 19:00:26 -08002698 const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
2699 ASSERT(stencilBits <= 8);
2700
Jinyoung Hur85769f02015-10-20 17:08:44 -04002701 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Ken Russellb9f92502018-01-27 19:00:26 -08002702 if (depthStencilState.stencilTest && stencilBits > 0)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002703 {
Ken Russellb9f92502018-01-27 19:00:26 -08002704 GLuint maxStencilValue = (1 << stencilBits) - 1;
2705
2706 bool differentRefs =
2707 clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
2708 clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
2709 bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
2710 (depthStencilState.stencilBackWritemask & maxStencilValue);
2711 bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
2712 (depthStencilState.stencilBackMask & maxStencilValue);
2713
2714 if (differentRefs || differentWritemasks || differentMasks)
Jamie Madillcbcde722017-01-06 14:50:00 -05002715 {
Ken Russellb9f92502018-01-27 19:00:26 -08002716 if (!extensions.webglCompatibility)
2717 {
Jamie Madilla2f043d2018-07-10 17:21:20 -04002718 WARN() << "This ANGLE implementation does not support separate front/back "
2719 "stencil writemasks, reference values, or stencil mask values.";
Ken Russellb9f92502018-01-27 19:00:26 -08002720 }
2721 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
2722 return false;
Jamie Madillcbcde722017-01-06 14:50:00 -05002723 }
Geoff Lang3a86ad32015-09-01 11:47:05 -04002724 }
Jamie Madillac528012014-06-20 13:21:23 -04002725 }
2726
Jamie Madill427064d2018-04-13 16:20:34 -04002727 if (!ValidateFramebufferComplete(context, framebuffer))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002728 {
Geoff Langb1196682014-07-23 13:47:29 -04002729 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002730 }
2731
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002732 // If we are running GLES1, there is no current program.
2733 if (context->getClientVersion() >= Version(2, 0))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002734 {
Jamie Madilld4cfa572014-07-08 10:00:32 -04002735
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002736 gl::Program *program = state.getProgram();
2737 if (!program)
Martin Radev7cf61662017-07-26 17:10:53 +03002738 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002739 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Martin Radev7cf61662017-07-26 17:10:53 +03002740 return false;
2741 }
Martin Radev7e69f762017-07-27 14:54:13 +03002742
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002743 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2744 // vertex shader stage or fragment shader stage is a undefined behaviour.
2745 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2746 // produce undefined result.
2747 if (!program->hasLinkedShaderStage(ShaderType::Vertex) ||
2748 !program->hasLinkedShaderStage(ShaderType::Fragment))
Martin Radev7e69f762017-07-27 14:54:13 +03002749 {
2750 context->handleError(InvalidOperation()
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002751 << "It is a undefined behaviour to render without "
2752 "vertex shader stage or fragment shader stage.");
Martin Radev7e69f762017-07-27 14:54:13 +03002753 return false;
2754 }
Martin Radevffe754b2017-07-31 10:38:07 +03002755
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002756 if (!program->validateSamplers(nullptr, context->getCaps()))
Martin Radevffe754b2017-07-31 10:38:07 +03002757 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002758 context->handleError(InvalidOperation());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002759 return false;
2760 }
2761
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002762 if (extensions.multiview)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002763 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002764 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
2765 const int framebufferNumViews = framebuffer->getNumViews();
2766 if (framebufferNumViews != programNumViews)
2767 {
2768 context->handleError(InvalidOperation()
2769 << "The number of views in the active program "
2770 "and draw framebuffer does not match.");
2771 return false;
2772 }
2773
2774 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2775 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2776 framebufferNumViews > 1)
2777 {
2778 context->handleError(InvalidOperation()
2779 << "There is an active transform feedback object "
2780 "when the number of views in the active draw "
2781 "framebuffer is greater than 1.");
2782 return false;
2783 }
2784
2785 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2786 state.isQueryActive(QueryType::TimeElapsed))
2787 {
2788 context->handleError(InvalidOperation()
2789 << "There is an active query for target "
2790 "GL_TIME_ELAPSED_EXT when the number of "
2791 "views in the active draw framebuffer is "
2792 "greater than 1.");
2793 return false;
2794 }
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002795 }
James Darpiniane8a93c62018-01-04 18:02:24 -08002796
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002797 // Do geometry shader specific validations
2798 if (program->hasLinkedShaderStage(ShaderType::Geometry))
James Darpiniane8a93c62018-01-04 18:02:24 -08002799 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002800 if (!IsCompatibleDrawModeWithGeometryShader(
2801 mode, program->getGeometryShaderInputPrimitiveType()))
2802 {
2803 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2804 IncompatibleDrawModeAgainstGeometryShader);
2805 return false;
2806 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002807 }
Geoff Lange0cff192017-05-30 13:04:56 -04002808
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002809 // Uniform buffer validation
2810 for (unsigned int uniformBlockIndex = 0;
2811 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Geoff Lang9ab5b822017-05-30 16:19:23 -04002812 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002813 const gl::InterfaceBlock &uniformBlock =
2814 program->getUniformBlockByIndex(uniformBlockIndex);
2815 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
2816 const OffsetBindingPointer<Buffer> &uniformBuffer =
2817 state.getIndexedUniformBuffer(blockBinding);
2818
2819 if (uniformBuffer.get() == nullptr)
2820 {
2821 // undefined behaviour
2822 context->handleError(
2823 InvalidOperation()
2824 << "It is undefined behaviour to have a used but unbound uniform buffer.");
2825 return false;
2826 }
2827
2828 size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
2829 if (uniformBufferSize < uniformBlock.dataSize)
2830 {
2831 // undefined behaviour
2832 context->handleError(
2833 InvalidOperation()
2834 << "It is undefined behaviour to use a uniform buffer that is too small.");
2835 return false;
2836 }
2837
2838 if (extensions.webglCompatibility &&
2839 uniformBuffer->isBoundForTransformFeedbackAndOtherUse())
2840 {
2841 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2842 UniformBufferBoundForTransformFeedback);
2843 return false;
2844 }
Geoff Lang9ab5b822017-05-30 16:19:23 -04002845 }
2846
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002847 // Do some additonal WebGL-specific validation
2848 if (extensions.webglCompatibility)
Geoff Lange0cff192017-05-30 13:04:56 -04002849 {
Lingfeng Yang461b09a2018-04-23 09:02:09 -07002850 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2851 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2852 transformFeedbackObject->buffersBoundForOtherUse())
2853 {
2854 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
2855 TransformFeedbackBufferDoubleBound);
2856 return false;
2857 }
2858 // Detect rendering feedback loops for WebGL.
2859 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2860 {
2861 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
2862 return false;
2863 }
2864
2865 // Detect that the vertex shader input types match the attribute types
2866 if (!ValidateVertexShaderAttributeTypeMatch(context))
2867 {
2868 return false;
2869 }
2870
2871 // Detect that the color buffer types match the fragment shader output types
2872 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2873 {
2874 return false;
2875 }
Geoff Lange0cff192017-05-30 13:04:56 -04002876 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002877 }
2878
Jamie Madill9fdaa492018-02-16 10:52:11 -05002879 return true;
Jamie Madill250d33f2014-06-06 17:09:03 -04002880}
2881
Jamie Madill5b772312018-03-08 20:28:32 -05002882bool ValidateDrawArraysCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002883 PrimitiveMode mode,
Jamie Madillc1d770e2017-04-13 17:31:24 -04002884 GLint first,
2885 GLsizei count,
2886 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002887{
Jamie Madillfd716582014-06-06 17:09:04 -04002888 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002889 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002890 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002891 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002892 }
2893
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002894 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002895 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002896 if (curTransformFeedback && curTransformFeedback->isActive() &&
James Darpinian30b604d2018-03-12 17:26:57 -07002897 !curTransformFeedback->isPaused())
Jamie Madillfd716582014-06-06 17:09:04 -04002898 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002899 if (!ValidateTransformFeedbackPrimitiveMode(context,
2900 curTransformFeedback->getPrimitiveMode(), mode))
James Darpinian30b604d2018-03-12 17:26:57 -07002901 {
James Darpinian30b604d2018-03-12 17:26:57 -07002902 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2903 return false;
2904 }
2905
2906 if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
2907 {
2908 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackBufferTooSmall);
2909 return false;
2910 }
Jamie Madillfd716582014-06-06 17:09:04 -04002911 }
2912
Jiajia Qind9671222016-11-29 16:30:31 +08002913 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002914 {
2915 return false;
2916 }
2917
Corentin Wallez71168a02016-12-19 15:11:18 -08002918 // Check the computation of maxVertex doesn't overflow.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002919 // - first < 0 has been checked as an error condition.
2920 // - if count < 0, skip validating no-op draw calls.
Corentin Wallez71168a02016-12-19 15:11:18 -08002921 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
Jamie Madill9fdaa492018-02-16 10:52:11 -05002922 ASSERT(first >= 0);
2923 if (count > 0)
Corentin Wallez92db6942016-12-09 13:10:36 -05002924 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05002925 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2926 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
2927 {
2928 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
2929 return false;
2930 }
Corentin Wallez92db6942016-12-09 13:10:36 -05002931
Jamie Madill9fdaa492018-02-16 10:52:11 -05002932 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
2933 {
2934 return false;
2935 }
Jamie Madillfd716582014-06-06 17:09:04 -04002936 }
2937
2938 return true;
2939}
2940
He Yunchaoced53ae2016-11-29 15:00:51 +08002941bool ValidateDrawArraysInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04002942 PrimitiveMode mode,
He Yunchaoced53ae2016-11-29 15:00:51 +08002943 GLint first,
2944 GLsizei count,
2945 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002946{
Geoff Lang63c5a592017-09-27 14:08:16 -04002947 if (!context->getExtensions().instancedArrays)
2948 {
2949 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2950 return false;
2951 }
2952
Corentin Wallez170efbf2017-05-02 13:45:01 -04002953 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002954 {
2955 return false;
2956 }
2957
Corentin Wallez0dc97812017-06-22 14:38:44 -04002958 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002959}
2960
Jamie Madill493f9572018-05-24 19:52:15 -04002961bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002962{
Jamie Madill250d33f2014-06-06 17:09:03 -04002963 switch (type)
2964 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002965 case GL_UNSIGNED_BYTE:
2966 case GL_UNSIGNED_SHORT:
2967 break;
2968 case GL_UNSIGNED_INT:
2969 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2970 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002971 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002972 return false;
2973 }
2974 break;
2975 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002976 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002977 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002978 }
2979
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002980 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002981
2982 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002983 if (curTransformFeedback && curTransformFeedback->isActive() &&
2984 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002985 {
Jiawei Shao80c32cc2018-04-25 09:48:36 +08002986 // EXT_geometry_shader allows transform feedback to work with all draw commands.
2987 // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
2988 if (context->getExtensions().geometryShader)
2989 {
2990 if (!ValidateTransformFeedbackPrimitiveMode(
2991 context, curTransformFeedback->getPrimitiveMode(), mode))
2992 {
2993 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
2994 return false;
2995 }
2996 }
2997 else
2998 {
2999 // It is an invalid operation to call DrawElements, DrawRangeElements or
3000 // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
3001 // 86)
3002 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3003 UnsupportedDrawModeForTransformFeedback);
3004 return false;
3005 }
Jamie Madill250d33f2014-06-06 17:09:03 -04003006 }
3007
Jiajia Qind9671222016-11-29 16:30:31 +08003008 return true;
3009}
3010
Jamie Madill5b772312018-03-08 20:28:32 -05003011bool ValidateDrawElementsCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003012 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003013 GLsizei count,
3014 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003015 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003016 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08003017{
Jiawei Shao80c32cc2018-04-25 09:48:36 +08003018 if (!ValidateDrawElementsBase(context, mode, type))
Jiajia Qind9671222016-11-29 16:30:31 +08003019 return false;
3020
3021 const State &state = context->getGLState();
3022
Corentin Wallez170efbf2017-05-02 13:45:01 -04003023 if (!ValidateDrawBase(context, mode, count))
3024 {
3025 return false;
3026 }
3027
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003028 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
3029 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
3030 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
3031 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04003032 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003033 // Check for mapped buffers
3034 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04003035 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08003036 {
3037 context->handleError(InvalidOperation() << "Index buffer is mapped.");
3038 return false;
3039 }
Jamie Madill250d33f2014-06-06 17:09:03 -04003040 }
3041
He Yunchaoced53ae2016-11-29 15:00:51 +08003042 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003043 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003044
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003045 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3046
3047 if (context->getExtensions().webglCompatibility)
3048 {
3049 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3050 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3051 {
3052 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3053 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3054 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003055 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003056 return false;
3057 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003058
3059 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3060 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3061 // error is generated.
3062 if (reinterpret_cast<intptr_t>(indices) < 0)
3063 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003064 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003065 return false;
3066 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003067 }
3068
3069 if (context->getExtensions().webglCompatibility ||
3070 !context->getGLState().areClientArraysEnabled())
3071 {
Brandon Jones2a018152018-06-08 15:59:26 -07003072 if (!elementArrayBuffer)
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003073 {
3074 // [WebGL 1.0] Section 6.2 No Client Side Arrays
Brandon Jones2a018152018-06-08 15:59:26 -07003075 // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
3076 // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003077 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003078 return false;
3079 }
3080 }
3081
Jamie Madill9fdaa492018-02-16 10:52:11 -05003082 if (count > 0 && !elementArrayBuffer && !indices)
Jamie Madillae3000b2014-08-25 15:47:51 -04003083 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003084 // This is an application error that would normally result in a crash, but we catch it and
3085 // return an error
3086 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
3087 return false;
3088 }
3089
3090 if (count > 0 && elementArrayBuffer)
3091 {
3092 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3093 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3094 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3095 constexpr uint64_t kMaxTypeSize = 8;
3096 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3097 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3098 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
3099
3100 uint64_t typeSize = typeBytes;
3101 uint64_t elementCount = static_cast<uint64_t>(count);
3102 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3103
3104 // Doing the multiplication here is overflow-safe
3105 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3106
3107 // The offset can be any value, check for overflows
3108 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3109 if (elementDataSizeNoOffset > kUint64Max - offset)
Jamie Madillae3000b2014-08-25 15:47:51 -04003110 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003111 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
3112 return false;
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003113 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003114
3115 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3116 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003117 {
Jamie Madill9fdaa492018-02-16 10:52:11 -05003118 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
3119 return false;
3120 }
3121
3122 ASSERT(isPow2(typeSize) && typeSize > 0);
3123 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
3124 {
3125 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
Geoff Langb1196682014-07-23 13:47:29 -04003126 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003127 }
James Darpiniane8a93c62018-01-04 18:02:24 -08003128
3129 if (context->getExtensions().webglCompatibility &&
3130 elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
3131 {
3132 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
3133 ElementArrayBufferBoundForTransformFeedback);
3134 return false;
3135 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003136 }
3137
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003138 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003139 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003140 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
3141 // access is enabled.
3142 if (!ValidateDrawAttribs(context, primcount, 0, 1))
3143 {
3144 return false;
3145 }
3146 }
Jamie Madill9fdaa492018-02-16 10:52:11 -05003147 else if (count == 0)
3148 {
3149 // ValidateDrawAttribs also does some extra validation that is independent of the vertex
3150 // count.
3151 if (!ValidateDrawAttribs(context, 0, 0, 0))
3152 {
3153 return false;
3154 }
3155 }
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003156 else
3157 {
3158 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003159 const DrawCallParams &params = context->getParams<DrawCallParams>();
3160 ANGLE_VALIDATION_TRY(params.ensureIndexRangeResolved(context));
3161 const IndexRange &indexRange = params.getIndexRange();
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003162
3163 // If we use an index greater than our maximum supported index range, return an error.
3164 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3165 // return an error if possible here.
Jamie Madill6f5444d2018-03-14 10:08:11 -04003166 if (static_cast<GLuint64>(indexRange.end) >= context->getCaps().maxElementIndex)
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003167 {
3168 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3169 return false;
3170 }
3171
Jamie Madill6f5444d2018-03-14 10:08:11 -04003172 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRange.end),
3173 static_cast<GLint>(indexRange.vertexCount())))
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003174 {
3175 return false;
3176 }
3177
3178 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill6f5444d2018-03-14 10:08:11 -04003179 return (indexRange.vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003180 }
3181
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08003182 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003183}
3184
Jamie Madill5b772312018-03-08 20:28:32 -05003185bool ValidateDrawElementsInstancedCommon(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003186 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003187 GLsizei count,
3188 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003189 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003190 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003191{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003192 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003193}
3194
Geoff Lang3edfe032015-09-04 16:38:24 -04003195bool ValidateDrawElementsInstancedANGLE(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003196 PrimitiveMode mode,
Geoff Lang3edfe032015-09-04 16:38:24 -04003197 GLsizei count,
3198 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003199 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003200 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003201{
Geoff Lang63c5a592017-09-27 14:08:16 -04003202 if (!context->getExtensions().instancedArrays)
3203 {
3204 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3205 return false;
3206 }
3207
Corentin Wallez170efbf2017-05-02 13:45:01 -04003208 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003209 {
3210 return false;
3211 }
3212
Corentin Wallez0dc97812017-06-22 14:38:44 -04003213 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003214}
3215
He Yunchaoced53ae2016-11-29 15:00:51 +08003216bool ValidateFramebufferTextureBase(Context *context,
3217 GLenum target,
3218 GLenum attachment,
3219 GLuint texture,
3220 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003221{
Geoff Lange8afa902017-09-27 15:00:43 -04003222 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003223 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003224 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003225 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003226 }
3227
3228 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003229 {
3230 return false;
3231 }
3232
Jamie Madill55ec3b12014-07-03 10:38:57 -04003233 if (texture != 0)
3234 {
3235 gl::Texture *tex = context->getTexture(texture);
3236
Luc Ferronadcf0ae2018-01-24 08:27:37 -05003237 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003238 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003239 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003240 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003241 }
3242
3243 if (level < 0)
3244 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003245 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003246 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003247 }
3248 }
3249
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003250 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003251 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003252
Jamie Madill84115c92015-04-23 15:00:07 -04003253 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003254 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003255 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003256 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003257 }
3258
3259 return true;
3260}
3261
Geoff Langb1196682014-07-23 13:47:29 -04003262bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003263{
3264 if (program == 0)
3265 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003266 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003267 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003268 }
3269
Dian Xiang769769a2015-09-09 15:20:08 -07003270 gl::Program *programObject = GetValidProgram(context, program);
3271 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003272 {
3273 return false;
3274 }
3275
Jamie Madill0063c512014-08-25 15:47:53 -04003276 if (!programObject || !programObject->isLinked())
3277 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003278 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003279 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003280 }
3281
Geoff Lang7dd2e102014-11-10 15:19:26 -05003282 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003283 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003284 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003285 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003286 }
3287
Jamie Madill0063c512014-08-25 15:47:53 -04003288 return true;
3289}
3290
Geoff Langf41d0ee2016-10-07 13:04:23 -04003291static bool ValidateSizedGetUniform(Context *context,
3292 GLuint program,
3293 GLint location,
3294 GLsizei bufSize,
3295 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003296{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003297 if (length)
3298 {
3299 *length = 0;
3300 }
3301
Jamie Madill78f41802014-08-25 15:47:55 -04003302 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003303 {
Jamie Madill78f41802014-08-25 15:47:55 -04003304 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003305 }
3306
Geoff Langf41d0ee2016-10-07 13:04:23 -04003307 if (bufSize < 0)
3308 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003309 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003310 return false;
3311 }
3312
Jamie Madilla502c742014-08-28 17:19:13 -04003313 gl::Program *programObject = context->getProgram(program);
3314 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003315
Jamie Madill78f41802014-08-25 15:47:55 -04003316 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003317 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003318 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003319 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003320 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003321 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003322 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003323 }
3324
Geoff Langf41d0ee2016-10-07 13:04:23 -04003325 if (length)
3326 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003327 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003328 }
3329
Jamie Madill0063c512014-08-25 15:47:53 -04003330 return true;
3331}
3332
He Yunchaoced53ae2016-11-29 15:00:51 +08003333bool ValidateGetnUniformfvEXT(Context *context,
3334 GLuint program,
3335 GLint location,
3336 GLsizei bufSize,
3337 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003338{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003339 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003340}
3341
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003342bool ValidateGetnUniformfvRobustANGLE(Context *context,
3343 GLuint program,
3344 GLint location,
3345 GLsizei bufSize,
3346 GLsizei *length,
3347 GLfloat *params)
3348{
3349 UNIMPLEMENTED();
3350 return false;
3351}
3352
He Yunchaoced53ae2016-11-29 15:00:51 +08003353bool ValidateGetnUniformivEXT(Context *context,
3354 GLuint program,
3355 GLint location,
3356 GLsizei bufSize,
3357 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003358{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003359 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3360}
3361
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07003362bool ValidateGetnUniformivRobustANGLE(Context *context,
3363 GLuint program,
3364 GLint location,
3365 GLsizei bufSize,
3366 GLsizei *length,
3367 GLint *params)
3368{
3369 UNIMPLEMENTED();
3370 return false;
3371}
3372
3373bool ValidateGetnUniformuivRobustANGLE(Context *context,
3374 GLuint program,
3375 GLint location,
3376 GLsizei bufSize,
3377 GLsizei *length,
3378 GLuint *params)
3379{
3380 UNIMPLEMENTED();
3381 return false;
3382}
3383
Geoff Langf41d0ee2016-10-07 13:04:23 -04003384bool ValidateGetUniformfvRobustANGLE(Context *context,
3385 GLuint program,
3386 GLint location,
3387 GLsizei bufSize,
3388 GLsizei *length,
3389 GLfloat *params)
3390{
3391 if (!ValidateRobustEntryPoint(context, bufSize))
3392 {
3393 return false;
3394 }
3395
Brandon Jonesd1049182018-03-28 10:02:20 -07003396 GLsizei writeLength = 0;
3397
Geoff Langf41d0ee2016-10-07 13:04:23 -04003398 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003399 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3400 {
3401 return false;
3402 }
3403
3404 SetRobustLengthParam(length, writeLength);
3405
3406 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003407}
3408
3409bool ValidateGetUniformivRobustANGLE(Context *context,
3410 GLuint program,
3411 GLint location,
3412 GLsizei bufSize,
3413 GLsizei *length,
3414 GLint *params)
3415{
3416 if (!ValidateRobustEntryPoint(context, bufSize))
3417 {
3418 return false;
3419 }
3420
Brandon Jonesd1049182018-03-28 10:02:20 -07003421 GLsizei writeLength = 0;
3422
Geoff Langf41d0ee2016-10-07 13:04:23 -04003423 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003424 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3425 {
3426 return false;
3427 }
3428
3429 SetRobustLengthParam(length, writeLength);
3430
3431 return true;
Geoff Langf41d0ee2016-10-07 13:04:23 -04003432}
3433
3434bool ValidateGetUniformuivRobustANGLE(Context *context,
3435 GLuint program,
3436 GLint location,
3437 GLsizei bufSize,
3438 GLsizei *length,
3439 GLuint *params)
3440{
3441 if (!ValidateRobustEntryPoint(context, bufSize))
3442 {
3443 return false;
3444 }
3445
3446 if (context->getClientMajorVersion() < 3)
3447 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003448 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003449 return false;
3450 }
3451
Brandon Jonesd1049182018-03-28 10:02:20 -07003452 GLsizei writeLength = 0;
3453
Geoff Langf41d0ee2016-10-07 13:04:23 -04003454 // bufSize is validated in ValidateSizedGetUniform
Brandon Jonesd1049182018-03-28 10:02:20 -07003455 if (!ValidateSizedGetUniform(context, program, location, bufSize, &writeLength))
3456 {
3457 return false;
3458 }
3459
3460 SetRobustLengthParam(length, writeLength);
3461
3462 return true;
Jamie Madill0063c512014-08-25 15:47:53 -04003463}
3464
He Yunchaoced53ae2016-11-29 15:00:51 +08003465bool ValidateDiscardFramebufferBase(Context *context,
3466 GLenum target,
3467 GLsizei numAttachments,
3468 const GLenum *attachments,
3469 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003470{
3471 if (numAttachments < 0)
3472 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003473 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003474 return false;
3475 }
3476
3477 for (GLsizei i = 0; i < numAttachments; ++i)
3478 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003479 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003480 {
3481 if (defaultFramebuffer)
3482 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003483 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003484 return false;
3485 }
3486
3487 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3488 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003489 context->handleError(InvalidOperation() << "Requested color attachment is "
3490 "greater than the maximum supported "
3491 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003492 return false;
3493 }
3494 }
3495 else
3496 {
3497 switch (attachments[i])
3498 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003499 case GL_DEPTH_ATTACHMENT:
3500 case GL_STENCIL_ATTACHMENT:
3501 case GL_DEPTH_STENCIL_ATTACHMENT:
3502 if (defaultFramebuffer)
3503 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003504 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3505 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003506 return false;
3507 }
3508 break;
3509 case GL_COLOR:
3510 case GL_DEPTH:
3511 case GL_STENCIL:
3512 if (!defaultFramebuffer)
3513 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003514 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3515 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003516 return false;
3517 }
3518 break;
3519 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003520 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003521 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003522 }
3523 }
3524 }
3525
3526 return true;
3527}
3528
Austin Kinross6ee1e782015-05-29 17:05:37 -07003529bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3530{
Jamie Madill007530e2017-12-28 14:27:04 -05003531 if (!context->getExtensions().debugMarker)
3532 {
3533 // The debug marker calls should not set error state
3534 // However, it seems reasonable to set an error state if the extension is not enabled
3535 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3536 return false;
3537 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003538
Jamie Madill007530e2017-12-28 14:27:04 -05003539 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003540 if (length < 0)
3541 {
3542 return false;
3543 }
3544
3545 if (marker == nullptr)
3546 {
3547 return false;
3548 }
3549
3550 return true;
3551}
3552
3553bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3554{
Jamie Madill007530e2017-12-28 14:27:04 -05003555 if (!context->getExtensions().debugMarker)
3556 {
3557 // The debug marker calls should not set error state
3558 // However, it seems reasonable to set an error state if the extension is not enabled
3559 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3560 return false;
3561 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003562
Jamie Madill007530e2017-12-28 14:27:04 -05003563 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003564 if (length < 0)
3565 {
3566 return false;
3567 }
3568
3569 if (length > 0 && marker == nullptr)
3570 {
3571 return false;
3572 }
3573
3574 return true;
3575}
3576
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003577bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003578{
Geoff Langa8406172015-07-21 16:53:39 -04003579 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003581 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003582 return false;
3583 }
3584
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003585 switch (type)
Geoff Langa8406172015-07-21 16:53:39 -04003586 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003587 case TextureType::_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003588 if (!context->getExtensions().eglImage)
3589 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003590 context->handleError(InvalidEnum()
3591 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003592 }
3593 break;
3594
Corentin Wallezf0e89be2017-11-08 14:00:32 -08003595 case TextureType::External:
Geoff Langb66a9092016-05-16 15:59:14 -04003596 if (!context->getExtensions().eglImageExternal)
3597 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003598 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3599 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003600 }
Geoff Langa8406172015-07-21 16:53:39 -04003601 break;
3602
3603 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003604 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003605 return false;
3606 }
3607
Rafael Cintron05a449a2018-06-20 18:08:04 -07003608 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003609
Jamie Madill61e16b42017-06-19 11:13:23 -04003610 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003611 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003612 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003613 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003614 return false;
3615 }
3616
Jamie Madill007530e2017-12-28 14:27:04 -05003617 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003618 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003619 context->handleError(InvalidOperation()
3620 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003621 return false;
3622 }
3623
Geoff Langca271392017-04-05 12:30:00 -04003624 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003625 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003626 if (!textureCaps.texturable)
3627 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003628 context->handleError(InvalidOperation()
3629 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003630 return false;
3631 }
3632
Geoff Langdcab33b2015-07-21 13:03:16 -04003633 return true;
3634}
3635
3636bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003637 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003638 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003639{
Geoff Langa8406172015-07-21 16:53:39 -04003640 if (!context->getExtensions().eglImage)
3641 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003642 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003643 return false;
3644 }
3645
3646 switch (target)
3647 {
3648 case GL_RENDERBUFFER:
3649 break;
3650
3651 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003652 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003653 return false;
3654 }
3655
Rafael Cintron05a449a2018-06-20 18:08:04 -07003656 egl::Image *imageObject = static_cast<egl::Image *>(image);
Jamie Madill007530e2017-12-28 14:27:04 -05003657
Jamie Madill61e16b42017-06-19 11:13:23 -04003658 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003659 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003660 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003661 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003662 return false;
3663 }
3664
Geoff Langca271392017-04-05 12:30:00 -04003665 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003666 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04003667 if (!textureCaps.renderbuffer)
Geoff Langa8406172015-07-21 16:53:39 -04003668 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003669 context->handleError(InvalidOperation()
3670 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003671 return false;
3672 }
3673
Geoff Langdcab33b2015-07-21 13:03:16 -04003674 return true;
3675}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003676
3677bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3678{
Geoff Lang36167ab2015-12-07 10:27:14 -05003679 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003680 {
3681 // The default VAO should always exist
3682 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003683 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003684 return false;
3685 }
3686
3687 return true;
3688}
3689
Geoff Langc5629752015-12-07 16:29:04 -05003690bool ValidateProgramBinaryBase(Context *context,
3691 GLuint program,
3692 GLenum binaryFormat,
3693 const void *binary,
3694 GLint length)
3695{
3696 Program *programObject = GetValidProgram(context, program);
3697 if (programObject == nullptr)
3698 {
3699 return false;
3700 }
3701
3702 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3703 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3704 programBinaryFormats.end())
3705 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003706 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003707 return false;
3708 }
3709
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003710 if (context->hasActiveTransformFeedback(program))
3711 {
3712 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003713 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3714 "is associated with an active transform "
3715 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003716 return false;
3717 }
3718
Geoff Langc5629752015-12-07 16:29:04 -05003719 return true;
3720}
3721
3722bool ValidateGetProgramBinaryBase(Context *context,
3723 GLuint program,
3724 GLsizei bufSize,
3725 GLsizei *length,
3726 GLenum *binaryFormat,
3727 void *binary)
3728{
3729 Program *programObject = GetValidProgram(context, program);
3730 if (programObject == nullptr)
3731 {
3732 return false;
3733 }
3734
3735 if (!programObject->isLinked())
3736 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003737 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003738 return false;
3739 }
3740
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003741 if (context->getCaps().programBinaryFormats.empty())
3742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003743 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003744 return false;
3745 }
3746
Geoff Langc5629752015-12-07 16:29:04 -05003747 return true;
3748}
Jamie Madillc29968b2016-01-20 11:17:23 -05003749
Jamie Madill5b772312018-03-08 20:28:32 -05003750bool ValidateDrawBuffersBase(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05003751{
3752 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003753 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003754 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003755 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3756 return false;
3757 }
3758 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3759 {
3760 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003761 return false;
3762 }
3763
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003764 ASSERT(context->getGLState().getDrawFramebuffer());
3765 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003766 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3767
3768 // This should come first before the check for the default frame buffer
3769 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3770 // rather than INVALID_OPERATION
3771 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3772 {
3773 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3774
3775 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003776 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3777 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003778 {
3779 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003780 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3781 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3782 // 3.1 is still a bit ambiguous about the error, but future specs are
3783 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003784 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003785 return false;
3786 }
3787 else if (bufs[colorAttachment] >= maxColorAttachment)
3788 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003789 context->handleError(InvalidOperation()
3790 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003791 return false;
3792 }
3793 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3794 frameBufferId != 0)
3795 {
3796 // INVALID_OPERATION-GL is bound to buffer and ith argument
3797 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003798 context->handleError(InvalidOperation()
3799 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003800 return false;
3801 }
3802 }
3803
3804 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3805 // and n is not 1 or bufs is bound to value other than BACK and NONE
3806 if (frameBufferId == 0)
3807 {
3808 if (n != 1)
3809 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003810 context->handleError(InvalidOperation()
3811 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003812 return false;
3813 }
3814
3815 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3816 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003817 context->handleError(
3818 InvalidOperation()
3819 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003820 return false;
3821 }
3822 }
3823
3824 return true;
3825}
3826
Geoff Lang496c02d2016-10-20 11:38:11 -07003827bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003828 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003829 GLenum pname,
3830 GLsizei *length,
3831 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003832{
Geoff Lang496c02d2016-10-20 11:38:11 -07003833 if (length)
3834 {
3835 *length = 0;
3836 }
3837
3838 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3839 {
3840 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003841 InvalidOperation()
3842 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003843 return false;
3844 }
3845
Corentin Walleze4477002017-12-01 14:39:58 -05003846 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003847 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003848 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003849 return false;
3850 }
3851
Geoff Lang496c02d2016-10-20 11:38:11 -07003852 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003853 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003854 case GL_BUFFER_MAP_POINTER:
3855 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003856
Geoff Lang496c02d2016-10-20 11:38:11 -07003857 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003858 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003859 return false;
3860 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003861
3862 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3863 // target bound to zero generate an INVALID_OPERATION error."
3864 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003865 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003866 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003867 context->handleError(InvalidOperation()
3868 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003869 return false;
3870 }
3871
Geoff Lang496c02d2016-10-20 11:38:11 -07003872 if (length)
3873 {
3874 *length = 1;
3875 }
3876
Olli Etuaho4f667482016-03-30 15:56:35 +03003877 return true;
3878}
3879
Corentin Wallez336129f2017-10-17 15:55:40 -04003880bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003881{
Corentin Walleze4477002017-12-01 14:39:58 -05003882 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003883 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003884 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003885 return false;
3886 }
3887
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003888 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003889
3890 if (buffer == nullptr || !buffer->isMapped())
3891 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003892 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003893 return false;
3894 }
3895
3896 return true;
3897}
3898
3899bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003900 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003901 GLintptr offset,
3902 GLsizeiptr length,
3903 GLbitfield access)
3904{
Corentin Walleze4477002017-12-01 14:39:58 -05003905 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003906 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003907 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003908 return false;
3909 }
3910
Brandon Jones6cad5662017-06-14 13:25:13 -07003911 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003912 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003913 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3914 return false;
3915 }
3916
3917 if (length < 0)
3918 {
3919 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003920 return false;
3921 }
3922
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003923 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003924
3925 if (!buffer)
3926 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003927 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003928 return false;
3929 }
3930
3931 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003932 CheckedNumeric<size_t> checkedOffset(offset);
3933 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003934
Jamie Madille2e406c2016-06-02 13:04:10 -04003935 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003936 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003937 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003938 return false;
3939 }
3940
3941 // Check for invalid bits in the mask
3942 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3943 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3944 GL_MAP_UNSYNCHRONIZED_BIT;
3945
3946 if (access & ~(allAccessBits))
3947 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003948 context->handleError(InvalidValue()
3949 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003950 return false;
3951 }
3952
3953 if (length == 0)
3954 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003955 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003956 return false;
3957 }
3958
3959 if (buffer->isMapped())
3960 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003961 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003962 return false;
3963 }
3964
3965 // Check for invalid bit combinations
3966 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3967 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003968 context->handleError(InvalidOperation()
3969 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003970 return false;
3971 }
3972
3973 GLbitfield writeOnlyBits =
3974 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3975
3976 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3977 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003978 context->handleError(InvalidOperation()
3979 << "Invalid access bits when mapping buffer for reading: 0x"
3980 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003981 return false;
3982 }
3983
3984 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3985 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003986 context->handleError(
3987 InvalidOperation()
3988 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003989 return false;
3990 }
Geoff Lang79f71042017-08-14 16:43:43 -04003991
3992 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003993}
3994
3995bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003996 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003997 GLintptr offset,
3998 GLsizeiptr length)
3999{
Brandon Jones6cad5662017-06-14 13:25:13 -07004000 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03004001 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004002 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
4003 return false;
4004 }
4005
4006 if (length < 0)
4007 {
4008 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03004009 return false;
4010 }
4011
Corentin Walleze4477002017-12-01 14:39:58 -05004012 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03004013 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004014 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03004015 return false;
4016 }
4017
Jamie Madilldfde6ab2016-06-09 07:07:18 -07004018 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03004019
4020 if (buffer == nullptr)
4021 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004022 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004023 return false;
4024 }
4025
4026 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
4027 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004028 context->handleError(InvalidOperation()
4029 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004030 return false;
4031 }
4032
4033 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04004034 CheckedNumeric<size_t> checkedOffset(offset);
4035 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03004036
Jamie Madille2e406c2016-06-02 13:04:10 -04004037 if (!checkedSize.IsValid() ||
4038 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03004039 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004040 context->handleError(InvalidValue()
4041 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03004042 return false;
4043 }
4044
4045 return true;
4046}
4047
Olli Etuaho41997e72016-03-10 13:38:39 +02004048bool ValidateGenOrDelete(Context *context, GLint n)
4049{
4050 if (n < 0)
4051 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004052 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02004053 return false;
4054 }
4055 return true;
4056}
4057
Jamie Madill5b772312018-03-08 20:28:32 -05004058bool ValidateRobustEntryPoint(Context *context, GLsizei bufSize)
Geoff Langff5b2d52016-09-07 11:32:23 -04004059{
4060 if (!context->getExtensions().robustClientMemory)
4061 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004062 context->handleError(InvalidOperation()
4063 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004064 return false;
4065 }
4066
4067 if (bufSize < 0)
4068 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004069 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004070 return false;
4071 }
4072
4073 return true;
4074}
4075
Jamie Madill5b772312018-03-08 20:28:32 -05004076bool ValidateRobustBufferSize(Context *context, GLsizei bufSize, GLsizei numParams)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004077{
4078 if (bufSize < numParams)
4079 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004080 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4081 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004082 return false;
4083 }
4084
4085 return true;
4086}
4087
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004088bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04004089 GLenum target,
4090 GLenum attachment,
4091 GLenum pname,
4092 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004093{
Geoff Lange8afa902017-09-27 15:00:43 -04004094 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04004095 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004096 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004097 return false;
4098 }
4099
4100 int clientVersion = context->getClientMajorVersion();
4101
4102 switch (pname)
4103 {
4104 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4105 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4106 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4107 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4108 break;
4109
Martin Radeve5285d22017-07-14 16:23:53 +03004110 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4111 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4112 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4113 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4114 if (clientVersion < 3 || !context->getExtensions().multiview)
4115 {
4116 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4117 return false;
4118 }
4119 break;
4120
Geoff Langff5b2d52016-09-07 11:32:23 -04004121 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4122 if (clientVersion < 3 && !context->getExtensions().sRGB)
4123 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004124 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004125 return false;
4126 }
4127 break;
4128
4129 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4130 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4131 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4132 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4133 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4134 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4135 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4136 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4137 if (clientVersion < 3)
4138 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004139 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004140 return false;
4141 }
4142 break;
4143
Jiawei Shaoa8802472018-05-28 11:17:47 +08004144 case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
4145 if (!context->getExtensions().geometryShader)
4146 {
4147 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4148 return false;
4149 }
4150 break;
4151
Geoff Langff5b2d52016-09-07 11:32:23 -04004152 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004153 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004154 return false;
4155 }
4156
4157 // Determine if the attachment is a valid enum
4158 switch (attachment)
4159 {
4160 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04004161 case GL_DEPTH:
4162 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04004163 if (clientVersion < 3)
4164 {
Geoff Langfa125c92017-10-24 13:01:46 -04004165 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004166 return false;
4167 }
4168 break;
4169
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004170 case GL_DEPTH_STENCIL_ATTACHMENT:
4171 if (clientVersion < 3 && !context->isWebGL1())
4172 {
4173 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
4174 return false;
4175 }
4176 break;
4177
Geoff Langfa125c92017-10-24 13:01:46 -04004178 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04004179 case GL_DEPTH_ATTACHMENT:
4180 case GL_STENCIL_ATTACHMENT:
4181 break;
4182
4183 default:
Geoff Langfa125c92017-10-24 13:01:46 -04004184 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
4185 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04004186 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4187 {
Geoff Langfa125c92017-10-24 13:01:46 -04004188 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004189 return false;
4190 }
4191 break;
4192 }
4193
4194 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4195 ASSERT(framebuffer);
4196
4197 if (framebuffer->id() == 0)
4198 {
4199 if (clientVersion < 3)
4200 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004201 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004202 return false;
4203 }
4204
4205 switch (attachment)
4206 {
4207 case GL_BACK:
4208 case GL_DEPTH:
4209 case GL_STENCIL:
4210 break;
4211
4212 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004213 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004214 return false;
4215 }
4216 }
4217 else
4218 {
4219 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4220 {
4221 // Valid attachment query
4222 }
4223 else
4224 {
4225 switch (attachment)
4226 {
4227 case GL_DEPTH_ATTACHMENT:
4228 case GL_STENCIL_ATTACHMENT:
4229 break;
4230
4231 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004232 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04004233 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004234 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004235 return false;
4236 }
4237 break;
4238
4239 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004240 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004241 return false;
4242 }
4243 }
4244 }
4245
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004246 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004247 if (attachmentObject)
4248 {
4249 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4250 attachmentObject->type() == GL_TEXTURE ||
4251 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4252
4253 switch (pname)
4254 {
4255 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4256 if (attachmentObject->type() != GL_RENDERBUFFER &&
4257 attachmentObject->type() != GL_TEXTURE)
4258 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004259 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004260 return false;
4261 }
4262 break;
4263
4264 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4265 if (attachmentObject->type() != GL_TEXTURE)
4266 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004267 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004268 return false;
4269 }
4270 break;
4271
4272 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4273 if (attachmentObject->type() != GL_TEXTURE)
4274 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004275 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004276 return false;
4277 }
4278 break;
4279
4280 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4281 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4282 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004283 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004284 return false;
4285 }
4286 break;
4287
4288 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4289 if (attachmentObject->type() != GL_TEXTURE)
4290 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004291 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004292 return false;
4293 }
4294 break;
4295
4296 default:
4297 break;
4298 }
4299 }
4300 else
4301 {
4302 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4303 // is NONE, then querying any other pname will generate INVALID_ENUM.
4304
4305 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4306 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4307 // INVALID_OPERATION for all other pnames
4308
4309 switch (pname)
4310 {
4311 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4312 break;
4313
4314 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4315 if (clientVersion < 3)
4316 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004317 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004318 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004319 return false;
4320 }
4321 break;
4322
4323 default:
4324 if (clientVersion < 3)
4325 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004326 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004327 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004328 return false;
4329 }
4330 else
4331 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004332 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004333 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004334 return false;
4335 }
4336 }
4337 }
4338
Martin Radeve5285d22017-07-14 16:23:53 +03004339 if (numParams)
4340 {
4341 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4342 {
4343 // Only when the viewport offsets are queried we can have a varying number of output
4344 // parameters.
4345 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4346 *numParams = numViews * 2;
4347 }
4348 else
4349 {
4350 // For all other queries we can have only one output parameter.
4351 *numParams = 1;
4352 }
4353 }
4354
Geoff Langff5b2d52016-09-07 11:32:23 -04004355 return true;
4356}
4357
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004358bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004359 GLenum target,
4360 GLenum attachment,
4361 GLenum pname,
4362 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004363 GLsizei *length,
4364 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004365{
4366 if (!ValidateRobustEntryPoint(context, bufSize))
4367 {
4368 return false;
4369 }
4370
Brandon Jonesd1049182018-03-28 10:02:20 -07004371 GLsizei numParams = 0;
Jamie Madillbe849e42017-05-02 15:49:00 -04004372 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004373 &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004374 {
4375 return false;
4376 }
4377
Brandon Jonesd1049182018-03-28 10:02:20 -07004378 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004379 {
4380 return false;
4381 }
4382
Brandon Jonesd1049182018-03-28 10:02:20 -07004383 SetRobustLengthParam(length, numParams);
4384
Geoff Langff5b2d52016-09-07 11:32:23 -04004385 return true;
4386}
4387
Jamie Madill5b772312018-03-08 20:28:32 -05004388bool ValidateGetBufferParameterivRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004389 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004390 GLenum pname,
4391 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004392 GLsizei *length,
4393 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004394{
4395 if (!ValidateRobustEntryPoint(context, bufSize))
4396 {
4397 return false;
4398 }
4399
Brandon Jonesd1049182018-03-28 10:02:20 -07004400 GLsizei numParams = 0;
4401
4402 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004403 {
4404 return false;
4405 }
4406
Brandon Jonesd1049182018-03-28 10:02:20 -07004407 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004408 {
4409 return false;
4410 }
4411
Brandon Jonesd1049182018-03-28 10:02:20 -07004412 SetRobustLengthParam(length, numParams);
Geoff Langebebe1c2016-10-14 12:01:31 -04004413 return true;
4414}
4415
Jamie Madill5b772312018-03-08 20:28:32 -05004416bool ValidateGetBufferParameteri64vRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004417 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004418 GLenum pname,
4419 GLsizei bufSize,
4420 GLsizei *length,
4421 GLint64 *params)
4422{
Brandon Jonesd1049182018-03-28 10:02:20 -07004423 GLsizei numParams = 0;
4424
Geoff Langebebe1c2016-10-14 12:01:31 -04004425 if (!ValidateRobustEntryPoint(context, bufSize))
4426 {
4427 return false;
4428 }
4429
Brandon Jonesd1049182018-03-28 10:02:20 -07004430 if (!ValidateGetBufferParameterBase(context, target, pname, false, &numParams))
Geoff Langebebe1c2016-10-14 12:01:31 -04004431 {
4432 return false;
4433 }
4434
Brandon Jonesd1049182018-03-28 10:02:20 -07004435 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004436 {
4437 return false;
4438 }
4439
Brandon Jonesd1049182018-03-28 10:02:20 -07004440 SetRobustLengthParam(length, numParams);
4441
Geoff Langff5b2d52016-09-07 11:32:23 -04004442 return true;
4443}
4444
Jamie Madill5b772312018-03-08 20:28:32 -05004445bool ValidateGetProgramivBase(Context *context, GLuint program, GLenum pname, GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004446{
4447 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004448 if (numParams)
4449 {
4450 *numParams = 1;
4451 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004452
4453 Program *programObject = GetValidProgram(context, program);
4454 if (!programObject)
4455 {
4456 return false;
4457 }
4458
4459 switch (pname)
4460 {
4461 case GL_DELETE_STATUS:
4462 case GL_LINK_STATUS:
4463 case GL_VALIDATE_STATUS:
4464 case GL_INFO_LOG_LENGTH:
4465 case GL_ATTACHED_SHADERS:
4466 case GL_ACTIVE_ATTRIBUTES:
4467 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4468 case GL_ACTIVE_UNIFORMS:
4469 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4470 break;
4471
4472 case GL_PROGRAM_BINARY_LENGTH:
4473 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4474 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004475 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4476 "requires GL_OES_get_program_binary or "
4477 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004478 return false;
4479 }
4480 break;
4481
4482 case GL_ACTIVE_UNIFORM_BLOCKS:
4483 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4484 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4485 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4486 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4487 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4488 if (context->getClientMajorVersion() < 3)
4489 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004490 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004491 return false;
4492 }
4493 break;
4494
Yunchao He61afff12017-03-14 15:34:03 +08004495 case GL_PROGRAM_SEPARABLE:
jchen1058f67be2017-10-27 08:59:27 +08004496 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004497 if (context->getClientVersion() < Version(3, 1))
4498 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004499 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004500 return false;
4501 }
4502 break;
4503
Jiawei Shao6ae51612018-02-23 14:03:25 +08004504 case GL_COMPUTE_WORK_GROUP_SIZE:
4505 if (context->getClientVersion() < Version(3, 1))
4506 {
4507 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
4508 return false;
4509 }
4510
4511 // [OpenGL ES 3.1] Chapter 7.12 Page 122
4512 // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
4513 // program which has not been linked successfully, or which does not contain objects to
4514 // form a compute shader.
4515 if (!programObject->isLinked())
4516 {
4517 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4518 return false;
4519 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004520 if (!programObject->hasLinkedShaderStage(ShaderType::Compute))
Jiawei Shao6ae51612018-02-23 14:03:25 +08004521 {
4522 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveComputeShaderStage);
4523 return false;
4524 }
4525 break;
4526
Jiawei Shao447bfac2018-03-14 14:23:40 +08004527 case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
4528 case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
4529 case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
4530 case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
4531 if (!context->getExtensions().geometryShader)
4532 {
4533 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GeometryShaderExtensionNotEnabled);
4534 return false;
4535 }
4536
4537 // [EXT_geometry_shader] Chapter 7.12
4538 // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
4539 // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
4540 // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
4541 // successfully, or which does not contain objects to form a geometry shader.
4542 if (!programObject->isLinked())
4543 {
4544 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4545 return false;
4546 }
Jiawei Shao385b3e02018-03-21 09:43:28 +08004547 if (!programObject->hasLinkedShaderStage(ShaderType::Geometry))
Jiawei Shao447bfac2018-03-14 14:23:40 +08004548 {
4549 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoActiveGeometryShaderStage);
4550 return false;
4551 }
4552 break;
4553
Geoff Langff5b2d52016-09-07 11:32:23 -04004554 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004555 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004556 return false;
4557 }
4558
4559 return true;
4560}
4561
4562bool ValidateGetProgramivRobustANGLE(Context *context,
4563 GLuint program,
4564 GLenum pname,
4565 GLsizei bufSize,
Brandon Jonesd1049182018-03-28 10:02:20 -07004566 GLsizei *length,
4567 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004568{
4569 if (!ValidateRobustEntryPoint(context, bufSize))
4570 {
4571 return false;
4572 }
4573
Brandon Jonesd1049182018-03-28 10:02:20 -07004574 GLsizei numParams = 0;
4575
4576 if (!ValidateGetProgramivBase(context, program, pname, &numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004577 {
4578 return false;
4579 }
4580
Brandon Jonesd1049182018-03-28 10:02:20 -07004581 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004582 {
4583 return false;
4584 }
4585
Brandon Jonesd1049182018-03-28 10:02:20 -07004586 SetRobustLengthParam(length, numParams);
4587
Geoff Langff5b2d52016-09-07 11:32:23 -04004588 return true;
4589}
4590
Geoff Lang740d9022016-10-07 11:20:52 -04004591bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4592 GLenum target,
4593 GLenum pname,
4594 GLsizei bufSize,
4595 GLsizei *length,
4596 GLint *params)
4597{
4598 if (!ValidateRobustEntryPoint(context, bufSize))
4599 {
4600 return false;
4601 }
4602
Brandon Jonesd1049182018-03-28 10:02:20 -07004603 GLsizei numParams = 0;
4604
4605 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, &numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004606 {
4607 return false;
4608 }
4609
Brandon Jonesd1049182018-03-28 10:02:20 -07004610 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang740d9022016-10-07 11:20:52 -04004611 {
4612 return false;
4613 }
4614
Brandon Jonesd1049182018-03-28 10:02:20 -07004615 SetRobustLengthParam(length, numParams);
4616
Geoff Lang740d9022016-10-07 11:20:52 -04004617 return true;
4618}
4619
Geoff Langd7d0ed32016-10-07 11:33:51 -04004620bool ValidateGetShaderivRobustANGLE(Context *context,
4621 GLuint shader,
4622 GLenum pname,
4623 GLsizei bufSize,
4624 GLsizei *length,
4625 GLint *params)
4626{
4627 if (!ValidateRobustEntryPoint(context, bufSize))
4628 {
4629 return false;
4630 }
4631
Brandon Jonesd1049182018-03-28 10:02:20 -07004632 GLsizei numParams = 0;
4633
4634 if (!ValidateGetShaderivBase(context, shader, pname, &numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004635 {
4636 return false;
4637 }
4638
Brandon Jonesd1049182018-03-28 10:02:20 -07004639 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langd7d0ed32016-10-07 11:33:51 -04004640 {
4641 return false;
4642 }
4643
Brandon Jonesd1049182018-03-28 10:02:20 -07004644 SetRobustLengthParam(length, numParams);
4645
Geoff Langd7d0ed32016-10-07 11:33:51 -04004646 return true;
4647}
4648
Geoff Langc1984ed2016-10-07 12:41:00 -04004649bool ValidateGetTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004650 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004651 GLenum pname,
4652 GLsizei bufSize,
4653 GLsizei *length,
4654 GLfloat *params)
4655{
4656 if (!ValidateRobustEntryPoint(context, bufSize))
4657 {
4658 return false;
4659 }
4660
Brandon Jonesd1049182018-03-28 10:02:20 -07004661 GLsizei numParams = 0;
4662
4663 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004664 {
4665 return false;
4666 }
4667
Brandon Jonesd1049182018-03-28 10:02:20 -07004668 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004669 {
4670 return false;
4671 }
4672
Brandon Jonesd1049182018-03-28 10:02:20 -07004673 SetRobustLengthParam(length, numParams);
4674
Geoff Langc1984ed2016-10-07 12:41:00 -04004675 return true;
4676}
4677
Geoff Langc1984ed2016-10-07 12:41:00 -04004678bool ValidateGetTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004679 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004680 GLenum pname,
4681 GLsizei bufSize,
4682 GLsizei *length,
4683 GLint *params)
4684{
Brandon Jonesd1049182018-03-28 10:02:20 -07004685
Geoff Langc1984ed2016-10-07 12:41:00 -04004686 if (!ValidateRobustEntryPoint(context, bufSize))
4687 {
4688 return false;
4689 }
Brandon Jonesd1049182018-03-28 10:02:20 -07004690 GLsizei numParams = 0;
4691 if (!ValidateGetTexParameterBase(context, target, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004692 {
4693 return false;
4694 }
4695
Brandon Jonesd1049182018-03-28 10:02:20 -07004696 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004697 {
4698 return false;
4699 }
4700
Brandon Jonesd1049182018-03-28 10:02:20 -07004701 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004702 return true;
4703}
4704
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004705bool ValidateGetTexParameterIivRobustANGLE(Context *context,
4706 TextureType target,
4707 GLenum pname,
4708 GLsizei bufSize,
4709 GLsizei *length,
4710 GLint *params)
4711{
4712 UNIMPLEMENTED();
4713 return false;
4714}
4715
4716bool ValidateGetTexParameterIuivRobustANGLE(Context *context,
4717 TextureType target,
4718 GLenum pname,
4719 GLsizei bufSize,
4720 GLsizei *length,
4721 GLuint *params)
4722{
4723 UNIMPLEMENTED();
4724 return false;
4725}
4726
Geoff Langc1984ed2016-10-07 12:41:00 -04004727bool ValidateTexParameterfvRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004728 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004729 GLenum pname,
4730 GLsizei bufSize,
4731 const GLfloat *params)
4732{
4733 if (!ValidateRobustEntryPoint(context, bufSize))
4734 {
4735 return false;
4736 }
4737
4738 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4739}
4740
Geoff Langc1984ed2016-10-07 12:41:00 -04004741bool ValidateTexParameterivRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004742 TextureType target,
Geoff Langc1984ed2016-10-07 12:41:00 -04004743 GLenum pname,
4744 GLsizei bufSize,
4745 const GLint *params)
4746{
4747 if (!ValidateRobustEntryPoint(context, bufSize))
4748 {
4749 return false;
4750 }
4751
4752 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4753}
4754
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004755bool ValidateTexParameterIivRobustANGLE(Context *context,
4756 TextureType target,
4757 GLenum pname,
4758 GLsizei bufSize,
4759 const GLint *params)
4760{
4761 UNIMPLEMENTED();
4762 return false;
4763}
4764
4765bool ValidateTexParameterIuivRobustANGLE(Context *context,
4766 TextureType target,
4767 GLenum pname,
4768 GLsizei bufSize,
4769 const GLuint *params)
4770{
4771 UNIMPLEMENTED();
4772 return false;
4773}
4774
Geoff Langc1984ed2016-10-07 12:41:00 -04004775bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4776 GLuint sampler,
4777 GLenum pname,
4778 GLuint bufSize,
4779 GLsizei *length,
4780 GLfloat *params)
4781{
4782 if (!ValidateRobustEntryPoint(context, bufSize))
4783 {
4784 return false;
4785 }
4786
Brandon Jonesd1049182018-03-28 10:02:20 -07004787 GLsizei numParams = 0;
4788
4789 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004790 {
4791 return false;
4792 }
4793
Brandon Jonesd1049182018-03-28 10:02:20 -07004794 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004795 {
4796 return false;
4797 }
4798
Brandon Jonesd1049182018-03-28 10:02:20 -07004799 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004800 return true;
4801}
4802
Geoff Langc1984ed2016-10-07 12:41:00 -04004803bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4804 GLuint sampler,
4805 GLenum pname,
Brandon Jonesd1049182018-03-28 10:02:20 -07004806 GLsizei bufSize,
Geoff Langc1984ed2016-10-07 12:41:00 -04004807 GLsizei *length,
4808 GLint *params)
4809{
4810 if (!ValidateRobustEntryPoint(context, bufSize))
4811 {
4812 return false;
4813 }
4814
Brandon Jonesd1049182018-03-28 10:02:20 -07004815 GLsizei numParams = 0;
4816
4817 if (!ValidateGetSamplerParameterBase(context, sampler, pname, &numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004818 {
4819 return false;
4820 }
4821
Brandon Jonesd1049182018-03-28 10:02:20 -07004822 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langc1984ed2016-10-07 12:41:00 -04004823 {
4824 return false;
4825 }
4826
Brandon Jonesd1049182018-03-28 10:02:20 -07004827 SetRobustLengthParam(length, numParams);
Geoff Langc1984ed2016-10-07 12:41:00 -04004828 return true;
4829}
4830
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004831bool ValidateGetSamplerParameterIivRobustANGLE(Context *context,
4832 GLuint sampler,
4833 GLenum pname,
4834 GLsizei bufSize,
4835 GLsizei *length,
4836 GLint *params)
4837{
4838 UNIMPLEMENTED();
4839 return false;
4840}
4841
4842bool ValidateGetSamplerParameterIuivRobustANGLE(Context *context,
4843 GLuint sampler,
4844 GLenum pname,
4845 GLsizei bufSize,
4846 GLsizei *length,
4847 GLuint *params)
4848{
4849 UNIMPLEMENTED();
4850 return false;
4851}
4852
Geoff Langc1984ed2016-10-07 12:41:00 -04004853bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4854 GLuint sampler,
4855 GLenum pname,
4856 GLsizei bufSize,
4857 const GLfloat *params)
4858{
4859 if (!ValidateRobustEntryPoint(context, bufSize))
4860 {
4861 return false;
4862 }
4863
4864 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4865}
4866
Geoff Langc1984ed2016-10-07 12:41:00 -04004867bool ValidateSamplerParameterivRobustANGLE(Context *context,
4868 GLuint sampler,
4869 GLenum pname,
4870 GLsizei bufSize,
4871 const GLint *params)
4872{
4873 if (!ValidateRobustEntryPoint(context, bufSize))
4874 {
4875 return false;
4876 }
4877
4878 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4879}
4880
Brandon Jonesfe4bbe62018-04-06 13:50:14 -07004881bool ValidateSamplerParameterIivRobustANGLE(Context *context,
4882 GLuint sampler,
4883 GLenum pname,
4884 GLsizei bufSize,
4885 const GLint *param)
4886{
4887 UNIMPLEMENTED();
4888 return false;
4889}
4890
4891bool ValidateSamplerParameterIuivRobustANGLE(Context *context,
4892 GLuint sampler,
4893 GLenum pname,
4894 GLsizei bufSize,
4895 const GLuint *param)
4896{
4897 UNIMPLEMENTED();
4898 return false;
4899}
4900
Geoff Lang0b031062016-10-13 14:30:04 -04004901bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4902 GLuint index,
4903 GLenum pname,
4904 GLsizei bufSize,
4905 GLsizei *length,
4906 GLfloat *params)
4907{
4908 if (!ValidateRobustEntryPoint(context, bufSize))
4909 {
4910 return false;
4911 }
4912
Brandon Jonesd1049182018-03-28 10:02:20 -07004913 GLsizei writeLength = 0;
4914
4915 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004916 {
4917 return false;
4918 }
4919
Brandon Jonesd1049182018-03-28 10:02:20 -07004920 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004921 {
4922 return false;
4923 }
4924
Brandon Jonesd1049182018-03-28 10:02:20 -07004925 SetRobustLengthParam(length, writeLength);
Geoff Lang0b031062016-10-13 14:30:04 -04004926 return true;
4927}
4928
Geoff Lang0b031062016-10-13 14:30:04 -04004929bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4930 GLuint index,
4931 GLenum pname,
4932 GLsizei bufSize,
4933 GLsizei *length,
4934 GLint *params)
4935{
4936 if (!ValidateRobustEntryPoint(context, bufSize))
4937 {
4938 return false;
4939 }
4940
Brandon Jonesd1049182018-03-28 10:02:20 -07004941 GLsizei writeLength = 0;
4942
4943 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004944 {
4945 return false;
4946 }
4947
Brandon Jonesd1049182018-03-28 10:02:20 -07004948 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004949 {
4950 return false;
4951 }
4952
Brandon Jonesd1049182018-03-28 10:02:20 -07004953 SetRobustLengthParam(length, writeLength);
4954
Geoff Lang0b031062016-10-13 14:30:04 -04004955 return true;
4956}
4957
Geoff Lang0b031062016-10-13 14:30:04 -04004958bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4959 GLuint index,
4960 GLenum pname,
4961 GLsizei bufSize,
4962 GLsizei *length,
4963 void **pointer)
4964{
4965 if (!ValidateRobustEntryPoint(context, bufSize))
4966 {
4967 return false;
4968 }
4969
Brandon Jonesd1049182018-03-28 10:02:20 -07004970 GLsizei writeLength = 0;
4971
4972 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, true, false))
Geoff Lang0b031062016-10-13 14:30:04 -04004973 {
4974 return false;
4975 }
4976
Brandon Jonesd1049182018-03-28 10:02:20 -07004977 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04004978 {
4979 return false;
4980 }
4981
Brandon Jonesd1049182018-03-28 10:02:20 -07004982 SetRobustLengthParam(length, writeLength);
4983
Geoff Lang0b031062016-10-13 14:30:04 -04004984 return true;
4985}
4986
Geoff Lang0b031062016-10-13 14:30:04 -04004987bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4988 GLuint index,
4989 GLenum pname,
4990 GLsizei bufSize,
4991 GLsizei *length,
4992 GLint *params)
4993{
4994 if (!ValidateRobustEntryPoint(context, bufSize))
4995 {
4996 return false;
4997 }
4998
Brandon Jonesd1049182018-03-28 10:02:20 -07004999 GLsizei writeLength = 0;
5000
5001 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04005002 {
5003 return false;
5004 }
5005
Brandon Jonesd1049182018-03-28 10:02:20 -07005006 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04005007 {
5008 return false;
5009 }
5010
Brandon Jonesd1049182018-03-28 10:02:20 -07005011 SetRobustLengthParam(length, writeLength);
5012
Geoff Lang0b031062016-10-13 14:30:04 -04005013 return true;
5014}
5015
Geoff Lang0b031062016-10-13 14:30:04 -04005016bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
5017 GLuint index,
5018 GLenum pname,
5019 GLsizei bufSize,
5020 GLsizei *length,
5021 GLuint *params)
5022{
5023 if (!ValidateRobustEntryPoint(context, bufSize))
5024 {
5025 return false;
5026 }
5027
Brandon Jonesd1049182018-03-28 10:02:20 -07005028 GLsizei writeLength = 0;
5029
5030 if (!ValidateGetVertexAttribBase(context, index, pname, &writeLength, false, true))
Geoff Lang0b031062016-10-13 14:30:04 -04005031 {
5032 return false;
5033 }
5034
Brandon Jonesd1049182018-03-28 10:02:20 -07005035 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang0b031062016-10-13 14:30:04 -04005036 {
5037 return false;
5038 }
5039
Brandon Jonesd1049182018-03-28 10:02:20 -07005040 SetRobustLengthParam(length, writeLength);
5041
Geoff Lang0b031062016-10-13 14:30:04 -04005042 return true;
5043}
5044
Geoff Lang6899b872016-10-14 11:30:13 -04005045bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
5046 GLuint program,
5047 GLuint uniformBlockIndex,
5048 GLenum pname,
5049 GLsizei bufSize,
5050 GLsizei *length,
5051 GLint *params)
5052{
5053 if (!ValidateRobustEntryPoint(context, bufSize))
5054 {
5055 return false;
5056 }
5057
Brandon Jonesd1049182018-03-28 10:02:20 -07005058 GLsizei writeLength = 0;
5059
5060 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname,
5061 &writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005062 {
5063 return false;
5064 }
5065
Brandon Jonesd1049182018-03-28 10:02:20 -07005066 if (!ValidateRobustBufferSize(context, bufSize, writeLength))
Geoff Lang6899b872016-10-14 11:30:13 -04005067 {
5068 return false;
5069 }
5070
Brandon Jonesd1049182018-03-28 10:02:20 -07005071 SetRobustLengthParam(length, writeLength);
5072
Geoff Lang6899b872016-10-14 11:30:13 -04005073 return true;
5074}
5075
Brandon Jones416aaf92018-04-10 08:10:16 -07005076bool ValidateGetInternalformativRobustANGLE(Context *context,
Geoff Lang0a9661f2016-10-20 10:59:20 -07005077 GLenum target,
5078 GLenum internalformat,
5079 GLenum pname,
5080 GLsizei bufSize,
5081 GLsizei *length,
5082 GLint *params)
5083{
5084 if (!ValidateRobustEntryPoint(context, bufSize))
5085 {
5086 return false;
5087 }
5088
Brandon Jonesd1049182018-03-28 10:02:20 -07005089 GLsizei numParams = 0;
5090
5091 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
5092 &numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005093 {
5094 return false;
5095 }
5096
Brandon Jonesd1049182018-03-28 10:02:20 -07005097 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang0a9661f2016-10-20 10:59:20 -07005098 {
5099 return false;
5100 }
5101
Brandon Jonesd1049182018-03-28 10:02:20 -07005102 SetRobustLengthParam(length, numParams);
5103
Geoff Lang0a9661f2016-10-20 10:59:20 -07005104 return true;
5105}
5106
Jamie Madill5b772312018-03-08 20:28:32 -05005107bool ValidateVertexFormatBase(Context *context,
Shao80957d92017-02-20 21:25:59 +08005108 GLuint attribIndex,
5109 GLint size,
5110 GLenum type,
5111 GLboolean pureInteger)
5112{
5113 const Caps &caps = context->getCaps();
5114 if (attribIndex >= caps.maxVertexAttributes)
5115 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005116 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08005117 return false;
5118 }
5119
5120 if (size < 1 || size > 4)
5121 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005122 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04005123 return false;
Shao80957d92017-02-20 21:25:59 +08005124 }
5125
5126 switch (type)
5127 {
5128 case GL_BYTE:
5129 case GL_UNSIGNED_BYTE:
5130 case GL_SHORT:
5131 case GL_UNSIGNED_SHORT:
5132 break;
5133
5134 case GL_INT:
5135 case GL_UNSIGNED_INT:
5136 if (context->getClientMajorVersion() < 3)
5137 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005138 context->handleError(InvalidEnum()
5139 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005140 return false;
5141 }
5142 break;
5143
5144 case GL_FIXED:
5145 case GL_FLOAT:
5146 if (pureInteger)
5147 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005148 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005149 return false;
5150 }
5151 break;
5152
5153 case GL_HALF_FLOAT:
5154 if (context->getClientMajorVersion() < 3)
5155 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005156 context->handleError(InvalidEnum()
5157 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005158 return false;
5159 }
5160 if (pureInteger)
5161 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005162 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005163 return false;
5164 }
5165 break;
5166
5167 case GL_INT_2_10_10_10_REV:
5168 case GL_UNSIGNED_INT_2_10_10_10_REV:
5169 if (context->getClientMajorVersion() < 3)
5170 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005171 context->handleError(InvalidEnum()
5172 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08005173 return false;
5174 }
5175 if (pureInteger)
5176 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005177 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08005178 return false;
5179 }
5180 if (size != 4)
5181 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005182 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
5183 "UNSIGNED_INT_2_10_10_10_REV and "
5184 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08005185 return false;
5186 }
5187 break;
5188
5189 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005190 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08005191 return false;
5192 }
5193
5194 return true;
5195}
5196
Geoff Lang76e65652017-03-27 14:58:02 -04005197// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5198// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5199// specified clear value and the type of a buffer that is being cleared generates an
5200// INVALID_OPERATION error instead of producing undefined results
Jamie Madill5b772312018-03-08 20:28:32 -05005201bool ValidateWebGLFramebufferAttachmentClearType(Context *context,
Geoff Lang76e65652017-03-27 14:58:02 -04005202 GLint drawbuffer,
5203 const GLenum *validComponentTypes,
5204 size_t validComponentTypeCount)
5205{
5206 const FramebufferAttachment *attachment =
5207 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5208 if (attachment)
5209 {
5210 GLenum componentType = attachment->getFormat().info->componentType;
5211 const GLenum *end = validComponentTypes + validComponentTypeCount;
5212 if (std::find(validComponentTypes, end, componentType) == end)
5213 {
5214 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005215 InvalidOperation()
5216 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005217 return false;
5218 }
5219 }
5220
5221 return true;
5222}
5223
Jamie Madill5b772312018-03-08 20:28:32 -05005224bool ValidateRobustCompressedTexImageBase(Context *context, GLsizei imageSize, GLsizei dataSize)
Corentin Wallezb2931602017-04-11 15:58:57 -04005225{
5226 if (!ValidateRobustEntryPoint(context, dataSize))
5227 {
5228 return false;
5229 }
5230
Corentin Wallez336129f2017-10-17 15:55:40 -04005231 gl::Buffer *pixelUnpackBuffer =
5232 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04005233 if (pixelUnpackBuffer == nullptr)
5234 {
5235 if (dataSize < imageSize)
5236 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005237 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005238 }
5239 }
5240 return true;
5241}
5242
Jamie Madill5b772312018-03-08 20:28:32 -05005243bool ValidateGetBufferParameterBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04005244 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005245 GLenum pname,
5246 bool pointerVersion,
5247 GLsizei *numParams)
5248{
5249 if (numParams)
5250 {
5251 *numParams = 0;
5252 }
5253
Corentin Walleze4477002017-12-01 14:39:58 -05005254 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04005255 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005256 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005257 return false;
5258 }
5259
5260 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5261 if (!buffer)
5262 {
5263 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005264 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005265 return false;
5266 }
5267
5268 const Extensions &extensions = context->getExtensions();
5269
5270 switch (pname)
5271 {
5272 case GL_BUFFER_USAGE:
5273 case GL_BUFFER_SIZE:
5274 break;
5275
5276 case GL_BUFFER_ACCESS_OES:
5277 if (!extensions.mapBuffer)
5278 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005279 context->handleError(InvalidEnum()
5280 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005281 return false;
5282 }
5283 break;
5284
5285 case GL_BUFFER_MAPPED:
5286 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5287 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5288 !extensions.mapBufferRange)
5289 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005290 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5291 "GL_OES_mapbuffer or "
5292 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005293 return false;
5294 }
5295 break;
5296
5297 case GL_BUFFER_MAP_POINTER:
5298 if (!pointerVersion)
5299 {
5300 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005301 InvalidEnum()
5302 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005303 return false;
5304 }
5305 break;
5306
5307 case GL_BUFFER_ACCESS_FLAGS:
5308 case GL_BUFFER_MAP_OFFSET:
5309 case GL_BUFFER_MAP_LENGTH:
5310 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5311 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005312 context->handleError(InvalidEnum()
5313 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005314 return false;
5315 }
5316 break;
5317
5318 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005319 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005320 return false;
5321 }
5322
5323 // All buffer parameter queries return one value.
5324 if (numParams)
5325 {
5326 *numParams = 1;
5327 }
5328
5329 return true;
5330}
5331
5332bool ValidateGetRenderbufferParameterivBase(Context *context,
5333 GLenum target,
5334 GLenum pname,
5335 GLsizei *length)
5336{
5337 if (length)
5338 {
5339 *length = 0;
5340 }
5341
5342 if (target != GL_RENDERBUFFER)
5343 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005344 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005345 return false;
5346 }
5347
5348 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5349 if (renderbuffer == nullptr)
5350 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005351 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005352 return false;
5353 }
5354
5355 switch (pname)
5356 {
5357 case GL_RENDERBUFFER_WIDTH:
5358 case GL_RENDERBUFFER_HEIGHT:
5359 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5360 case GL_RENDERBUFFER_RED_SIZE:
5361 case GL_RENDERBUFFER_GREEN_SIZE:
5362 case GL_RENDERBUFFER_BLUE_SIZE:
5363 case GL_RENDERBUFFER_ALPHA_SIZE:
5364 case GL_RENDERBUFFER_DEPTH_SIZE:
5365 case GL_RENDERBUFFER_STENCIL_SIZE:
5366 break;
5367
5368 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5369 if (!context->getExtensions().framebufferMultisample)
5370 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005371 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005372 return false;
5373 }
5374 break;
5375
5376 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005377 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005378 return false;
5379 }
5380
5381 if (length)
5382 {
5383 *length = 1;
5384 }
5385 return true;
5386}
5387
5388bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5389{
5390 if (length)
5391 {
5392 *length = 0;
5393 }
5394
5395 if (GetValidShader(context, shader) == nullptr)
5396 {
5397 return false;
5398 }
5399
5400 switch (pname)
5401 {
5402 case GL_SHADER_TYPE:
5403 case GL_DELETE_STATUS:
5404 case GL_COMPILE_STATUS:
5405 case GL_INFO_LOG_LENGTH:
5406 case GL_SHADER_SOURCE_LENGTH:
5407 break;
5408
5409 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5410 if (!context->getExtensions().translatedShaderSource)
5411 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005412 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005413 return false;
5414 }
5415 break;
5416
5417 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005418 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005419 return false;
5420 }
5421
5422 if (length)
5423 {
5424 *length = 1;
5425 }
5426 return true;
5427}
5428
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005429bool ValidateGetTexParameterBase(Context *context,
5430 TextureType target,
5431 GLenum pname,
5432 GLsizei *length)
Jamie Madillbe849e42017-05-02 15:49:00 -04005433{
5434 if (length)
5435 {
5436 *length = 0;
5437 }
5438
5439 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5440 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005441 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005442 return false;
5443 }
5444
5445 if (context->getTargetTexture(target) == nullptr)
5446 {
5447 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005448 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005449 return false;
5450 }
5451
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005452 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5453 {
5454 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5455 return false;
5456 }
5457
Jamie Madillbe849e42017-05-02 15:49:00 -04005458 switch (pname)
5459 {
5460 case GL_TEXTURE_MAG_FILTER:
5461 case GL_TEXTURE_MIN_FILTER:
5462 case GL_TEXTURE_WRAP_S:
5463 case GL_TEXTURE_WRAP_T:
5464 break;
5465
5466 case GL_TEXTURE_USAGE_ANGLE:
5467 if (!context->getExtensions().textureUsage)
5468 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005469 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005470 return false;
5471 }
5472 break;
5473
5474 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05005475 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04005476 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005477 return false;
5478 }
5479 break;
5480
5481 case GL_TEXTURE_IMMUTABLE_FORMAT:
5482 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5483 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005484 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005485 return false;
5486 }
5487 break;
5488
5489 case GL_TEXTURE_WRAP_R:
5490 case GL_TEXTURE_IMMUTABLE_LEVELS:
5491 case GL_TEXTURE_SWIZZLE_R:
5492 case GL_TEXTURE_SWIZZLE_G:
5493 case GL_TEXTURE_SWIZZLE_B:
5494 case GL_TEXTURE_SWIZZLE_A:
5495 case GL_TEXTURE_BASE_LEVEL:
5496 case GL_TEXTURE_MAX_LEVEL:
5497 case GL_TEXTURE_MIN_LOD:
5498 case GL_TEXTURE_MAX_LOD:
5499 case GL_TEXTURE_COMPARE_MODE:
5500 case GL_TEXTURE_COMPARE_FUNC:
5501 if (context->getClientMajorVersion() < 3)
5502 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005503 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005504 return false;
5505 }
5506 break;
5507
5508 case GL_TEXTURE_SRGB_DECODE_EXT:
5509 if (!context->getExtensions().textureSRGBDecode)
5510 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005511 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005512 return false;
5513 }
5514 break;
5515
Yunchao Hebacaa712018-01-30 14:01:39 +08005516 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5517 if (context->getClientVersion() < Version(3, 1))
5518 {
5519 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
5520 return false;
5521 }
5522 break;
5523
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005524 case GL_GENERATE_MIPMAP:
5525 case GL_TEXTURE_CROP_RECT_OES:
5526 // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
5527 // after GL_OES_draw_texture functionality implemented
5528 if (context->getClientMajorVersion() > 1)
5529 {
5530 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5531 return false;
5532 }
5533 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005534 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005535 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005536 return false;
5537 }
5538
5539 if (length)
5540 {
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005541 *length = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005542 }
5543 return true;
5544}
5545
5546bool ValidateGetVertexAttribBase(Context *context,
5547 GLuint index,
5548 GLenum pname,
5549 GLsizei *length,
5550 bool pointer,
5551 bool pureIntegerEntryPoint)
5552{
5553 if (length)
5554 {
5555 *length = 0;
5556 }
5557
5558 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5559 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005560 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005561 return false;
5562 }
5563
5564 if (index >= context->getCaps().maxVertexAttributes)
5565 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005566 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005567 return false;
5568 }
5569
5570 if (pointer)
5571 {
5572 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5573 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005574 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005575 return false;
5576 }
5577 }
5578 else
5579 {
5580 switch (pname)
5581 {
5582 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5583 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5584 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5585 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5586 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5587 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5588 case GL_CURRENT_VERTEX_ATTRIB:
5589 break;
5590
5591 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5592 static_assert(
5593 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5594 "ANGLE extension enums not equal to GL enums.");
5595 if (context->getClientMajorVersion() < 3 &&
5596 !context->getExtensions().instancedArrays)
5597 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005598 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5599 "requires OpenGL ES 3.0 or "
5600 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005601 return false;
5602 }
5603 break;
5604
5605 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5606 if (context->getClientMajorVersion() < 3)
5607 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005608 context->handleError(
5609 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005610 return false;
5611 }
5612 break;
5613
5614 case GL_VERTEX_ATTRIB_BINDING:
5615 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5616 if (context->getClientVersion() < ES_3_1)
5617 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005618 context->handleError(InvalidEnum()
5619 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005620 return false;
5621 }
5622 break;
5623
5624 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005625 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005626 return false;
5627 }
5628 }
5629
5630 if (length)
5631 {
5632 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5633 {
5634 *length = 4;
5635 }
5636 else
5637 {
5638 *length = 1;
5639 }
5640 }
5641
5642 return true;
5643}
5644
Jamie Madill4928b7c2017-06-20 12:57:39 -04005645bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005646 GLint x,
5647 GLint y,
5648 GLsizei width,
5649 GLsizei height,
5650 GLenum format,
5651 GLenum type,
5652 GLsizei bufSize,
5653 GLsizei *length,
5654 GLsizei *columns,
5655 GLsizei *rows,
5656 void *pixels)
5657{
5658 if (length != nullptr)
5659 {
5660 *length = 0;
5661 }
5662 if (rows != nullptr)
5663 {
5664 *rows = 0;
5665 }
5666 if (columns != nullptr)
5667 {
5668 *columns = 0;
5669 }
5670
5671 if (width < 0 || height < 0)
5672 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005673 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005674 return false;
5675 }
5676
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005677 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005678
Jamie Madill427064d2018-04-13 16:20:34 -04005679 if (!ValidateFramebufferComplete(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005680 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005681 return false;
5682 }
5683
Jamie Madille98b1b52018-03-08 09:47:23 -05005684 if (readFramebuffer->id() != 0 && !ValidateFramebufferNotMultisampled(context, readFramebuffer))
Jamie Madillbe849e42017-05-02 15:49:00 -04005685 {
Jamie Madillbe849e42017-05-02 15:49:00 -04005686 return false;
5687 }
5688
Jamie Madill690c8eb2018-03-12 15:20:03 -04005689 Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005690 ASSERT(framebuffer);
5691
5692 if (framebuffer->getReadBufferState() == GL_NONE)
5693 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005694 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005695 return false;
5696 }
5697
5698 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5699 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5700 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5701 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5702 // situation is an application error that would lead to a crash in ANGLE.
5703 if (readBuffer == nullptr)
5704 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005705 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005706 return false;
5707 }
5708
Martin Radev28031682017-07-28 14:47:56 +03005709 // ANGLE_multiview, Revision 1:
5710 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
Olli Etuaho8acb1b62018-07-30 16:20:54 +03005711 // current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
5712 // in the current read framebuffer is more than one.
5713 if (framebuffer->readDisallowedByMultiview())
Martin Radev28031682017-07-28 14:47:56 +03005714 {
5715 context->handleError(InvalidFramebufferOperation()
5716 << "Attempting to read from a multi-view framebuffer.");
5717 return false;
5718 }
5719
Geoff Lang280ba992017-04-18 16:30:58 -04005720 if (context->getExtensions().webglCompatibility)
5721 {
5722 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5723 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5724 // and type before validating the combination of format and type. However, the
5725 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5726 // verifies that GL_INVALID_OPERATION is generated.
5727 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5728 // dEQP/WebGL.
5729 if (!ValidReadPixelsFormatEnum(context, format))
5730 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005731 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005732 return false;
5733 }
5734
5735 if (!ValidReadPixelsTypeEnum(context, type))
5736 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005737 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005738 return false;
5739 }
5740 }
5741
Jamie Madill690c8eb2018-03-12 15:20:03 -04005742 GLenum currentFormat = GL_NONE;
5743 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadFormat(context, &currentFormat));
5744
5745 GLenum currentType = GL_NONE;
5746 ANGLE_VALIDATION_TRY(framebuffer->getImplementationColorReadType(context, &currentType));
5747
Jamie Madillbe849e42017-05-02 15:49:00 -04005748 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5749
5750 bool validFormatTypeCombination =
5751 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5752
5753 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5754 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005755 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005756 return false;
5757 }
5758
5759 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005760 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005761 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5762 {
5763 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005764 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005765 return false;
5766 }
James Darpiniane8a93c62018-01-04 18:02:24 -08005767 if (context->getExtensions().webglCompatibility && pixelPackBuffer != nullptr &&
5768 pixelPackBuffer->isBoundForTransformFeedbackAndOtherUse())
5769 {
5770 ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelPackBufferBoundForTransformFeedback);
5771 return false;
5772 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005773
5774 // .. the data would be packed to the buffer object such that the memory writes required
5775 // would exceed the data store size.
5776 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5777 const gl::Extents size(width, height, 1);
5778 const auto &pack = context->getGLState().getPackState();
5779
Jamie Madillca2ff382018-07-11 09:01:17 -04005780 GLuint endByte = 0;
5781 if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
Jamie Madillbe849e42017-05-02 15:49:00 -04005782 {
Jamie Madillca2ff382018-07-11 09:01:17 -04005783 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005784 return false;
5785 }
5786
Jamie Madillbe849e42017-05-02 15:49:00 -04005787 if (bufSize >= 0)
5788 {
5789 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5790 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005791 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005792 return false;
5793 }
5794 }
5795
5796 if (pixelPackBuffer != nullptr)
5797 {
5798 CheckedNumeric<size_t> checkedEndByte(endByte);
5799 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5800 checkedEndByte += checkedOffset;
5801
5802 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5803 {
5804 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005805 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005806 return false;
5807 }
5808 }
5809
5810 if (pixelPackBuffer == nullptr && length != nullptr)
5811 {
5812 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5813 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005814 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005815 return false;
5816 }
5817
5818 *length = static_cast<GLsizei>(endByte);
5819 }
5820
Geoff Langa953b522018-02-21 16:56:23 -05005821 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
Jamie Madillbe849e42017-05-02 15:49:00 -04005822 angle::CheckedNumeric<int> clippedExtent(length);
5823 if (start < 0)
5824 {
5825 // "subtract" the area that is less than 0
5826 clippedExtent += start;
5827 }
5828
Geoff Langa953b522018-02-21 16:56:23 -05005829 angle::CheckedNumeric<int> readExtent = start;
5830 readExtent += length;
5831 if (!readExtent.IsValid())
5832 {
5833 return false;
5834 }
5835
5836 if (readExtent.ValueOrDie() > bufferSize)
Jamie Madillbe849e42017-05-02 15:49:00 -04005837 {
5838 // Subtract the region to the right of the read buffer
5839 clippedExtent -= (readExtent - bufferSize);
5840 }
5841
5842 if (!clippedExtent.IsValid())
5843 {
Geoff Langa953b522018-02-21 16:56:23 -05005844 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005845 }
5846
Geoff Langa953b522018-02-21 16:56:23 -05005847 *outExtent = std::max(clippedExtent.ValueOrDie(), 0);
5848 return true;
Jamie Madillbe849e42017-05-02 15:49:00 -04005849 };
5850
Geoff Langa953b522018-02-21 16:56:23 -05005851 GLsizei writtenColumns = 0;
5852 if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
5853 {
5854 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5855 return false;
5856 }
5857
5858 GLsizei writtenRows = 0;
5859 if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
5860 {
5861 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
5862 return false;
5863 }
5864
Jamie Madillbe849e42017-05-02 15:49:00 -04005865 if (columns != nullptr)
5866 {
Geoff Langa953b522018-02-21 16:56:23 -05005867 *columns = writtenColumns;
Jamie Madillbe849e42017-05-02 15:49:00 -04005868 }
5869
5870 if (rows != nullptr)
5871 {
Geoff Langa953b522018-02-21 16:56:23 -05005872 *rows = writtenRows;
Jamie Madillbe849e42017-05-02 15:49:00 -04005873 }
5874
5875 return true;
5876}
5877
5878template <typename ParamType>
5879bool ValidateTexParameterBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005880 TextureType target,
Jamie Madillbe849e42017-05-02 15:49:00 -04005881 GLenum pname,
5882 GLsizei bufSize,
5883 const ParamType *params)
5884{
5885 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5886 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005887 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005888 return false;
5889 }
5890
5891 if (context->getTargetTexture(target) == nullptr)
5892 {
5893 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005894 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005895 return false;
5896 }
5897
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005898 const GLsizei minBufSize = GetTexParameterCount(pname);
Jamie Madillbe849e42017-05-02 15:49:00 -04005899 if (bufSize >= 0 && bufSize < minBufSize)
5900 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005901 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005902 return false;
5903 }
5904
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005905 if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
5906 {
5907 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5908 return false;
5909 }
5910
Jamie Madillbe849e42017-05-02 15:49:00 -04005911 switch (pname)
5912 {
5913 case GL_TEXTURE_WRAP_R:
5914 case GL_TEXTURE_SWIZZLE_R:
5915 case GL_TEXTURE_SWIZZLE_G:
5916 case GL_TEXTURE_SWIZZLE_B:
5917 case GL_TEXTURE_SWIZZLE_A:
5918 case GL_TEXTURE_BASE_LEVEL:
5919 case GL_TEXTURE_MAX_LEVEL:
5920 case GL_TEXTURE_COMPARE_MODE:
5921 case GL_TEXTURE_COMPARE_FUNC:
5922 case GL_TEXTURE_MIN_LOD:
5923 case GL_TEXTURE_MAX_LOD:
5924 if (context->getClientMajorVersion() < 3)
5925 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005926 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005927 return false;
5928 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005929 if (target == TextureType::External && !context->getExtensions().eglImageExternalEssl3)
Jamie Madillbe849e42017-05-02 15:49:00 -04005930 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005931 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5932 "available without "
5933 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005934 return false;
5935 }
5936 break;
5937
Lingfeng Yangf97641c2018-06-21 19:22:45 -07005938 case GL_GENERATE_MIPMAP:
5939 case GL_TEXTURE_CROP_RECT_OES:
5940 if (context->getClientMajorVersion() > 1)
5941 {
5942 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
5943 return false;
5944 }
5945 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005946 default:
5947 break;
5948 }
5949
Corentin Wallezf0e89be2017-11-08 14:00:32 -08005950 if (target == TextureType::_2DMultisample)
JiangYizhou4cff8d62017-07-06 14:54:09 +08005951 {
5952 switch (pname)
5953 {
5954 case GL_TEXTURE_MIN_FILTER:
5955 case GL_TEXTURE_MAG_FILTER:
5956 case GL_TEXTURE_WRAP_S:
5957 case GL_TEXTURE_WRAP_T:
5958 case GL_TEXTURE_WRAP_R:
5959 case GL_TEXTURE_MIN_LOD:
5960 case GL_TEXTURE_MAX_LOD:
5961 case GL_TEXTURE_COMPARE_MODE:
5962 case GL_TEXTURE_COMPARE_FUNC:
5963 context->handleError(InvalidEnum()
5964 << "Invalid parameter for 2D multisampled textures.");
5965 return false;
5966 }
5967 }
5968
Jamie Madillbe849e42017-05-02 15:49:00 -04005969 switch (pname)
5970 {
5971 case GL_TEXTURE_WRAP_S:
5972 case GL_TEXTURE_WRAP_T:
5973 case GL_TEXTURE_WRAP_R:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005974 {
5975 bool restrictedWrapModes =
5976 target == TextureType::External || target == TextureType::Rectangle;
5977 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
Jamie Madillbe849e42017-05-02 15:49:00 -04005978 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005979 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005980 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005981 }
5982 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005983
5984 case GL_TEXTURE_MIN_FILTER:
Lingfeng Yang038dd532018-03-29 17:31:52 -07005985 {
5986 bool restrictedMinFilter =
5987 target == TextureType::External || target == TextureType::Rectangle;
5988 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
Jamie Madillbe849e42017-05-02 15:49:00 -04005989 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07005990 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04005991 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07005992 }
5993 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04005994
5995 case GL_TEXTURE_MAG_FILTER:
5996 if (!ValidateTextureMagFilterValue(context, params))
5997 {
5998 return false;
5999 }
6000 break;
6001
6002 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04006003 if (!context->getExtensions().textureUsage)
6004 {
6005 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6006 return false;
6007 }
6008
Jamie Madillbe849e42017-05-02 15:49:00 -04006009 switch (ConvertToGLenum(params[0]))
6010 {
6011 case GL_NONE:
6012 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
6013 break;
6014
6015 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006016 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006017 return false;
6018 }
6019 break;
6020
6021 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Lingfeng Yang038dd532018-03-29 17:31:52 -07006022 {
6023 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6024 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
Jamie Madillbe849e42017-05-02 15:49:00 -04006025 {
Lingfeng Yang038dd532018-03-29 17:31:52 -07006026 return false;
Jamie Madillbe849e42017-05-02 15:49:00 -04006027 }
Lingfeng Yang038dd532018-03-29 17:31:52 -07006028 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
6029 }
6030 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006031
6032 case GL_TEXTURE_MIN_LOD:
6033 case GL_TEXTURE_MAX_LOD:
6034 // any value is permissible
6035 break;
6036
6037 case GL_TEXTURE_COMPARE_MODE:
6038 if (!ValidateTextureCompareModeValue(context, params))
6039 {
6040 return false;
6041 }
6042 break;
6043
6044 case GL_TEXTURE_COMPARE_FUNC:
6045 if (!ValidateTextureCompareFuncValue(context, params))
6046 {
6047 return false;
6048 }
6049 break;
6050
6051 case GL_TEXTURE_SWIZZLE_R:
6052 case GL_TEXTURE_SWIZZLE_G:
6053 case GL_TEXTURE_SWIZZLE_B:
6054 case GL_TEXTURE_SWIZZLE_A:
6055 switch (ConvertToGLenum(params[0]))
6056 {
6057 case GL_RED:
6058 case GL_GREEN:
6059 case GL_BLUE:
6060 case GL_ALPHA:
6061 case GL_ZERO:
6062 case GL_ONE:
6063 break;
6064
6065 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006066 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006067 return false;
6068 }
6069 break;
6070
6071 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006072 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006073 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006074 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006075 return false;
6076 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006077 if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006078 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05006079 context->handleError(InvalidOperation()
6080 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04006081 return false;
6082 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006083 if (target == TextureType::_2DMultisample && static_cast<GLuint>(params[0]) != 0)
JiangYizhou4cff8d62017-07-06 14:54:09 +08006084 {
6085 context->handleError(InvalidOperation()
6086 << "Base level must be 0 for multisampled textures.");
6087 return false;
6088 }
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006089 if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04006090 {
6091 context->handleError(InvalidOperation()
6092 << "Base level must be 0 for rectangle textures.");
6093 return false;
6094 }
Jamie Madillbe849e42017-05-02 15:49:00 -04006095 break;
6096
6097 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05006098 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04006099 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006100 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04006101 return false;
6102 }
6103 break;
6104
6105 case GL_DEPTH_STENCIL_TEXTURE_MODE:
6106 if (context->getClientVersion() < Version(3, 1))
6107 {
Brandon Jones6cad5662017-06-14 13:25:13 -07006108 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04006109 return false;
6110 }
6111 switch (ConvertToGLenum(params[0]))
6112 {
6113 case GL_DEPTH_COMPONENT:
6114 case GL_STENCIL_INDEX:
6115 break;
6116
6117 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006118 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006119 return false;
6120 }
6121 break;
6122
6123 case GL_TEXTURE_SRGB_DECODE_EXT:
6124 if (!ValidateTextureSRGBDecodeValue(context, params))
6125 {
6126 return false;
6127 }
6128 break;
6129
Lingfeng Yangf97641c2018-06-21 19:22:45 -07006130 case GL_GENERATE_MIPMAP:
6131 case GL_TEXTURE_CROP_RECT_OES:
6132 if (context->getClientMajorVersion() > 1)
6133 {
6134 ANGLE_VALIDATION_ERR(context, InvalidEnum(), GLES1Only);
6135 return false;
6136 }
6137 break;
Jamie Madillbe849e42017-05-02 15:49:00 -04006138 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07006139 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04006140 return false;
6141 }
6142
6143 return true;
6144}
6145
Corentin Wallezf0e89be2017-11-08 14:00:32 -08006146template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLfloat *);
6147template bool ValidateTexParameterBase(Context *, TextureType, GLenum, GLsizei, const GLint *);
Jamie Madillbe849e42017-05-02 15:49:00 -04006148
Jamie Madill5b772312018-03-08 20:28:32 -05006149bool ValidateVertexAttribIndex(Context *context, GLuint index)
Jamie Madill12e957f2017-08-26 21:42:26 -04006150{
6151 if (index >= MAX_VERTEX_ATTRIBS)
6152 {
6153 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
6154 return false;
6155 }
6156
6157 return true;
6158}
6159
6160bool ValidateGetActiveUniformBlockivBase(Context *context,
6161 GLuint program,
6162 GLuint uniformBlockIndex,
6163 GLenum pname,
6164 GLsizei *length)
6165{
6166 if (length)
6167 {
6168 *length = 0;
6169 }
6170
6171 if (context->getClientMajorVersion() < 3)
6172 {
6173 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6174 return false;
6175 }
6176
6177 Program *programObject = GetValidProgram(context, program);
6178 if (!programObject)
6179 {
6180 return false;
6181 }
6182
6183 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
6184 {
6185 context->handleError(InvalidValue()
6186 << "uniformBlockIndex exceeds active uniform block count.");
6187 return false;
6188 }
6189
6190 switch (pname)
6191 {
6192 case GL_UNIFORM_BLOCK_BINDING:
6193 case GL_UNIFORM_BLOCK_DATA_SIZE:
6194 case GL_UNIFORM_BLOCK_NAME_LENGTH:
6195 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
6196 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
6197 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
6198 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
6199 break;
6200
6201 default:
6202 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6203 return false;
6204 }
6205
6206 if (length)
6207 {
6208 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
6209 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08006210 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04006211 programObject->getUniformBlockByIndex(uniformBlockIndex);
6212 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
6213 }
6214 else
6215 {
6216 *length = 1;
6217 }
6218 }
6219
6220 return true;
6221}
6222
Jamie Madill9696d072017-08-26 23:19:57 -04006223template <typename ParamType>
6224bool ValidateSamplerParameterBase(Context *context,
6225 GLuint sampler,
6226 GLenum pname,
6227 GLsizei bufSize,
6228 ParamType *params)
6229{
6230 if (context->getClientMajorVersion() < 3)
6231 {
6232 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6233 return false;
6234 }
6235
6236 if (!context->isSampler(sampler))
6237 {
6238 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6239 return false;
6240 }
6241
6242 const GLsizei minBufSize = 1;
6243 if (bufSize >= 0 && bufSize < minBufSize)
6244 {
6245 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
6246 return false;
6247 }
6248
6249 switch (pname)
6250 {
6251 case GL_TEXTURE_WRAP_S:
6252 case GL_TEXTURE_WRAP_T:
6253 case GL_TEXTURE_WRAP_R:
6254 if (!ValidateTextureWrapModeValue(context, params, false))
6255 {
6256 return false;
6257 }
6258 break;
6259
6260 case GL_TEXTURE_MIN_FILTER:
6261 if (!ValidateTextureMinFilterValue(context, params, false))
6262 {
6263 return false;
6264 }
6265 break;
6266
6267 case GL_TEXTURE_MAG_FILTER:
6268 if (!ValidateTextureMagFilterValue(context, params))
6269 {
6270 return false;
6271 }
6272 break;
6273
6274 case GL_TEXTURE_MIN_LOD:
6275 case GL_TEXTURE_MAX_LOD:
6276 // any value is permissible
6277 break;
6278
6279 case GL_TEXTURE_COMPARE_MODE:
6280 if (!ValidateTextureCompareModeValue(context, params))
6281 {
6282 return false;
6283 }
6284 break;
6285
6286 case GL_TEXTURE_COMPARE_FUNC:
6287 if (!ValidateTextureCompareFuncValue(context, params))
6288 {
6289 return false;
6290 }
6291 break;
6292
6293 case GL_TEXTURE_SRGB_DECODE_EXT:
6294 if (!ValidateTextureSRGBDecodeValue(context, params))
6295 {
6296 return false;
6297 }
6298 break;
6299
Luc Ferron1b1a8642018-01-23 15:12:01 -05006300 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6301 {
6302 GLfloat paramValue = static_cast<GLfloat>(params[0]);
6303 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
6304 {
6305 return false;
6306 }
6307 }
6308 break;
6309
Jamie Madill9696d072017-08-26 23:19:57 -04006310 default:
6311 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6312 return false;
6313 }
6314
6315 return true;
6316}
6317
6318template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
6319template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
6320
6321bool ValidateGetSamplerParameterBase(Context *context,
6322 GLuint sampler,
6323 GLenum pname,
6324 GLsizei *length)
6325{
6326 if (length)
6327 {
6328 *length = 0;
6329 }
6330
6331 if (context->getClientMajorVersion() < 3)
6332 {
6333 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
6334 return false;
6335 }
6336
6337 if (!context->isSampler(sampler))
6338 {
6339 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
6340 return false;
6341 }
6342
6343 switch (pname)
6344 {
6345 case GL_TEXTURE_WRAP_S:
6346 case GL_TEXTURE_WRAP_T:
6347 case GL_TEXTURE_WRAP_R:
6348 case GL_TEXTURE_MIN_FILTER:
6349 case GL_TEXTURE_MAG_FILTER:
6350 case GL_TEXTURE_MIN_LOD:
6351 case GL_TEXTURE_MAX_LOD:
6352 case GL_TEXTURE_COMPARE_MODE:
6353 case GL_TEXTURE_COMPARE_FUNC:
6354 break;
6355
Luc Ferron1b1a8642018-01-23 15:12:01 -05006356 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
6357 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
6358 {
6359 return false;
6360 }
6361 break;
6362
Jamie Madill9696d072017-08-26 23:19:57 -04006363 case GL_TEXTURE_SRGB_DECODE_EXT:
6364 if (!context->getExtensions().textureSRGBDecode)
6365 {
6366 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
6367 return false;
6368 }
6369 break;
6370
6371 default:
6372 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6373 return false;
6374 }
6375
6376 if (length)
6377 {
6378 *length = 1;
6379 }
6380 return true;
6381}
6382
6383bool ValidateGetInternalFormativBase(Context *context,
6384 GLenum target,
6385 GLenum internalformat,
6386 GLenum pname,
6387 GLsizei bufSize,
6388 GLsizei *numParams)
6389{
6390 if (numParams)
6391 {
6392 *numParams = 0;
6393 }
6394
6395 if (context->getClientMajorVersion() < 3)
6396 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08006397 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04006398 return false;
6399 }
6400
6401 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
Yuly Novikovf15f8862018-06-04 18:59:41 -04006402 if (!formatCaps.renderbuffer)
Jamie Madill9696d072017-08-26 23:19:57 -04006403 {
6404 context->handleError(InvalidEnum() << "Internal format is not renderable.");
6405 return false;
6406 }
6407
6408 switch (target)
6409 {
6410 case GL_RENDERBUFFER:
6411 break;
6412
6413 case GL_TEXTURE_2D_MULTISAMPLE:
6414 if (context->getClientVersion() < ES_3_1)
6415 {
6416 context->handleError(InvalidOperation()
6417 << "Texture target requires at least OpenGL ES 3.1.");
6418 return false;
6419 }
6420 break;
6421
6422 default:
6423 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
6424 return false;
6425 }
6426
6427 if (bufSize < 0)
6428 {
6429 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
6430 return false;
6431 }
6432
6433 GLsizei maxWriteParams = 0;
6434 switch (pname)
6435 {
6436 case GL_NUM_SAMPLE_COUNTS:
6437 maxWriteParams = 1;
6438 break;
6439
6440 case GL_SAMPLES:
6441 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
6442 break;
6443
6444 default:
6445 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
6446 return false;
6447 }
6448
6449 if (numParams)
6450 {
6451 // glGetInternalFormativ will not overflow bufSize
6452 *numParams = std::min(bufSize, maxWriteParams);
6453 }
6454
6455 return true;
6456}
6457
Jamie Madille98b1b52018-03-08 09:47:23 -05006458bool ValidateFramebufferNotMultisampled(Context *context, Framebuffer *framebuffer)
6459{
Jamie Madill427064d2018-04-13 16:20:34 -04006460 if (framebuffer->getSamples(context) != 0)
Jamie Madille98b1b52018-03-08 09:47:23 -05006461 {
6462 context->handleError(InvalidOperation());
6463 return false;
6464 }
6465 return true;
6466}
6467
Lingfeng Yang038dd532018-03-29 17:31:52 -07006468bool ValidateMultitextureUnit(Context *context, GLenum texture)
6469{
6470 if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
6471 {
6472 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMultitextureUnit);
6473 return false;
6474 }
6475 return true;
6476}
6477
Jamie Madillc29968b2016-01-20 11:17:23 -05006478} // namespace gl