blob: 7a12983e119b4a632d00b2ab35c59eced991c857 [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"
Jamie Madill231c7f52017-04-26 13:45:37 -040022#include "libANGLE/formatutils.h"
jchen10a99ed552017-09-22 08:10:32 +080023#include "libANGLE/queryconversions.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040024#include "libANGLE/validationES2.h"
25#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040026
27#include "common/mathutil.h"
28#include "common/utilities.h"
29
Jamie Madille2e406c2016-06-02 13:04:10 -040030using namespace angle;
31
Geoff Lange8ebe7f2013-08-05 15:03:13 -040032namespace gl
33{
Jamie Madill1ca74672015-07-21 15:14:11 -040034namespace
35{
jchen10a99ed552017-09-22 08:10:32 +080036
Corentin Wallez92db6942016-12-09 13:10:36 -050037bool ValidateDrawAttribs(ValidationContext *context,
38 GLint primcount,
39 GLint maxVertex,
40 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040041{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070042 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040043 const gl::Program *program = state.getProgram();
44
Corentin Wallez327411e2016-12-09 11:09:17 -050045 bool webglCompatibility = context->getExtensions().webglCompatibility;
46
Jamie Madill231c7f52017-04-26 13:45:37 -040047 const VertexArray *vao = state.getVertexArray();
48 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080049 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madilld078c682018-01-02 11:50:24 -050050 for (size_t attributeIndex : vao->getEnabledAttributesMask())
Jamie Madill1ca74672015-07-21 15:14:11 -040051 {
52 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallez672f7f32017-06-15 17:42:17 -040053
54 // No need to range check for disabled attribs.
55 if (!attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040056 {
Corentin Wallezfd456442016-12-21 17:57:00 -050057 continue;
58 }
Jamie Madill1ca74672015-07-21 15:14:11 -040059
Jamie Madill231c7f52017-04-26 13:45:37 -040060 // If we have no buffer, then we either get an error, or there are no more checks to be
61 // done.
Corentin Wallez672f7f32017-06-15 17:42:17 -040062 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
63 gl::Buffer *buffer = binding.getBuffer().get();
Corentin Wallezfd456442016-12-21 17:57:00 -050064 if (!buffer)
65 {
Geoff Langfeb8c682017-02-13 16:07:35 -050066 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -050067 {
68 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050069 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
70 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
71 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
72 // error.
Brandon Jonesafa75152017-07-21 13:11:29 -070073 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
Corentin Wallezfd456442016-12-21 17:57:00 -050074 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050075 }
Corentin Wallezfd456442016-12-21 17:57:00 -050076 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040077 {
78 // This is an application error that would normally result in a crash,
79 // but we catch it and return an error
Brandon Jonesafa75152017-07-21 13:11:29 -070080 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
Jamie Madill1ca74672015-07-21 15:14:11 -040081 return false;
82 }
Corentin Wallezfd456442016-12-21 17:57:00 -050083 continue;
84 }
85
Corentin Wallez672f7f32017-06-15 17:42:17 -040086 // This needs to come after the check for client arrays as even unused attributes cannot use
87 // client-side arrays
88 if (!program->isAttribLocationActive(attributeIndex))
89 {
90 continue;
91 }
92
Corentin Wallezfd456442016-12-21 17:57:00 -050093 // If we're drawing zero vertices, we have enough data.
94 if (vertexCount <= 0 || primcount <= 0)
95 {
96 continue;
97 }
98
99 GLint maxVertexElement = 0;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300100 GLuint divisor = binding.getDivisor();
101 if (divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500102 {
103 maxVertexElement = maxVertex;
104 }
105 else
106 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300107 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500108 }
109
110 // We do manual overflow checks here instead of using safe_math.h because it was
111 // a bottleneck. Thanks to some properties of GL we know inequalities that can
112 // help us make the overflow checks faster.
113
114 // The max possible attribSize is 16 for a vector of 4 32 bit values.
115 constexpr uint64_t kMaxAttribSize = 16;
116 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
117 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
118
119 // We know attribStride is given as a GLsizei which is typedefed to int.
120 // We also know an upper bound for attribSize.
121 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800122 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500123 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
124 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
125
126 // Computing the max offset using uint64_t without attrib.offset is overflow
127 // safe. Note: Last vertex element does not take the full stride!
128 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
129 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
130
131 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800132 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
133 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500134 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700135 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500136 return false;
137 }
138 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
139
140 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
141 // We can return INVALID_OPERATION if our vertex attribute does not have
142 // enough backing data.
143 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
144 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700145 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500146 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400147 }
148 }
149
150 return true;
151}
152
Geoff Lang280ba992017-04-18 16:30:58 -0400153bool ValidReadPixelsTypeEnum(ValidationContext *context, GLenum type)
154{
155 switch (type)
156 {
157 // Types referenced in Table 3.4 of the ES 2.0.25 spec
158 case GL_UNSIGNED_BYTE:
159 case GL_UNSIGNED_SHORT_4_4_4_4:
160 case GL_UNSIGNED_SHORT_5_5_5_1:
161 case GL_UNSIGNED_SHORT_5_6_5:
162 return context->getClientVersion() >= ES_2_0;
163
164 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
165 case GL_BYTE:
166 case GL_INT:
167 case GL_SHORT:
168 case GL_UNSIGNED_INT:
169 case GL_UNSIGNED_INT_10F_11F_11F_REV:
170 case GL_UNSIGNED_INT_24_8:
171 case GL_UNSIGNED_INT_2_10_10_10_REV:
172 case GL_UNSIGNED_INT_5_9_9_9_REV:
173 case GL_UNSIGNED_SHORT:
174 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
175 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
176 return context->getClientVersion() >= ES_3_0;
177
178 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400179 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
180 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400181
182 case GL_HALF_FLOAT:
183 return context->getClientVersion() >= ES_3_0 ||
184 context->getExtensions().textureHalfFloat;
185
186 case GL_HALF_FLOAT_OES:
187 return context->getExtensions().colorBufferHalfFloat;
188
189 default:
190 return false;
191 }
192}
193
194bool ValidReadPixelsFormatEnum(ValidationContext *context, GLenum format)
195{
196 switch (format)
197 {
198 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
199 case GL_RGBA:
200 case GL_RGB:
201 case GL_ALPHA:
202 return context->getClientVersion() >= ES_2_0;
203
204 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
205 case GL_RG:
206 case GL_RED:
207 case GL_RGBA_INTEGER:
208 case GL_RGB_INTEGER:
209 case GL_RG_INTEGER:
210 case GL_RED_INTEGER:
211 return context->getClientVersion() >= ES_3_0;
212
213 case GL_SRGB_ALPHA_EXT:
214 case GL_SRGB_EXT:
215 return context->getExtensions().sRGB;
216
217 case GL_BGRA_EXT:
218 return context->getExtensions().readFormatBGRA;
219
220 default:
221 return false;
222 }
223}
224
Geoff Langf607c602016-09-21 11:46:48 -0400225bool ValidReadPixelsFormatType(ValidationContext *context,
226 GLenum framebufferComponentType,
227 GLenum format,
228 GLenum type)
229{
230 switch (framebufferComponentType)
231 {
232 case GL_UNSIGNED_NORMALIZED:
233 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
234 // ReadPixels with BGRA even if the extension is not present
235 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
236 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
237 type == GL_UNSIGNED_BYTE);
238
239 case GL_SIGNED_NORMALIZED:
240 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
241
242 case GL_INT:
243 return (format == GL_RGBA_INTEGER && type == GL_INT);
244
245 case GL_UNSIGNED_INT:
246 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
247
248 case GL_FLOAT:
249 return (format == GL_RGBA && type == GL_FLOAT);
250
251 default:
252 UNREACHABLE();
253 return false;
254 }
255}
256
Geoff Langc1984ed2016-10-07 12:41:00 -0400257template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400258bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400259{
260 switch (ConvertToGLenum(params[0]))
261 {
262 case GL_CLAMP_TO_EDGE:
263 break;
264
265 case GL_REPEAT:
266 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400267 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400268 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400269 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700270 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400271 return false;
272 }
273 break;
274
275 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700276 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400277 return false;
278 }
279
280 return true;
281}
282
283template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400284bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400285{
286 switch (ConvertToGLenum(params[0]))
287 {
288 case GL_NEAREST:
289 case GL_LINEAR:
290 break;
291
292 case GL_NEAREST_MIPMAP_NEAREST:
293 case GL_LINEAR_MIPMAP_NEAREST:
294 case GL_NEAREST_MIPMAP_LINEAR:
295 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400296 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400297 {
298 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700299 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400300 return false;
301 }
302 break;
303
304 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700305 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400306 return false;
307 }
308
309 return true;
310}
311
312template <typename ParamType>
313bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
314{
315 switch (ConvertToGLenum(params[0]))
316 {
317 case GL_NEAREST:
318 case GL_LINEAR:
319 break;
320
321 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700322 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400323 return false;
324 }
325
326 return true;
327}
328
329template <typename ParamType>
330bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
331{
332 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
333 switch (ConvertToGLenum(params[0]))
334 {
335 case GL_NONE:
336 case GL_COMPARE_REF_TO_TEXTURE:
337 break;
338
339 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700340 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400341 return false;
342 }
343
344 return true;
345}
346
347template <typename ParamType>
348bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
349{
350 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
351 switch (ConvertToGLenum(params[0]))
352 {
353 case GL_LEQUAL:
354 case GL_GEQUAL:
355 case GL_LESS:
356 case GL_GREATER:
357 case GL_EQUAL:
358 case GL_NOTEQUAL:
359 case GL_ALWAYS:
360 case GL_NEVER:
361 break;
362
363 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700364 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400365 return false;
366 }
367
368 return true;
369}
370
371template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700372bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
373{
374 if (!context->getExtensions().textureSRGBDecode)
375 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700376 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700377 return false;
378 }
379
380 switch (ConvertToGLenum(params[0]))
381 {
382 case GL_DECODE_EXT:
383 case GL_SKIP_DECODE_EXT:
384 break;
385
386 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700387 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700388 return false;
389 }
390
391 return true;
392}
393
Geoff Lange0cff192017-05-30 13:04:56 -0400394bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
395{
396 const Program *program = context->getGLState().getProgram();
397 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
398
Brandon Jonesc405ae72017-12-06 14:15:03 -0800399 if (!ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
400 framebuffer->getDrawBufferTypeMask().to_ulong(),
401 program->getActiveOutputVariables().to_ulong(),
402 framebuffer->getDrawBufferMask().to_ulong()))
Geoff Lange0cff192017-05-30 13:04:56 -0400403 {
Brandon Jones76746f92017-11-22 11:44:41 -0800404 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
405 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400406 }
407
408 return true;
409}
410
Geoff Lang9ab5b822017-05-30 16:19:23 -0400411bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
412{
Jamie Madillcac94a92017-11-10 10:09:32 -0500413 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400414 const Program *program = context->getGLState().getProgram();
415 const VertexArray *vao = context->getGLState().getVertexArray();
416
Brandon Jonesc405ae72017-12-06 14:15:03 -0800417 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
418 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
419 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
420
421 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
422 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
423 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
424
425 if (!ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
426 program->getAttributesMask().to_ulong(), 0xFFFF))
Geoff Lang9ab5b822017-05-30 16:19:23 -0400427 {
Brandon Jonesc405ae72017-12-06 14:15:03 -0800428 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexShaderTypeMismatch);
429 return false;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400430 }
Geoff Lang9ab5b822017-05-30 16:19:23 -0400431 return true;
432}
433
Geoff Langf41a7152016-09-19 15:11:17 -0400434} // anonymous namespace
435
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500436bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400437{
Jamie Madilld7460c72014-01-21 16:38:14 -0500438 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400439 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800440 case GL_TEXTURE_2D:
441 case GL_TEXTURE_CUBE_MAP:
442 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400443
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400444 case GL_TEXTURE_RECTANGLE_ANGLE:
445 return context->getExtensions().textureRectangle;
446
He Yunchaoced53ae2016-11-29 15:00:51 +0800447 case GL_TEXTURE_3D:
448 case GL_TEXTURE_2D_ARRAY:
449 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500450
He Yunchaoced53ae2016-11-29 15:00:51 +0800451 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800452 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400453
He Yunchaoced53ae2016-11-29 15:00:51 +0800454 default:
455 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500456 }
Jamie Madill35d15012013-10-07 10:46:37 -0400457}
458
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500459bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
460{
461 switch (target)
462 {
463 case GL_TEXTURE_2D:
464 case GL_TEXTURE_CUBE_MAP:
465 return true;
466
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400467 case GL_TEXTURE_RECTANGLE_ANGLE:
468 return context->getExtensions().textureRectangle;
469
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500470 default:
471 return false;
472 }
473}
474
475bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
476{
477 switch (target)
478 {
479 case GL_TEXTURE_3D:
480 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300481 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500482
483 default:
484 return false;
485 }
486}
487
Ian Ewellbda75592016-04-18 17:25:54 -0400488// Most texture GL calls are not compatible with external textures, so we have a separate validation
489// function for use in the GL calls that do
490bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
491{
492 return (target == GL_TEXTURE_EXTERNAL_OES) &&
493 (context->getExtensions().eglImageExternal ||
494 context->getExtensions().eglStreamConsumerExternal);
495}
496
Shannon Woods4dfed832014-03-17 20:03:39 -0400497// This function differs from ValidTextureTarget in that the target must be
498// usable as the destination of a 2D operation-- so a cube face is valid, but
499// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400500// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500501bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400502{
503 switch (target)
504 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800505 case GL_TEXTURE_2D:
506 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
507 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
508 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
509 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
510 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
511 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
512 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400513 case GL_TEXTURE_RECTANGLE_ANGLE:
514 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800515 default:
516 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500517 }
518}
519
Jamie Madillbe849e42017-05-02 15:49:00 -0400520bool ValidateDrawElementsInstancedBase(ValidationContext *context,
521 GLenum mode,
522 GLsizei count,
523 GLenum type,
524 const GLvoid *indices,
525 GLsizei primcount)
526{
527 if (primcount < 0)
528 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700529 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400530 return false;
531 }
532
533 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
534 {
535 return false;
536 }
537
538 // No-op zero primitive count
539 return (primcount > 0);
540}
541
542bool ValidateDrawArraysInstancedBase(Context *context,
543 GLenum mode,
544 GLint first,
545 GLsizei count,
546 GLsizei primcount)
547{
548 if (primcount < 0)
549 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700550 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400551 return false;
552 }
553
554 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
555 {
556 return false;
557 }
558
559 // No-op if zero primitive count
560 return (primcount > 0);
561}
562
Corentin Wallez0dc97812017-06-22 14:38:44 -0400563bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400564{
565 // Verify there is at least one active attribute with a divisor of zero
566 const State &state = context->getGLState();
567
568 Program *program = state.getProgram();
569
570 const auto &attribs = state.getVertexArray()->getVertexAttributes();
571 const auto &bindings = state.getVertexArray()->getVertexBindings();
572 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
573 {
574 const VertexAttribute &attrib = attribs[attributeIndex];
575 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300576 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400577 {
578 return true;
579 }
580 }
581
Brandon Jonesafa75152017-07-21 13:11:29 -0700582 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400583 return false;
584}
585
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500586bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
587{
588 switch (target)
589 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800590 case GL_TEXTURE_3D:
591 case GL_TEXTURE_2D_ARRAY:
592 return true;
593 default:
594 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400595 }
596}
597
He Yunchao11b038b2016-11-22 21:24:04 +0800598bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
599{
600 switch (target)
601 {
602 case GL_TEXTURE_2D:
603 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
604 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
605 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
606 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
607 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
608 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
609 case GL_TEXTURE_3D:
610 case GL_TEXTURE_2D_ARRAY:
611 case GL_TEXTURE_2D_MULTISAMPLE:
612 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400613 case GL_TEXTURE_RECTANGLE_ANGLE:
614 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800615 default:
616 return false;
617 }
618}
619
Geoff Lange8afa902017-09-27 15:00:43 -0400620bool ValidFramebufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500621{
He Yunchaoced53ae2016-11-29 15:00:51 +0800622 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
623 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400624 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500625
626 switch (target)
627 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800628 case GL_FRAMEBUFFER:
629 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400630
He Yunchaoced53ae2016-11-29 15:00:51 +0800631 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800632 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400633 return (context->getExtensions().framebufferBlit ||
634 context->getClientMajorVersion() >= 3);
635
He Yunchaoced53ae2016-11-29 15:00:51 +0800636 default:
637 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500638 }
639}
640
Jamie Madillc29968b2016-01-20 11:17:23 -0500641bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400642{
Jamie Madillc29968b2016-01-20 11:17:23 -0500643 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400644 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -0400645 switch (target)
646 {
Jamie Madillc29968b2016-01-20 11:17:23 -0500647 case GL_TEXTURE_2D:
648 maxDimension = caps.max2DTextureSize;
649 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800650 case GL_TEXTURE_CUBE_MAP:
651 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
652 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
653 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
654 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
655 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
656 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
657 maxDimension = caps.maxCubeMapTextureSize;
658 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400659 case GL_TEXTURE_RECTANGLE_ANGLE:
660 return level == 0;
He Yunchaoced53ae2016-11-29 15:00:51 +0800661 case GL_TEXTURE_3D:
662 maxDimension = caps.max3DTextureSize;
663 break;
664 case GL_TEXTURE_2D_ARRAY:
665 maxDimension = caps.max2DTextureSize;
666 break;
He Yunchao11b038b2016-11-22 21:24:04 +0800667 case GL_TEXTURE_2D_MULTISAMPLE:
668 maxDimension = caps.max2DTextureSize;
669 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800670 default:
671 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400672 }
673
Brandon Jones6cad5662017-06-14 13:25:13 -0700674 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400675}
676
Brandon Jones6cad5662017-06-14 13:25:13 -0700677bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -0700678 GLenum target,
679 GLint level,
680 GLsizei width,
681 GLsizei height,
682 GLsizei depth,
683 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400684{
Brandon Jones6cad5662017-06-14 13:25:13 -0700685 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400686 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700687 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400688 return false;
689 }
Austin Kinross08528e12015-10-07 16:24:40 -0700690 // TexSubImage parameters can be NPOT without textureNPOT extension,
691 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500692 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500693 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500694 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400695 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400696 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700697 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400698 return false;
699 }
700
701 if (!ValidMipLevel(context, target, level))
702 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700703 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400704 return false;
705 }
706
707 return true;
708}
709
Geoff Lang0d8b7242015-09-09 14:56:53 -0400710bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
711{
712 // List of compressed format that require that the texture size is smaller than or a multiple of
713 // the compressed block size.
714 switch (internalFormat)
715 {
716 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
717 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
718 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
719 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langfff7a7d2017-06-02 10:39:17 -0400720 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
721 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
722 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
723 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
Minmin Gonge3939b92015-12-01 15:36:51 -0800724 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800725 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
726 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
727 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
728 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
729 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
730 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -0400731 return true;
732
733 default:
734 return false;
735 }
736}
737
Geoff Lang966c9402017-04-18 12:38:27 -0400738bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
739{
740 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
741 (size % blockSize == 0);
742}
743
Jamie Madillc29968b2016-01-20 11:17:23 -0500744bool ValidCompressedImageSize(const ValidationContext *context,
745 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400746 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500747 GLsizei width,
748 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400749{
Geoff Langca271392017-04-05 12:30:00 -0400750 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400751 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400752 {
753 return false;
754 }
755
Geoff Lang966c9402017-04-18 12:38:27 -0400756 if (width < 0 || height < 0)
757 {
758 return false;
759 }
760
761 if (CompressedTextureFormatRequiresExactSize(internalFormat))
762 {
763 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
764 // block size for level 0 but WebGL disallows this.
765 bool smallerThanBlockSizeAllowed =
766 level > 0 || !context->getExtensions().webglCompatibility;
767
768 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
769 smallerThanBlockSizeAllowed) ||
770 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
771 smallerThanBlockSizeAllowed))
772 {
773 return false;
774 }
775 }
776
777 return true;
778}
779
780bool ValidCompressedSubImageSize(const ValidationContext *context,
781 GLenum internalFormat,
782 GLint xoffset,
783 GLint yoffset,
784 GLsizei width,
785 GLsizei height,
786 size_t textureWidth,
787 size_t textureHeight)
788{
789 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
790 if (!formatInfo.compressed)
791 {
792 return false;
793 }
794
Geoff Lang44ff5a72017-02-03 15:15:43 -0500795 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400796 {
797 return false;
798 }
799
Geoff Lang0d8b7242015-09-09 14:56:53 -0400800 if (CompressedTextureFormatRequiresExactSize(internalFormat))
801 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500802 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400803 yoffset % formatInfo.compressedBlockHeight != 0)
804 {
805 return false;
806 }
807
808 // Allowed to either have data that is a multiple of block size or is smaller than the block
809 // size but fills the entire mip
810 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
811 static_cast<size_t>(width) == textureWidth &&
812 static_cast<size_t>(height) == textureHeight;
813 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
814 (height % formatInfo.compressedBlockHeight) == 0;
815 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400816 {
817 return false;
818 }
819 }
820
Geoff Langd4f180b2013-09-24 13:57:44 -0400821 return true;
822}
823
Geoff Langff5b2d52016-09-07 11:32:23 -0400824bool ValidImageDataSize(ValidationContext *context,
825 GLenum textureTarget,
826 GLsizei width,
827 GLsizei height,
828 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400829 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400830 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400831 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400832 GLsizei imageSize)
833{
Corentin Wallez336129f2017-10-17 15:55:40 -0400834 gl::Buffer *pixelUnpackBuffer =
835 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400836 if (pixelUnpackBuffer == nullptr && imageSize < 0)
837 {
838 // Checks are not required
839 return true;
840 }
841
842 // ...the data would be unpacked from the buffer object such that the memory reads required
843 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400844 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
845 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400846 const gl::Extents size(width, height, depth);
847 const auto &unpack = context->getGLState().getUnpackState();
848
849 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
850 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
851 if (endByteOrErr.isError())
852 {
853 context->handleError(endByteOrErr.getError());
854 return false;
855 }
856
857 GLuint endByte = endByteOrErr.getResult();
858
859 if (pixelUnpackBuffer)
860 {
861 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
862 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
863 checkedEndByte += checkedOffset;
864
865 if (!checkedEndByte.IsValid() ||
866 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
867 {
868 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500869 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -0400870 return false;
871 }
872 }
873 else
874 {
875 ASSERT(imageSize >= 0);
876 if (pixels == nullptr && imageSize != 0)
877 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500878 context->handleError(InvalidOperation()
879 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400880 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400881 }
882
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400883 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400884 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500885 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400886 return false;
887 }
888 }
889
890 return true;
891}
892
Geoff Lang37dde692014-01-31 16:34:54 -0500893bool ValidQueryType(const Context *context, GLenum queryType)
894{
He Yunchaoced53ae2016-11-29 15:00:51 +0800895 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
896 "GL extension enums not equal.");
897 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
898 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -0500899
900 switch (queryType)
901 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800902 case GL_ANY_SAMPLES_PASSED:
903 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400904 return context->getClientMajorVersion() >= 3 ||
905 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +0800906 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
907 return (context->getClientMajorVersion() >= 3);
908 case GL_TIME_ELAPSED_EXT:
909 return context->getExtensions().disjointTimerQuery;
910 case GL_COMMANDS_COMPLETED_CHROMIUM:
911 return context->getExtensions().syncQuery;
912 default:
913 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500914 }
915}
916
Geoff Lang2d62ab72017-03-23 16:54:40 -0400917bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
918 GLenum type,
919 GLboolean normalized,
920 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400921 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400922 bool pureInteger)
923{
924 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400925 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
926 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
927 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
928 // parameter exceeds 255.
929 constexpr GLsizei kMaxWebGLStride = 255;
930 if (stride > kMaxWebGLStride)
931 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500932 context->handleError(InvalidValue()
933 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -0400934 return false;
935 }
936
937 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
938 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
939 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
940 // or an INVALID_OPERATION error is generated.
941 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
942 size_t typeSize = GetVertexFormatTypeSize(internalType);
943
944 ASSERT(isPow2(typeSize) && typeSize > 0);
945 size_t sizeMask = (typeSize - 1);
946 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
947 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700948 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400949 return false;
950 }
951
952 if ((stride & sizeMask) != 0)
953 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700954 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400955 return false;
956 }
957
958 return true;
959}
960
Jamie Madillef300b12016-10-07 15:12:09 -0400961Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -0500962{
He Yunchaoced53ae2016-11-29 15:00:51 +0800963 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
964 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
965 // or program object and INVALID_OPERATION if the provided name identifies an object
966 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -0500967
Dian Xiang769769a2015-09-09 15:20:08 -0700968 Program *validProgram = context->getProgram(id);
969
970 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -0500971 {
Dian Xiang769769a2015-09-09 15:20:08 -0700972 if (context->getShader(id))
973 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700974 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -0700975 }
976 else
977 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700978 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -0700979 }
Geoff Lang48dcae72014-02-05 16:28:24 -0500980 }
Dian Xiang769769a2015-09-09 15:20:08 -0700981
982 return validProgram;
983}
984
Jamie Madillef300b12016-10-07 15:12:09 -0400985Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -0700986{
987 // See ValidProgram for spec details.
988
989 Shader *validShader = context->getShader(id);
990
991 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -0500992 {
Dian Xiang769769a2015-09-09 15:20:08 -0700993 if (context->getProgram(id))
994 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700995 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -0700996 }
997 else
998 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700999 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001000 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001001 }
Dian Xiang769769a2015-09-09 15:20:08 -07001002
1003 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001004}
1005
Geoff Langb1196682014-07-23 13:47:29 -04001006bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001007{
Geoff Langfa125c92017-10-24 13:01:46 -04001008 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001009 {
Geoff Langfa125c92017-10-24 13:01:46 -04001010 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1011 {
1012 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1013 return false;
1014 }
Jamie Madillb4472272014-07-03 10:38:55 -04001015
Geoff Langfa125c92017-10-24 13:01:46 -04001016 // Color attachment 0 is validated below because it is always valid
1017 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001018 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001019 {
Geoff Langfa125c92017-10-24 13:01:46 -04001020 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001021 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001022 }
1023 }
1024 else
1025 {
1026 switch (attachment)
1027 {
Geoff Langfa125c92017-10-24 13:01:46 -04001028 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001029 case GL_DEPTH_ATTACHMENT:
1030 case GL_STENCIL_ATTACHMENT:
1031 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001032
He Yunchaoced53ae2016-11-29 15:00:51 +08001033 case GL_DEPTH_STENCIL_ATTACHMENT:
1034 if (!context->getExtensions().webglCompatibility &&
1035 context->getClientMajorVersion() < 3)
1036 {
Geoff Langfa125c92017-10-24 13:01:46 -04001037 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001038 return false;
1039 }
1040 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001041
He Yunchaoced53ae2016-11-29 15:00:51 +08001042 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001043 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001044 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001045 }
1046 }
1047
1048 return true;
1049}
1050
Jamie Madille8fb6402017-02-14 17:56:40 -05001051bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001052 GLenum target,
1053 GLsizei samples,
1054 GLenum internalformat,
1055 GLsizei width,
1056 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001057{
1058 switch (target)
1059 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001060 case GL_RENDERBUFFER:
1061 break;
1062 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001063 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001064 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001065 }
1066
1067 if (width < 0 || height < 0 || samples < 0)
1068 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001069 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001070 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001071 }
1072
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001073 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1074 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1075
1076 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001077 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001078 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001079 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001080 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001081 }
1082
1083 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1084 // 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 -08001085 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001086 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1087 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001088 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001089 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001090 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001091 }
1092
Geoff Langaae65a42014-05-26 12:43:44 -04001093 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001094 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001095 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001096 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001097 }
1098
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001099 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001100 if (handle == 0)
1101 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001102 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001103 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001104 }
1105
1106 return true;
1107}
1108
He Yunchaoced53ae2016-11-29 15:00:51 +08001109bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1110 GLenum target,
1111 GLenum attachment,
1112 GLenum renderbuffertarget,
1113 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001114{
Geoff Lange8afa902017-09-27 15:00:43 -04001115 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001116 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001117 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001118 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001119 }
1120
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001121 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001122
Jamie Madill84115c92015-04-23 15:00:07 -04001123 ASSERT(framebuffer);
1124 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001125 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001126 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001127 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001128 }
1129
Jamie Madillb4472272014-07-03 10:38:55 -04001130 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001131 {
Jamie Madillb4472272014-07-03 10:38:55 -04001132 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001133 }
1134
Jamie Madillab9d82c2014-01-21 16:38:14 -05001135 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1136 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1137 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1138 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1139 if (renderbuffer != 0)
1140 {
1141 if (!context->getRenderbuffer(renderbuffer))
1142 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001143 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001144 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001145 }
1146 }
1147
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001148 return true;
1149}
1150
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001151bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001152 GLint srcX0,
1153 GLint srcY0,
1154 GLint srcX1,
1155 GLint srcY1,
1156 GLint dstX0,
1157 GLint dstY0,
1158 GLint dstX1,
1159 GLint dstY1,
1160 GLbitfield mask,
1161 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001162{
1163 switch (filter)
1164 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001165 case GL_NEAREST:
1166 break;
1167 case GL_LINEAR:
1168 break;
1169 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001170 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001171 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001172 }
1173
1174 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001176 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001177 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001178 }
1179
1180 if (mask == 0)
1181 {
1182 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1183 // buffers are copied.
1184 return false;
1185 }
1186
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001187 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1188 // color buffer, leaving only nearest being unfiltered from above
1189 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1190 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001191 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001192 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001193 }
1194
Jamie Madill51f40ec2016-06-15 14:06:00 -04001195 const auto &glState = context->getGLState();
1196 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1197 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001198
1199 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001200 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001201 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001202 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001203 }
1204
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001205 if (readFramebuffer->id() == drawFramebuffer->id())
1206 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001207 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001208 return false;
1209 }
1210
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001211 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001212 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001213 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001214 return false;
1215 }
1216
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001217 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001218 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001219 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001220 return false;
1221 }
1222
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001223 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001224 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001225 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001226 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001227 }
1228
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001229 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1230
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001231 if (mask & GL_COLOR_BUFFER_BIT)
1232 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001233 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001234 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001235
He Yunchao66a41a22016-12-15 16:45:05 +08001236 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001237 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001238 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001239
Geoff Langa15472a2015-08-11 11:48:03 -04001240 for (size_t drawbufferIdx = 0;
1241 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001242 {
Geoff Langa15472a2015-08-11 11:48:03 -04001243 const FramebufferAttachment *attachment =
1244 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1245 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001246 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001247 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001248
Geoff Langb2f3d052013-08-13 12:49:27 -04001249 // The GL ES 3.0.2 spec (pg 193) states that:
1250 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001251 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1252 // as well
1253 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1254 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001255 // Changes with EXT_color_buffer_float:
1256 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001257 GLenum readComponentType = readFormat.info->componentType;
1258 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001259 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001260 readComponentType == GL_SIGNED_NORMALIZED);
1261 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1262 drawComponentType == GL_SIGNED_NORMALIZED);
1263
1264 if (extensions.colorBufferFloat)
1265 {
1266 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1267 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1268
1269 if (readFixedOrFloat != drawFixedOrFloat)
1270 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001271 context->handleError(InvalidOperation()
1272 << "If the read buffer contains fixed-point or "
1273 "floating-point values, the draw buffer must "
1274 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001275 return false;
1276 }
1277 }
1278 else if (readFixedPoint != drawFixedPoint)
1279 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001280 context->handleError(InvalidOperation()
1281 << "If the read buffer contains fixed-point values, "
1282 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001283 return false;
1284 }
1285
1286 if (readComponentType == GL_UNSIGNED_INT &&
1287 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001288 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001289 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001290 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001291 }
1292
Jamie Madill6163c752015-12-07 16:32:59 -05001293 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001294 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001295 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001296 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001297 }
1298
Jamie Madilla3944d42016-07-22 22:13:26 -04001299 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001300 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001301 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001302 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001303 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001304 }
Geoff Lange4915782017-04-12 15:19:07 -04001305
1306 if (context->getExtensions().webglCompatibility &&
1307 *readColorBuffer == *attachment)
1308 {
1309 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001310 InvalidOperation()
1311 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001312 return false;
1313 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001314 }
1315 }
1316
Jamie Madilla3944d42016-07-22 22:13:26 -04001317 if ((readFormat.info->componentType == GL_INT ||
1318 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1319 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001320 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001321 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001322 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001323 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001324 }
He Yunchao66a41a22016-12-15 16:45:05 +08001325 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1326 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1327 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1328 // situation is an application error that would lead to a crash in ANGLE.
1329 else if (drawFramebuffer->hasEnabledDrawBuffer())
1330 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001331 context->handleError(
1332 InvalidOperation()
1333 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001334 return false;
1335 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001336 }
1337
He Yunchaoced53ae2016-11-29 15:00:51 +08001338 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001339 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1340 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001341 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001342 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001343 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001344 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001345 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001346 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001347 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001348
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001349 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001350 {
Kenneth Russell69382852017-07-21 16:38:44 -04001351 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001352 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001353 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001354 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001355 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001356
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001357 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001358 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001359 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001360 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001361 }
Geoff Lange4915782017-04-12 15:19:07 -04001362
1363 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1364 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001365 context->handleError(
1366 InvalidOperation()
1367 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001368 return false;
1369 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001370 }
He Yunchao66a41a22016-12-15 16:45:05 +08001371 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1372 else if (drawBuffer)
1373 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001374 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1375 "depth/stencil attachment of a "
1376 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001377 return false;
1378 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001379 }
1380 }
1381
Martin Radeva3ed4572017-07-27 18:29:37 +03001382 // ANGLE_multiview, Revision 1:
1383 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1384 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1385 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1386 {
1387 context->handleError(InvalidFramebufferOperation()
1388 << "Attempt to read from a multi-view framebuffer.");
1389 return false;
1390 }
1391 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1392 {
1393 context->handleError(InvalidFramebufferOperation()
1394 << "Attempt to write to a multi-view framebuffer.");
1395 return false;
1396 }
1397
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001398 return true;
1399}
1400
Jamie Madill4928b7c2017-06-20 12:57:39 -04001401bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001402 GLint x,
1403 GLint y,
1404 GLsizei width,
1405 GLsizei height,
1406 GLenum format,
1407 GLenum type,
1408 GLsizei bufSize,
1409 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001410 GLsizei *columns,
1411 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001412 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001413{
1414 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001415 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001416 return false;
1417 }
1418
Geoff Lang62fce5b2016-09-30 10:46:35 -04001419 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001420 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001421 {
Geoff Langb1196682014-07-23 13:47:29 -04001422 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001423 }
1424
Geoff Lang62fce5b2016-09-30 10:46:35 -04001425 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001426 {
Geoff Langb1196682014-07-23 13:47:29 -04001427 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001428 }
1429
Jamie Madillc29968b2016-01-20 11:17:23 -05001430 return true;
1431}
1432
1433bool ValidateReadnPixelsEXT(Context *context,
1434 GLint x,
1435 GLint y,
1436 GLsizei width,
1437 GLsizei height,
1438 GLenum format,
1439 GLenum type,
1440 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001441 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001442{
1443 if (bufSize < 0)
1444 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001445 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001446 return false;
1447 }
1448
Geoff Lang62fce5b2016-09-30 10:46:35 -04001449 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001450 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001451}
Jamie Madill26e91952014-03-05 15:01:27 -05001452
Jamie Madill4928b7c2017-06-20 12:57:39 -04001453bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001454 GLint x,
1455 GLint y,
1456 GLsizei width,
1457 GLsizei height,
1458 GLenum format,
1459 GLenum type,
1460 GLsizei bufSize,
1461 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001462 GLsizei *columns,
1463 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001464 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001465{
1466 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001467 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001468 return false;
1469 }
1470
Geoff Lange93daba2017-03-30 13:54:40 -04001471 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1472 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001473 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001474 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001475 }
1476
Geoff Lang62fce5b2016-09-30 10:46:35 -04001477 if (!ValidateRobustBufferSize(context, bufSize, *length))
1478 {
1479 return false;
1480 }
1481
1482 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001483}
1484
Jamie Madillf0e04492017-08-26 15:28:42 -04001485bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001486{
1487 if (!context->getExtensions().occlusionQueryBoolean &&
1488 !context->getExtensions().disjointTimerQuery)
1489 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001490 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001491 return false;
1492 }
1493
Olli Etuaho41997e72016-03-10 13:38:39 +02001494 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001495}
1496
Jamie Madillf0e04492017-08-26 15:28:42 -04001497bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001498{
1499 if (!context->getExtensions().occlusionQueryBoolean &&
1500 !context->getExtensions().disjointTimerQuery)
1501 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001502 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001503 return false;
1504 }
1505
Olli Etuaho41997e72016-03-10 13:38:39 +02001506 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001507}
1508
Jamie Madillf0e04492017-08-26 15:28:42 -04001509bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1510{
1511 if (!context->getExtensions().occlusionQueryBoolean &&
1512 !context->getExtensions().disjointTimerQuery)
1513 {
1514 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1515 return false;
1516 }
1517
1518 return true;
1519}
1520
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001521bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001522{
1523 if (!ValidQueryType(context, target))
1524 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001525 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001526 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001527 }
1528
1529 if (id == 0)
1530 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001531 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001532 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001533 }
1534
1535 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1536 // of zero, if the active query object name for <target> is non-zero (for the
1537 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1538 // the active query for either target is non-zero), if <id> is the name of an
1539 // existing query object whose type does not match <target>, or if <id> is the
1540 // active query object name for any query type, the error INVALID_OPERATION is
1541 // generated.
1542
1543 // Ensure no other queries are active
1544 // NOTE: If other queries than occlusion are supported, we will need to check
1545 // separately that:
1546 // a) The query ID passed is not the current active query for any target/type
1547 // b) There are no active queries for the requested target (and in the case
1548 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1549 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001550
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001551 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001552 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001553 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001554 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001555 }
1556
1557 Query *queryObject = context->getQuery(id, true, target);
1558
1559 // check that name was obtained with glGenQueries
1560 if (!queryObject)
1561 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001562 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001563 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001564 }
1565
1566 // check for type mismatch
1567 if (queryObject->getType() != target)
1568 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001569 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001570 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001571 }
1572
1573 return true;
1574}
1575
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001576bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1577{
1578 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001579 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001580 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001581 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001582 return false;
1583 }
1584
1585 return ValidateBeginQueryBase(context, target, id);
1586}
1587
1588bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001589{
1590 if (!ValidQueryType(context, target))
1591 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001592 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001593 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001594 }
1595
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001596 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001597
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001598 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001599 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001600 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001601 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001602 }
1603
Jamie Madill45c785d2014-05-13 14:09:34 -04001604 return true;
1605}
1606
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001607bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1608{
1609 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001610 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001611 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001612 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001613 return false;
1614 }
1615
1616 return ValidateEndQueryBase(context, target);
1617}
1618
1619bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1620{
1621 if (!context->getExtensions().disjointTimerQuery)
1622 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001623 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001624 return false;
1625 }
1626
1627 if (target != GL_TIMESTAMP_EXT)
1628 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001629 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001630 return false;
1631 }
1632
1633 Query *queryObject = context->getQuery(id, true, target);
1634 if (queryObject == nullptr)
1635 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001636 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001637 return false;
1638 }
1639
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001640 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001641 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001642 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001643 return false;
1644 }
1645
1646 return true;
1647}
1648
Geoff Lang2186c382016-10-14 10:54:54 -04001649bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001650{
Geoff Lang2186c382016-10-14 10:54:54 -04001651 if (numParams)
1652 {
1653 *numParams = 0;
1654 }
1655
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001656 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1657 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001658 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001659 return false;
1660 }
1661
1662 switch (pname)
1663 {
1664 case GL_CURRENT_QUERY_EXT:
1665 if (target == GL_TIMESTAMP_EXT)
1666 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001667 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001668 return false;
1669 }
1670 break;
1671 case GL_QUERY_COUNTER_BITS_EXT:
1672 if (!context->getExtensions().disjointTimerQuery ||
1673 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1674 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001675 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001676 return false;
1677 }
1678 break;
1679 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001680 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001681 return false;
1682 }
1683
Geoff Lang2186c382016-10-14 10:54:54 -04001684 if (numParams)
1685 {
1686 // All queries return only one value
1687 *numParams = 1;
1688 }
1689
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001690 return true;
1691}
1692
1693bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1694{
1695 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001696 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001697 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001698 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001699 return false;
1700 }
1701
Geoff Lang2186c382016-10-14 10:54:54 -04001702 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001703}
1704
Geoff Lang2186c382016-10-14 10:54:54 -04001705bool ValidateGetQueryivRobustANGLE(Context *context,
1706 GLenum target,
1707 GLenum pname,
1708 GLsizei bufSize,
1709 GLsizei *length,
1710 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001711{
Geoff Lang2186c382016-10-14 10:54:54 -04001712 if (!ValidateRobustEntryPoint(context, bufSize))
1713 {
1714 return false;
1715 }
1716
1717 if (!ValidateGetQueryivBase(context, target, pname, length))
1718 {
1719 return false;
1720 }
1721
1722 if (!ValidateRobustBufferSize(context, bufSize, *length))
1723 {
1724 return false;
1725 }
1726
1727 return true;
1728}
1729
1730bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1731{
1732 if (numParams)
1733 {
1734 *numParams = 0;
1735 }
1736
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001737 Query *queryObject = context->getQuery(id, false, GL_NONE);
1738
1739 if (!queryObject)
1740 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001741 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001742 return false;
1743 }
1744
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001745 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001746 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001747 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001748 return false;
1749 }
1750
1751 switch (pname)
1752 {
1753 case GL_QUERY_RESULT_EXT:
1754 case GL_QUERY_RESULT_AVAILABLE_EXT:
1755 break;
1756
1757 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001758 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001759 return false;
1760 }
1761
Geoff Lang2186c382016-10-14 10:54:54 -04001762 if (numParams)
1763 {
1764 *numParams = 1;
1765 }
1766
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001767 return true;
1768}
1769
1770bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1771{
1772 if (!context->getExtensions().disjointTimerQuery)
1773 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001774 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001775 return false;
1776 }
Geoff Lang2186c382016-10-14 10:54:54 -04001777 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1778}
1779
1780bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1781 GLuint id,
1782 GLenum pname,
1783 GLsizei bufSize,
1784 GLsizei *length,
1785 GLint *params)
1786{
1787 if (!context->getExtensions().disjointTimerQuery)
1788 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001789 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001790 return false;
1791 }
1792
1793 if (!ValidateRobustEntryPoint(context, bufSize))
1794 {
1795 return false;
1796 }
1797
1798 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1799 {
1800 return false;
1801 }
1802
1803 if (!ValidateRobustBufferSize(context, bufSize, *length))
1804 {
1805 return false;
1806 }
1807
1808 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001809}
1810
1811bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1812{
1813 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001814 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001815 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001816 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001817 return false;
1818 }
Geoff Lang2186c382016-10-14 10:54:54 -04001819 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1820}
1821
1822bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1823 GLuint id,
1824 GLenum pname,
1825 GLsizei bufSize,
1826 GLsizei *length,
1827 GLuint *params)
1828{
1829 if (!context->getExtensions().disjointTimerQuery &&
1830 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1831 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001832 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001833 return false;
1834 }
1835
1836 if (!ValidateRobustEntryPoint(context, bufSize))
1837 {
1838 return false;
1839 }
1840
1841 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1842 {
1843 return false;
1844 }
1845
1846 if (!ValidateRobustBufferSize(context, bufSize, *length))
1847 {
1848 return false;
1849 }
1850
1851 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001852}
1853
1854bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1855{
1856 if (!context->getExtensions().disjointTimerQuery)
1857 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001858 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001859 return false;
1860 }
Geoff Lang2186c382016-10-14 10:54:54 -04001861 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1862}
1863
1864bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1865 GLuint id,
1866 GLenum pname,
1867 GLsizei bufSize,
1868 GLsizei *length,
1869 GLint64 *params)
1870{
1871 if (!context->getExtensions().disjointTimerQuery)
1872 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001873 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001874 return false;
1875 }
1876
1877 if (!ValidateRobustEntryPoint(context, bufSize))
1878 {
1879 return false;
1880 }
1881
1882 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1883 {
1884 return false;
1885 }
1886
1887 if (!ValidateRobustBufferSize(context, bufSize, *length))
1888 {
1889 return false;
1890 }
1891
1892 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001893}
1894
1895bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1896{
1897 if (!context->getExtensions().disjointTimerQuery)
1898 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001899 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001900 return false;
1901 }
Geoff Lang2186c382016-10-14 10:54:54 -04001902 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1903}
1904
1905bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1906 GLuint id,
1907 GLenum pname,
1908 GLsizei bufSize,
1909 GLsizei *length,
1910 GLuint64 *params)
1911{
1912 if (!context->getExtensions().disjointTimerQuery)
1913 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001914 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001915 return false;
1916 }
1917
1918 if (!ValidateRobustEntryPoint(context, bufSize))
1919 {
1920 return false;
1921 }
1922
1923 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1924 {
1925 return false;
1926 }
1927
1928 if (!ValidateRobustBufferSize(context, bufSize, *length))
1929 {
1930 return false;
1931 }
1932
1933 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001934}
1935
Jiajia Qin5451d532017-11-16 17:16:34 +08001936bool ValidateUniformCommonBase(ValidationContext *context,
1937 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05001938 GLint location,
1939 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08001940 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05001941{
Jiajia Qin5451d532017-11-16 17:16:34 +08001942 // TODO(Jiajia): Add image uniform check in future.
1943 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05001944 {
Jiajia Qin5451d532017-11-16 17:16:34 +08001945 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05001946 return false;
1947 }
1948
Jiajia Qin5451d532017-11-16 17:16:34 +08001949 if (!program)
1950 {
1951 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
1952 return false;
1953 }
1954
1955 if (!program->isLinked())
1956 {
1957 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
1958 return false;
1959 }
1960
1961 if (location == -1)
1962 {
1963 // Silently ignore the uniform command
1964 return false;
1965 }
1966
1967 const auto &uniformLocations = program->getUniformLocations();
1968 size_t castedLocation = static_cast<size_t>(location);
1969 if (castedLocation >= uniformLocations.size())
1970 {
1971 context->handleError(InvalidOperation() << "Invalid uniform location");
1972 return false;
1973 }
1974
1975 const auto &uniformLocation = uniformLocations[castedLocation];
1976 if (uniformLocation.ignored)
1977 {
1978 // Silently ignore the uniform command
1979 return false;
1980 }
1981
1982 if (!uniformLocation.used())
1983 {
1984 context->handleError(InvalidOperation());
1985 return false;
1986 }
1987
1988 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
1989
1990 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
1991 if (!uniform.isArray() && count > 1)
1992 {
1993 context->handleError(InvalidOperation());
1994 return false;
1995 }
1996
1997 *uniformOut = &uniform;
1998 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05001999}
2000
Jiajia Qin5451d532017-11-16 17:16:34 +08002001bool ValidateUniform1ivValue(ValidationContext *context,
2002 GLenum uniformType,
2003 GLsizei count,
2004 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002005{
Jiajia Qin5451d532017-11-16 17:16:34 +08002006 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2007 // It is compatible with INT or BOOL.
2008 // Do these cheap tests first, for a little extra speed.
2009 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002010 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002011 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002012 }
2013
Jiajia Qin5451d532017-11-16 17:16:34 +08002014 if (IsSamplerType(uniformType))
2015 {
2016 // Check that the values are in range.
2017 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2018 for (GLsizei i = 0; i < count; ++i)
2019 {
2020 if (value[i] < 0 || value[i] >= max)
2021 {
2022 context->handleError(InvalidValue() << "sampler uniform value out of range");
2023 return false;
2024 }
2025 }
2026 return true;
2027 }
2028
2029 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2030 return false;
2031}
2032
2033bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2034{
2035 // Check that the value type is compatible with uniform type.
2036 // Do the cheaper test first, for a little extra speed.
2037 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2038 {
2039 return true;
2040 }
2041
2042 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2043 return false;
2044}
2045
2046bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2047{
2048 // Check that the value type is compatible with uniform type.
2049 if (valueType == uniformType)
2050 {
2051 return true;
2052 }
2053
2054 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2055 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002056}
2057
Jamie Madillc1d770e2017-04-13 17:31:24 -04002058bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002059{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002060 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002061 gl::Program *programObject = context->getGLState().getProgram();
2062 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2063 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002064}
2065
Jamie Madillbe849e42017-05-02 15:49:00 -04002066bool ValidateUniform1iv(ValidationContext *context,
2067 GLint location,
2068 GLsizei count,
2069 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002070{
2071 const LinkedUniform *uniform = nullptr;
2072 gl::Program *programObject = context->getGLState().getProgram();
2073 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2074 ValidateUniform1ivValue(context, uniform->type, count, value);
2075}
2076
Jamie Madillc1d770e2017-04-13 17:31:24 -04002077bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002078 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002079 GLint location,
2080 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002081 GLboolean transpose)
2082{
Geoff Lang92019432017-11-20 13:09:34 -05002083 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002084 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002085 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002086 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002087 }
2088
Jamie Madill62d31cb2015-09-11 13:25:51 -04002089 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002090 gl::Program *programObject = context->getGLState().getProgram();
2091 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2092 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002093}
2094
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002095bool ValidateStateQuery(ValidationContext *context,
2096 GLenum pname,
2097 GLenum *nativeType,
2098 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002099{
2100 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2101 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002102 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002103 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002104 }
2105
Jamie Madill0af26e12015-03-05 19:54:33 -05002106 const Caps &caps = context->getCaps();
2107
Jamie Madill893ab082014-05-16 16:56:10 -04002108 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2109 {
2110 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2111
Jamie Madill0af26e12015-03-05 19:54:33 -05002112 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002113 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002114 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002115 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002116 }
2117 }
2118
2119 switch (pname)
2120 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002121 case GL_TEXTURE_BINDING_2D:
2122 case GL_TEXTURE_BINDING_CUBE_MAP:
2123 case GL_TEXTURE_BINDING_3D:
2124 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002125 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002126 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002127 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2128 if (!context->getExtensions().textureRectangle)
2129 {
2130 context->handleError(InvalidEnum()
2131 << "ANGLE_texture_rectangle extension not present");
2132 return false;
2133 }
2134 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002135 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2136 if (!context->getExtensions().eglStreamConsumerExternal &&
2137 !context->getExtensions().eglImageExternal)
2138 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002139 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2140 "nor GL_OES_EGL_image_external "
2141 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002142 return false;
2143 }
2144 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002145
He Yunchaoced53ae2016-11-29 15:00:51 +08002146 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2147 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002148 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002149 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2150 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002151 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002152 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002153 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002154 }
2155
Jamie Madill51f40ec2016-06-15 14:06:00 -04002156 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2157 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002158
2159 if (framebuffer->getReadBufferState() == GL_NONE)
2160 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002161 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002162 return false;
2163 }
2164
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002165 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002166 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002167 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002168 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002169 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002170 }
2171 }
2172 break;
2173
He Yunchaoced53ae2016-11-29 15:00:51 +08002174 default:
2175 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002176 }
2177
2178 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002179 if (*numParams == 0)
2180 {
2181 return false;
2182 }
2183
2184 return true;
2185}
2186
2187bool ValidateRobustStateQuery(ValidationContext *context,
2188 GLenum pname,
2189 GLsizei bufSize,
2190 GLenum *nativeType,
2191 unsigned int *numParams)
2192{
2193 if (!ValidateRobustEntryPoint(context, bufSize))
2194 {
2195 return false;
2196 }
2197
2198 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2199 {
2200 return false;
2201 }
2202
2203 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002204 {
2205 return false;
2206 }
2207
2208 return true;
2209}
2210
Jamie Madillc29968b2016-01-20 11:17:23 -05002211bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2212 GLenum target,
2213 GLint level,
2214 GLenum internalformat,
2215 bool isSubImage,
2216 GLint xoffset,
2217 GLint yoffset,
2218 GLint zoffset,
2219 GLint x,
2220 GLint y,
2221 GLsizei width,
2222 GLsizei height,
2223 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002224 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002225{
Brandon Jones6cad5662017-06-14 13:25:13 -07002226 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002227 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002228 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2229 return false;
2230 }
2231
2232 if (width < 0 || height < 0)
2233 {
2234 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002235 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002236 }
2237
He Yunchaoced53ae2016-11-29 15:00:51 +08002238 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2239 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002240 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002241 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002242 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002243 }
2244
2245 if (border != 0)
2246 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002247 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002248 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002249 }
2250
2251 if (!ValidMipLevel(context, target, level))
2252 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002253 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002254 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002255 }
2256
Jamie Madill51f40ec2016-06-15 14:06:00 -04002257 const auto &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002258 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002259 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002260 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002261 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002262 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002263 }
2264
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002265 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002266 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002267 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002268 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002269 }
2270
Martin Radev138064f2016-07-15 12:03:41 +03002271 if (readFramebuffer->getReadBufferState() == GL_NONE)
2272 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002273 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002274 return false;
2275 }
2276
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002277 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2278 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002279 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002280 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002281 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2282 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002283 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002284 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002285 return false;
2286 }
2287
Martin Radev04e2c3b2017-07-27 16:54:35 +03002288 // ANGLE_multiview spec, Revision 1:
2289 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2290 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2291 // is not NONE.
2292 if (source->getMultiviewLayout() != GL_NONE)
2293 {
2294 context->handleError(InvalidFramebufferOperation()
2295 << "The active read framebuffer object has multiview attachments.");
2296 return false;
2297 }
2298
Geoff Langaae65a42014-05-26 12:43:44 -04002299 const gl::Caps &caps = context->getCaps();
2300
Geoff Langaae65a42014-05-26 12:43:44 -04002301 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002302 switch (target)
2303 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002304 case GL_TEXTURE_2D:
2305 maxDimension = caps.max2DTextureSize;
2306 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002307
He Yunchaoced53ae2016-11-29 15:00:51 +08002308 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2309 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2310 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2311 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2312 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2313 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2314 maxDimension = caps.maxCubeMapTextureSize;
2315 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002316
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002317 case GL_TEXTURE_RECTANGLE_ANGLE:
2318 maxDimension = caps.maxRectangleTextureSize;
2319 break;
2320
He Yunchaoced53ae2016-11-29 15:00:51 +08002321 case GL_TEXTURE_2D_ARRAY:
2322 maxDimension = caps.max2DTextureSize;
2323 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002324
He Yunchaoced53ae2016-11-29 15:00:51 +08002325 case GL_TEXTURE_3D:
2326 maxDimension = caps.max3DTextureSize;
2327 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002328
He Yunchaoced53ae2016-11-29 15:00:51 +08002329 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002330 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002331 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002332 }
2333
Jamie Madillc29968b2016-01-20 11:17:23 -05002334 gl::Texture *texture =
2335 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002336 if (!texture)
2337 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002338 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002339 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002340 }
2341
Geoff Lang69cce582015-09-17 13:20:36 -04002342 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002343 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002344 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002345 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002346 }
2347
Geoff Langca271392017-04-05 12:30:00 -04002348 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002349 isSubImage ? *texture->getFormat(target, level).info
2350 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002351
Geoff Lang966c9402017-04-18 12:38:27 -04002352 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002353 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002354 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002355 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002356 }
2357
2358 if (isSubImage)
2359 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002360 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2361 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2362 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002363 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002364 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002365 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002366 }
2367 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002368 else
2369 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002370 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002371 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002372 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002373 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002374 }
2375
Geoff Langeb66a6e2016-10-31 13:06:12 -04002376 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002377 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002378 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002379 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002380 }
2381
2382 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002383 if (static_cast<int>(width) > maxLevelDimension ||
2384 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002385 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002386 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002387 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002388 }
2389 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002390
Jamie Madill0c8abca2016-07-22 20:21:26 -04002391 if (textureFormatOut)
2392 {
2393 *textureFormatOut = texture->getFormat(target, level);
2394 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002395
2396 // Detect texture copying feedback loops for WebGL.
2397 if (context->getExtensions().webglCompatibility)
2398 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002399 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002400 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002401 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002402 return false;
2403 }
2404 }
2405
Jamie Madill560a8d82014-05-21 13:06:20 -04002406 return true;
2407}
2408
Jiajia Qind9671222016-11-29 16:30:31 +08002409bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002410{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002411 switch (mode)
2412 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002413 case GL_POINTS:
2414 case GL_LINES:
2415 case GL_LINE_LOOP:
2416 case GL_LINE_STRIP:
2417 case GL_TRIANGLES:
2418 case GL_TRIANGLE_STRIP:
2419 case GL_TRIANGLE_FAN:
2420 break;
2421 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002422 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002423 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002424 }
2425
Jamie Madill250d33f2014-06-06 17:09:03 -04002426 if (count < 0)
2427 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002428 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002429 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002430 }
2431
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002432 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002433
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002434 const Extensions &extensions = context->getExtensions();
2435
2436 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2437 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2438 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2439 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002440 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002441 // Check for mapped buffers
2442 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002443 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002444 {
2445 context->handleError(InvalidOperation());
2446 return false;
2447 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002448 }
2449
Jamie Madillcbcde722017-01-06 14:50:00 -05002450 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2451 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002452 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002453 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002454 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002455 const FramebufferAttachment *dsAttachment =
2456 framebuffer->getStencilOrDepthStencilAttachment();
2457 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002458 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002459 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002460
2461 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2462 bool differentWritemasks =
2463 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2464 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2465 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2466 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2467
2468 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002469 {
Martin Radevffe754b2017-07-31 10:38:07 +03002470 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002471 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002472 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2473 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002474 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002475 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002476 return false;
2477 }
Jamie Madillac528012014-06-20 13:21:23 -04002478 }
2479
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002480 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002481 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002482 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002483 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002484 }
2485
Geoff Lang7dd2e102014-11-10 15:19:26 -05002486 gl::Program *program = state.getProgram();
2487 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002488 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002489 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002490 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002491 }
2492
Yunchao Hecddcb592017-11-13 15:27:35 +08002493 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2494 // vertex shader stage or fragment shader stage is a undefined behaviour.
2495 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2496 // produce undefined result.
Yunchao Heece12532017-11-21 15:50:21 +08002497 if (!program->hasLinkedVertexShader() || !program->hasLinkedFragmentShader())
Yunchao Hecddcb592017-11-13 15:27:35 +08002498 {
2499 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2500 "vertex shader stage or fragment shader stage.");
2501 return false;
2502 }
2503
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002504 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002505 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002506 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002507 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002508 }
2509
Martin Radevffe754b2017-07-31 10:38:07 +03002510 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002511 {
Martin Radevda8e2572017-09-12 17:21:16 +03002512 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002513 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002514 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002515 {
2516 context->handleError(InvalidOperation() << "The number of views in the active program "
2517 "and draw framebuffer does not match.");
2518 return false;
2519 }
Martin Radev7e69f762017-07-27 14:54:13 +03002520
2521 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2522 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2523 framebufferNumViews > 1)
2524 {
2525 context->handleError(InvalidOperation()
2526 << "There is an active transform feedback object "
2527 "when the number of views in the active draw "
2528 "framebuffer is greater than 1.");
2529 return false;
2530 }
Martin Radevffe754b2017-07-31 10:38:07 +03002531
2532 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2533 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2534 {
2535 context->handleError(InvalidOperation() << "There is an active query for target "
2536 "GL_TIME_ELAPSED_EXT when the number of "
2537 "views in the active draw framebuffer is "
2538 "greater than 1.");
2539 return false;
2540 }
Martin Radev7cf61662017-07-26 17:10:53 +03002541 }
2542
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002543 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002544 for (unsigned int uniformBlockIndex = 0;
2545 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002546 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002547 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002548 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002549 const OffsetBindingPointer<Buffer> &uniformBuffer =
2550 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002551
Geoff Lang5d124a62015-09-15 13:03:27 -04002552 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002553 {
2554 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002555 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002556 InvalidOperation()
2557 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002558 return false;
2559 }
2560
Geoff Lang5d124a62015-09-15 13:03:27 -04002561 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002562 if (uniformBufferSize == 0)
2563 {
2564 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002565 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002566 }
2567
Jamie Madill62d31cb2015-09-11 13:25:51 -04002568 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002569 {
2570 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002571 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002572 InvalidOperation()
2573 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002574 return false;
2575 }
2576 }
2577
Geoff Lange0cff192017-05-30 13:04:56 -04002578 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002579 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002580 {
Geoff Lange0cff192017-05-30 13:04:56 -04002581 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002582 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2583 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002584 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002585 return false;
2586 }
Geoff Lange0cff192017-05-30 13:04:56 -04002587
Geoff Lang9ab5b822017-05-30 16:19:23 -04002588 // Detect that the vertex shader input types match the attribute types
2589 if (!ValidateVertexShaderAttributeTypeMatch(context))
2590 {
2591 return false;
2592 }
2593
Geoff Lange0cff192017-05-30 13:04:56 -04002594 // Detect that the color buffer types match the fragment shader output types
2595 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2596 {
2597 return false;
2598 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002599 }
2600
Jamie Madill250d33f2014-06-06 17:09:03 -04002601 // No-op if zero count
2602 return (count > 0);
2603}
2604
Jamie Madillc1d770e2017-04-13 17:31:24 -04002605bool ValidateDrawArraysCommon(ValidationContext *context,
2606 GLenum mode,
2607 GLint first,
2608 GLsizei count,
2609 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002610{
Jamie Madillfd716582014-06-06 17:09:04 -04002611 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002612 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002613 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002614 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002615 }
2616
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002617 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002618 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002619 if (curTransformFeedback && curTransformFeedback->isActive() &&
2620 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002621 {
2622 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002623 // that does not match the current transform feedback object's draw mode (if transform
2624 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002625 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002626 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002627 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002628 }
2629
Jiajia Qind9671222016-11-29 16:30:31 +08002630 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002631 {
2632 return false;
2633 }
2634
Corentin Wallez71168a02016-12-19 15:11:18 -08002635 // Check the computation of maxVertex doesn't overflow.
2636 // - first < 0 or count < 0 have been checked as an error condition
2637 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2638 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2639 ASSERT(count > 0 && first >= 0);
2640 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2641 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002642 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002643 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002644 return false;
2645 }
2646
Corentin Wallez71168a02016-12-19 15:11:18 -08002647 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002648 {
2649 return false;
2650 }
2651
2652 return true;
2653}
2654
He Yunchaoced53ae2016-11-29 15:00:51 +08002655bool ValidateDrawArraysInstancedANGLE(Context *context,
2656 GLenum mode,
2657 GLint first,
2658 GLsizei count,
2659 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002660{
Geoff Lang63c5a592017-09-27 14:08:16 -04002661 if (!context->getExtensions().instancedArrays)
2662 {
2663 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2664 return false;
2665 }
2666
Corentin Wallez170efbf2017-05-02 13:45:01 -04002667 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002668 {
2669 return false;
2670 }
2671
Corentin Wallez0dc97812017-06-22 14:38:44 -04002672 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002673}
2674
Jiajia Qind9671222016-11-29 16:30:31 +08002675bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002676{
Jamie Madill250d33f2014-06-06 17:09:03 -04002677 switch (type)
2678 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002679 case GL_UNSIGNED_BYTE:
2680 case GL_UNSIGNED_SHORT:
2681 break;
2682 case GL_UNSIGNED_INT:
2683 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2684 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002685 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002686 return false;
2687 }
2688 break;
2689 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002690 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002691 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002692 }
2693
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002694 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002695
2696 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002697 if (curTransformFeedback && curTransformFeedback->isActive() &&
2698 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002699 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002700 // It is an invalid operation to call DrawElements, DrawRangeElements or
2701 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002702 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002703 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002704 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002705 }
2706
Jiajia Qind9671222016-11-29 16:30:31 +08002707 return true;
2708}
2709
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002710bool ValidateDrawElementsCommon(ValidationContext *context,
2711 GLenum mode,
2712 GLsizei count,
2713 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002714 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002715 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002716{
2717 if (!ValidateDrawElementsBase(context, type))
2718 return false;
2719
2720 const State &state = context->getGLState();
2721
Corentin Wallez170efbf2017-05-02 13:45:01 -04002722 if (!ValidateDrawBase(context, mode, count))
2723 {
2724 return false;
2725 }
2726
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002727 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2728 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2729 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2730 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002731 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002732 // Check for mapped buffers
2733 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002734 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002735 {
2736 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2737 return false;
2738 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002739 }
2740
He Yunchaoced53ae2016-11-29 15:00:51 +08002741 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002742 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002743
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002744 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2745
2746 if (context->getExtensions().webglCompatibility)
2747 {
2748 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2749 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2750 {
2751 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2752 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2753 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002754 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002755 return false;
2756 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002757
2758 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2759 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2760 // error is generated.
2761 if (reinterpret_cast<intptr_t>(indices) < 0)
2762 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002763 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002764 return false;
2765 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002766 }
2767
2768 if (context->getExtensions().webglCompatibility ||
2769 !context->getGLState().areClientArraysEnabled())
2770 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002771 if (!elementArrayBuffer && count > 0)
2772 {
2773 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2774 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2775 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002776 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002777 return false;
2778 }
2779 }
2780
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002781 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002782 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002783 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002784 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002785 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2786 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2787 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2788 constexpr uint64_t kMaxTypeSize = 8;
2789 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2790 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2791 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002792
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002793 uint64_t typeSize = typeBytes;
2794 uint64_t elementCount = static_cast<uint64_t>(count);
2795 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2796
2797 // Doing the multiplication here is overflow-safe
2798 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2799
2800 // The offset can be any value, check for overflows
2801 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2802 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002803 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002804 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002805 return false;
2806 }
2807
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002808 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2809 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002810 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002811 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002812 return false;
2813 }
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002814
Corentin Wallez487653b2017-09-01 17:17:55 -04002815 ASSERT(isPow2(typeSize) && typeSize > 0);
2816 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002817 {
2818 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
2819 return false;
2820 }
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002821 }
2822 else if (!indices)
2823 {
2824 // This is an application error that would normally result in a crash,
2825 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002826 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04002827 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002828 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002829 }
2830
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002831 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002832 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002833 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2834 // access is enabled.
2835 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2836 {
2837 return false;
2838 }
2839 }
2840 else
2841 {
2842 // Use the parameter buffer to retrieve and cache the index range.
2843 const auto &params = context->getParams<HasIndexRange>();
2844 const auto &indexRangeOpt = params.getIndexRange();
2845 if (!indexRangeOpt.valid())
2846 {
2847 // Unexpected error.
2848 return false;
2849 }
2850
2851 // If we use an index greater than our maximum supported index range, return an error.
2852 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2853 // return an error if possible here.
2854 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2855 {
2856 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2857 return false;
2858 }
2859
2860 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2861 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2862 {
2863 return false;
2864 }
2865
2866 // No op if there are no real indices in the index data (all are primitive restart).
2867 return (indexRangeOpt.value().vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002868 }
2869
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002870 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002871}
2872
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002873bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2874 GLenum mode,
2875 GLsizei count,
2876 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002877 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002878 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002879{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002880 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002881}
2882
Geoff Lang3edfe032015-09-04 16:38:24 -04002883bool ValidateDrawElementsInstancedANGLE(Context *context,
2884 GLenum mode,
2885 GLsizei count,
2886 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002887 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002888 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002889{
Geoff Lang63c5a592017-09-27 14:08:16 -04002890 if (!context->getExtensions().instancedArrays)
2891 {
2892 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2893 return false;
2894 }
2895
Corentin Wallez170efbf2017-05-02 13:45:01 -04002896 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002897 {
2898 return false;
2899 }
2900
Corentin Wallez0dc97812017-06-22 14:38:44 -04002901 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002902}
2903
He Yunchaoced53ae2016-11-29 15:00:51 +08002904bool ValidateFramebufferTextureBase(Context *context,
2905 GLenum target,
2906 GLenum attachment,
2907 GLuint texture,
2908 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002909{
Geoff Lange8afa902017-09-27 15:00:43 -04002910 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002911 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002912 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002913 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002914 }
2915
2916 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002917 {
2918 return false;
2919 }
2920
Jamie Madill55ec3b12014-07-03 10:38:57 -04002921 if (texture != 0)
2922 {
2923 gl::Texture *tex = context->getTexture(texture);
2924
Luc Ferronadcf0ae2018-01-24 08:27:37 -05002925 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002926 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002927 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002928 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002929 }
2930
2931 if (level < 0)
2932 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002933 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002934 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002935 }
2936 }
2937
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002938 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002939 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002940
Jamie Madill84115c92015-04-23 15:00:07 -04002941 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002942 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002943 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002944 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002945 }
2946
2947 return true;
2948}
2949
Geoff Langb1196682014-07-23 13:47:29 -04002950bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04002951{
2952 if (program == 0)
2953 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002954 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002955 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002956 }
2957
Dian Xiang769769a2015-09-09 15:20:08 -07002958 gl::Program *programObject = GetValidProgram(context, program);
2959 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05002960 {
2961 return false;
2962 }
2963
Jamie Madill0063c512014-08-25 15:47:53 -04002964 if (!programObject || !programObject->isLinked())
2965 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002966 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04002967 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002968 }
2969
Geoff Lang7dd2e102014-11-10 15:19:26 -05002970 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04002971 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002972 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002973 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04002974 }
2975
Jamie Madill0063c512014-08-25 15:47:53 -04002976 return true;
2977}
2978
Geoff Langf41d0ee2016-10-07 13:04:23 -04002979static bool ValidateSizedGetUniform(Context *context,
2980 GLuint program,
2981 GLint location,
2982 GLsizei bufSize,
2983 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04002984{
Geoff Langf41d0ee2016-10-07 13:04:23 -04002985 if (length)
2986 {
2987 *length = 0;
2988 }
2989
Jamie Madill78f41802014-08-25 15:47:55 -04002990 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04002991 {
Jamie Madill78f41802014-08-25 15:47:55 -04002992 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002993 }
2994
Geoff Langf41d0ee2016-10-07 13:04:23 -04002995 if (bufSize < 0)
2996 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002997 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04002998 return false;
2999 }
3000
Jamie Madilla502c742014-08-28 17:19:13 -04003001 gl::Program *programObject = context->getProgram(program);
3002 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003003
Jamie Madill78f41802014-08-25 15:47:55 -04003004 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003005 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003006 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003007 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003008 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003009 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003010 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003011 }
3012
Geoff Langf41d0ee2016-10-07 13:04:23 -04003013 if (length)
3014 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003015 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003016 }
3017
Jamie Madill0063c512014-08-25 15:47:53 -04003018 return true;
3019}
3020
He Yunchaoced53ae2016-11-29 15:00:51 +08003021bool ValidateGetnUniformfvEXT(Context *context,
3022 GLuint program,
3023 GLint location,
3024 GLsizei bufSize,
3025 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003026{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003027 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003028}
3029
He Yunchaoced53ae2016-11-29 15:00:51 +08003030bool ValidateGetnUniformivEXT(Context *context,
3031 GLuint program,
3032 GLint location,
3033 GLsizei bufSize,
3034 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003035{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003036 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3037}
3038
3039bool ValidateGetUniformfvRobustANGLE(Context *context,
3040 GLuint program,
3041 GLint location,
3042 GLsizei bufSize,
3043 GLsizei *length,
3044 GLfloat *params)
3045{
3046 if (!ValidateRobustEntryPoint(context, bufSize))
3047 {
3048 return false;
3049 }
3050
3051 // bufSize is validated in ValidateSizedGetUniform
3052 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3053}
3054
3055bool ValidateGetUniformivRobustANGLE(Context *context,
3056 GLuint program,
3057 GLint location,
3058 GLsizei bufSize,
3059 GLsizei *length,
3060 GLint *params)
3061{
3062 if (!ValidateRobustEntryPoint(context, bufSize))
3063 {
3064 return false;
3065 }
3066
3067 // bufSize is validated in ValidateSizedGetUniform
3068 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3069}
3070
3071bool ValidateGetUniformuivRobustANGLE(Context *context,
3072 GLuint program,
3073 GLint location,
3074 GLsizei bufSize,
3075 GLsizei *length,
3076 GLuint *params)
3077{
3078 if (!ValidateRobustEntryPoint(context, bufSize))
3079 {
3080 return false;
3081 }
3082
3083 if (context->getClientMajorVersion() < 3)
3084 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003085 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003086 return false;
3087 }
3088
3089 // bufSize is validated in ValidateSizedGetUniform
3090 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003091}
3092
He Yunchaoced53ae2016-11-29 15:00:51 +08003093bool ValidateDiscardFramebufferBase(Context *context,
3094 GLenum target,
3095 GLsizei numAttachments,
3096 const GLenum *attachments,
3097 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003098{
3099 if (numAttachments < 0)
3100 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003101 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003102 return false;
3103 }
3104
3105 for (GLsizei i = 0; i < numAttachments; ++i)
3106 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003107 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003108 {
3109 if (defaultFramebuffer)
3110 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003111 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003112 return false;
3113 }
3114
3115 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3116 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003117 context->handleError(InvalidOperation() << "Requested color attachment is "
3118 "greater than the maximum supported "
3119 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003120 return false;
3121 }
3122 }
3123 else
3124 {
3125 switch (attachments[i])
3126 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003127 case GL_DEPTH_ATTACHMENT:
3128 case GL_STENCIL_ATTACHMENT:
3129 case GL_DEPTH_STENCIL_ATTACHMENT:
3130 if (defaultFramebuffer)
3131 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003132 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3133 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003134 return false;
3135 }
3136 break;
3137 case GL_COLOR:
3138 case GL_DEPTH:
3139 case GL_STENCIL:
3140 if (!defaultFramebuffer)
3141 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003142 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3143 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003144 return false;
3145 }
3146 break;
3147 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003148 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003149 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003150 }
3151 }
3152 }
3153
3154 return true;
3155}
3156
Austin Kinross6ee1e782015-05-29 17:05:37 -07003157bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3158{
Jamie Madill007530e2017-12-28 14:27:04 -05003159 if (!context->getExtensions().debugMarker)
3160 {
3161 // The debug marker calls should not set error state
3162 // However, it seems reasonable to set an error state if the extension is not enabled
3163 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3164 return false;
3165 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003166
Jamie Madill007530e2017-12-28 14:27:04 -05003167 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003168 if (length < 0)
3169 {
3170 return false;
3171 }
3172
3173 if (marker == nullptr)
3174 {
3175 return false;
3176 }
3177
3178 return true;
3179}
3180
3181bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3182{
Jamie Madill007530e2017-12-28 14:27:04 -05003183 if (!context->getExtensions().debugMarker)
3184 {
3185 // The debug marker calls should not set error state
3186 // However, it seems reasonable to set an error state if the extension is not enabled
3187 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3188 return false;
3189 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003190
Jamie Madill007530e2017-12-28 14:27:04 -05003191 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003192 if (length < 0)
3193 {
3194 return false;
3195 }
3196
3197 if (length > 0 && marker == nullptr)
3198 {
3199 return false;
3200 }
3201
3202 return true;
3203}
3204
Jamie Madill007530e2017-12-28 14:27:04 -05003205bool ValidateEGLImageTargetTexture2DOES(Context *context, GLenum target, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003206{
Geoff Langa8406172015-07-21 16:53:39 -04003207 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3208 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003209 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003210 return false;
3211 }
3212
3213 switch (target)
3214 {
3215 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003216 if (!context->getExtensions().eglImage)
3217 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003218 context->handleError(InvalidEnum()
3219 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003220 }
3221 break;
3222
3223 case GL_TEXTURE_EXTERNAL_OES:
3224 if (!context->getExtensions().eglImageExternal)
3225 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003226 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3227 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003228 }
Geoff Langa8406172015-07-21 16:53:39 -04003229 break;
3230
3231 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003232 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003233 return false;
3234 }
3235
Jamie Madill007530e2017-12-28 14:27:04 -05003236 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3237
Jamie Madill61e16b42017-06-19 11:13:23 -04003238 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003239 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003240 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003241 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003242 return false;
3243 }
3244
Jamie Madill007530e2017-12-28 14:27:04 -05003245 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003246 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003247 context->handleError(InvalidOperation()
3248 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003249 return false;
3250 }
3251
Geoff Langca271392017-04-05 12:30:00 -04003252 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003253 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003254 if (!textureCaps.texturable)
3255 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003256 context->handleError(InvalidOperation()
3257 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003258 return false;
3259 }
3260
Geoff Langdcab33b2015-07-21 13:03:16 -04003261 return true;
3262}
3263
3264bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003265 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003266 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003267{
Geoff Langa8406172015-07-21 16:53:39 -04003268 if (!context->getExtensions().eglImage)
3269 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003270 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003271 return false;
3272 }
3273
3274 switch (target)
3275 {
3276 case GL_RENDERBUFFER:
3277 break;
3278
3279 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003280 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003281 return false;
3282 }
3283
Jamie Madill007530e2017-12-28 14:27:04 -05003284 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3285
Jamie Madill61e16b42017-06-19 11:13:23 -04003286 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003287 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003288 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003289 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003290 return false;
3291 }
3292
Geoff Langca271392017-04-05 12:30:00 -04003293 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003294 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003295 if (!textureCaps.renderable)
3296 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003297 context->handleError(InvalidOperation()
3298 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003299 return false;
3300 }
3301
Geoff Langdcab33b2015-07-21 13:03:16 -04003302 return true;
3303}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003304
3305bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3306{
Geoff Lang36167ab2015-12-07 10:27:14 -05003307 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003308 {
3309 // The default VAO should always exist
3310 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003311 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003312 return false;
3313 }
3314
3315 return true;
3316}
3317
Geoff Langc5629752015-12-07 16:29:04 -05003318bool ValidateProgramBinaryBase(Context *context,
3319 GLuint program,
3320 GLenum binaryFormat,
3321 const void *binary,
3322 GLint length)
3323{
3324 Program *programObject = GetValidProgram(context, program);
3325 if (programObject == nullptr)
3326 {
3327 return false;
3328 }
3329
3330 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3331 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3332 programBinaryFormats.end())
3333 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003334 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003335 return false;
3336 }
3337
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003338 if (context->hasActiveTransformFeedback(program))
3339 {
3340 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003341 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3342 "is associated with an active transform "
3343 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003344 return false;
3345 }
3346
Geoff Langc5629752015-12-07 16:29:04 -05003347 return true;
3348}
3349
3350bool ValidateGetProgramBinaryBase(Context *context,
3351 GLuint program,
3352 GLsizei bufSize,
3353 GLsizei *length,
3354 GLenum *binaryFormat,
3355 void *binary)
3356{
3357 Program *programObject = GetValidProgram(context, program);
3358 if (programObject == nullptr)
3359 {
3360 return false;
3361 }
3362
3363 if (!programObject->isLinked())
3364 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003365 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003366 return false;
3367 }
3368
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003369 if (context->getCaps().programBinaryFormats.empty())
3370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003371 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003372 return false;
3373 }
3374
Geoff Langc5629752015-12-07 16:29:04 -05003375 return true;
3376}
Jamie Madillc29968b2016-01-20 11:17:23 -05003377
Jamie Madillc29968b2016-01-20 11:17:23 -05003378bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3379{
3380 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003381 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003382 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003383 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3384 return false;
3385 }
3386 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3387 {
3388 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003389 return false;
3390 }
3391
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003392 ASSERT(context->getGLState().getDrawFramebuffer());
3393 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003394 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3395
3396 // This should come first before the check for the default frame buffer
3397 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3398 // rather than INVALID_OPERATION
3399 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3400 {
3401 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3402
3403 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003404 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3405 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003406 {
3407 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003408 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3409 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3410 // 3.1 is still a bit ambiguous about the error, but future specs are
3411 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003412 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003413 return false;
3414 }
3415 else if (bufs[colorAttachment] >= maxColorAttachment)
3416 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003417 context->handleError(InvalidOperation()
3418 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003419 return false;
3420 }
3421 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3422 frameBufferId != 0)
3423 {
3424 // INVALID_OPERATION-GL is bound to buffer and ith argument
3425 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003426 context->handleError(InvalidOperation()
3427 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003428 return false;
3429 }
3430 }
3431
3432 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3433 // and n is not 1 or bufs is bound to value other than BACK and NONE
3434 if (frameBufferId == 0)
3435 {
3436 if (n != 1)
3437 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003438 context->handleError(InvalidOperation()
3439 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003440 return false;
3441 }
3442
3443 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3444 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003445 context->handleError(
3446 InvalidOperation()
3447 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003448 return false;
3449 }
3450 }
3451
3452 return true;
3453}
3454
Geoff Lang496c02d2016-10-20 11:38:11 -07003455bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003456 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003457 GLenum pname,
3458 GLsizei *length,
3459 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003460{
Geoff Lang496c02d2016-10-20 11:38:11 -07003461 if (length)
3462 {
3463 *length = 0;
3464 }
3465
3466 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3467 {
3468 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003469 InvalidOperation()
3470 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003471 return false;
3472 }
3473
Corentin Walleze4477002017-12-01 14:39:58 -05003474 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003475 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003476 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003477 return false;
3478 }
3479
Geoff Lang496c02d2016-10-20 11:38:11 -07003480 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003481 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003482 case GL_BUFFER_MAP_POINTER:
3483 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003484
Geoff Lang496c02d2016-10-20 11:38:11 -07003485 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003486 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003487 return false;
3488 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003489
3490 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3491 // target bound to zero generate an INVALID_OPERATION error."
3492 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003493 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003494 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003495 context->handleError(InvalidOperation()
3496 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003497 return false;
3498 }
3499
Geoff Lang496c02d2016-10-20 11:38:11 -07003500 if (length)
3501 {
3502 *length = 1;
3503 }
3504
Olli Etuaho4f667482016-03-30 15:56:35 +03003505 return true;
3506}
3507
Corentin Wallez336129f2017-10-17 15:55:40 -04003508bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003509{
Corentin Walleze4477002017-12-01 14:39:58 -05003510 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003511 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003512 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003513 return false;
3514 }
3515
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003516 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003517
3518 if (buffer == nullptr || !buffer->isMapped())
3519 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003520 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003521 return false;
3522 }
3523
3524 return true;
3525}
3526
3527bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003528 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003529 GLintptr offset,
3530 GLsizeiptr length,
3531 GLbitfield access)
3532{
Corentin Walleze4477002017-12-01 14:39:58 -05003533 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003534 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003535 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003536 return false;
3537 }
3538
Brandon Jones6cad5662017-06-14 13:25:13 -07003539 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003540 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003541 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3542 return false;
3543 }
3544
3545 if (length < 0)
3546 {
3547 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003548 return false;
3549 }
3550
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003551 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003552
3553 if (!buffer)
3554 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003555 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003556 return false;
3557 }
3558
3559 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003560 CheckedNumeric<size_t> checkedOffset(offset);
3561 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003562
Jamie Madille2e406c2016-06-02 13:04:10 -04003563 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003564 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003565 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003566 return false;
3567 }
3568
3569 // Check for invalid bits in the mask
3570 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3571 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3572 GL_MAP_UNSYNCHRONIZED_BIT;
3573
3574 if (access & ~(allAccessBits))
3575 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003576 context->handleError(InvalidValue()
3577 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003578 return false;
3579 }
3580
3581 if (length == 0)
3582 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003583 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003584 return false;
3585 }
3586
3587 if (buffer->isMapped())
3588 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003589 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003590 return false;
3591 }
3592
3593 // Check for invalid bit combinations
3594 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3595 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003596 context->handleError(InvalidOperation()
3597 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003598 return false;
3599 }
3600
3601 GLbitfield writeOnlyBits =
3602 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3603
3604 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3605 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003606 context->handleError(InvalidOperation()
3607 << "Invalid access bits when mapping buffer for reading: 0x"
3608 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003609 return false;
3610 }
3611
3612 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3613 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003614 context->handleError(
3615 InvalidOperation()
3616 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003617 return false;
3618 }
Geoff Lang79f71042017-08-14 16:43:43 -04003619
3620 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003621}
3622
3623bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003624 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003625 GLintptr offset,
3626 GLsizeiptr length)
3627{
Brandon Jones6cad5662017-06-14 13:25:13 -07003628 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003629 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003630 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3631 return false;
3632 }
3633
3634 if (length < 0)
3635 {
3636 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003637 return false;
3638 }
3639
Corentin Walleze4477002017-12-01 14:39:58 -05003640 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003641 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003642 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003643 return false;
3644 }
3645
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003646 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003647
3648 if (buffer == nullptr)
3649 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003650 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003651 return false;
3652 }
3653
3654 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3655 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003656 context->handleError(InvalidOperation()
3657 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003658 return false;
3659 }
3660
3661 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003662 CheckedNumeric<size_t> checkedOffset(offset);
3663 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003664
Jamie Madille2e406c2016-06-02 13:04:10 -04003665 if (!checkedSize.IsValid() ||
3666 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003667 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003668 context->handleError(InvalidValue()
3669 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003670 return false;
3671 }
3672
3673 return true;
3674}
3675
Olli Etuaho41997e72016-03-10 13:38:39 +02003676bool ValidateGenOrDelete(Context *context, GLint n)
3677{
3678 if (n < 0)
3679 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003680 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003681 return false;
3682 }
3683 return true;
3684}
3685
Geoff Langff5b2d52016-09-07 11:32:23 -04003686bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3687{
3688 if (!context->getExtensions().robustClientMemory)
3689 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003690 context->handleError(InvalidOperation()
3691 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003692 return false;
3693 }
3694
3695 if (bufSize < 0)
3696 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003697 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003698 return false;
3699 }
3700
3701 return true;
3702}
3703
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003704bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3705{
3706 if (bufSize < numParams)
3707 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003708 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3709 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003710 return false;
3711 }
3712
3713 return true;
3714}
3715
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003716bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04003717 GLenum target,
3718 GLenum attachment,
3719 GLenum pname,
3720 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003721{
Geoff Lange8afa902017-09-27 15:00:43 -04003722 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003724 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003725 return false;
3726 }
3727
3728 int clientVersion = context->getClientMajorVersion();
3729
3730 switch (pname)
3731 {
3732 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3733 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3734 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3735 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3736 break;
3737
Martin Radeve5285d22017-07-14 16:23:53 +03003738 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3739 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3740 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3741 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3742 if (clientVersion < 3 || !context->getExtensions().multiview)
3743 {
3744 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3745 return false;
3746 }
3747 break;
3748
Geoff Langff5b2d52016-09-07 11:32:23 -04003749 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3750 if (clientVersion < 3 && !context->getExtensions().sRGB)
3751 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003752 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003753 return false;
3754 }
3755 break;
3756
3757 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3758 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3759 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3760 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3761 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3762 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3763 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3764 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3765 if (clientVersion < 3)
3766 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003767 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003768 return false;
3769 }
3770 break;
3771
3772 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003773 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003774 return false;
3775 }
3776
3777 // Determine if the attachment is a valid enum
3778 switch (attachment)
3779 {
3780 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04003781 case GL_DEPTH:
3782 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04003783 if (clientVersion < 3)
3784 {
Geoff Langfa125c92017-10-24 13:01:46 -04003785 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003786 return false;
3787 }
3788 break;
3789
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003790 case GL_DEPTH_STENCIL_ATTACHMENT:
3791 if (clientVersion < 3 && !context->isWebGL1())
3792 {
3793 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3794 return false;
3795 }
3796 break;
3797
Geoff Langfa125c92017-10-24 13:01:46 -04003798 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003799 case GL_DEPTH_ATTACHMENT:
3800 case GL_STENCIL_ATTACHMENT:
3801 break;
3802
3803 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003804 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3805 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003806 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3807 {
Geoff Langfa125c92017-10-24 13:01:46 -04003808 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003809 return false;
3810 }
3811 break;
3812 }
3813
3814 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3815 ASSERT(framebuffer);
3816
3817 if (framebuffer->id() == 0)
3818 {
3819 if (clientVersion < 3)
3820 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003821 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003822 return false;
3823 }
3824
3825 switch (attachment)
3826 {
3827 case GL_BACK:
3828 case GL_DEPTH:
3829 case GL_STENCIL:
3830 break;
3831
3832 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003833 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003834 return false;
3835 }
3836 }
3837 else
3838 {
3839 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3840 {
3841 // Valid attachment query
3842 }
3843 else
3844 {
3845 switch (attachment)
3846 {
3847 case GL_DEPTH_ATTACHMENT:
3848 case GL_STENCIL_ATTACHMENT:
3849 break;
3850
3851 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003852 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04003853 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003854 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003855 return false;
3856 }
3857 break;
3858
3859 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003860 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003861 return false;
3862 }
3863 }
3864 }
3865
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003866 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003867 if (attachmentObject)
3868 {
3869 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3870 attachmentObject->type() == GL_TEXTURE ||
3871 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3872
3873 switch (pname)
3874 {
3875 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3876 if (attachmentObject->type() != GL_RENDERBUFFER &&
3877 attachmentObject->type() != GL_TEXTURE)
3878 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003879 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003880 return false;
3881 }
3882 break;
3883
3884 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3885 if (attachmentObject->type() != GL_TEXTURE)
3886 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003887 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003888 return false;
3889 }
3890 break;
3891
3892 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3893 if (attachmentObject->type() != GL_TEXTURE)
3894 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003895 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003896 return false;
3897 }
3898 break;
3899
3900 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3901 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3902 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003903 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003904 return false;
3905 }
3906 break;
3907
3908 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3909 if (attachmentObject->type() != GL_TEXTURE)
3910 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003911 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003912 return false;
3913 }
3914 break;
3915
3916 default:
3917 break;
3918 }
3919 }
3920 else
3921 {
3922 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3923 // is NONE, then querying any other pname will generate INVALID_ENUM.
3924
3925 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3926 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3927 // INVALID_OPERATION for all other pnames
3928
3929 switch (pname)
3930 {
3931 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3932 break;
3933
3934 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3935 if (clientVersion < 3)
3936 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003937 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003938 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003939 return false;
3940 }
3941 break;
3942
3943 default:
3944 if (clientVersion < 3)
3945 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003946 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003947 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003948 return false;
3949 }
3950 else
3951 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003952 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003953 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003954 return false;
3955 }
3956 }
3957 }
3958
Martin Radeve5285d22017-07-14 16:23:53 +03003959 if (numParams)
3960 {
3961 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
3962 {
3963 // Only when the viewport offsets are queried we can have a varying number of output
3964 // parameters.
3965 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
3966 *numParams = numViews * 2;
3967 }
3968 else
3969 {
3970 // For all other queries we can have only one output parameter.
3971 *numParams = 1;
3972 }
3973 }
3974
Geoff Langff5b2d52016-09-07 11:32:23 -04003975 return true;
3976}
3977
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003978bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04003979 GLenum target,
3980 GLenum attachment,
3981 GLenum pname,
3982 GLsizei bufSize,
3983 GLsizei *numParams)
3984{
3985 if (!ValidateRobustEntryPoint(context, bufSize))
3986 {
3987 return false;
3988 }
3989
Jamie Madillbe849e42017-05-02 15:49:00 -04003990 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
3991 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04003992 {
3993 return false;
3994 }
3995
3996 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
3997 {
3998 return false;
3999 }
4000
4001 return true;
4002}
4003
Geoff Langff5b2d52016-09-07 11:32:23 -04004004bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004005 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004006 GLenum pname,
4007 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004008 GLsizei *length,
4009 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004010{
4011 if (!ValidateRobustEntryPoint(context, bufSize))
4012 {
4013 return false;
4014 }
4015
Geoff Langebebe1c2016-10-14 12:01:31 -04004016 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004017 {
4018 return false;
4019 }
4020
Geoff Langebebe1c2016-10-14 12:01:31 -04004021 if (!ValidateRobustBufferSize(context, bufSize, *length))
4022 {
4023 return false;
4024 }
4025
4026 return true;
4027}
4028
Geoff Langebebe1c2016-10-14 12:01:31 -04004029bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004030 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004031 GLenum pname,
4032 GLsizei bufSize,
4033 GLsizei *length,
4034 GLint64 *params)
4035{
4036 if (!ValidateRobustEntryPoint(context, bufSize))
4037 {
4038 return false;
4039 }
4040
4041 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4042 {
4043 return false;
4044 }
4045
4046 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004047 {
4048 return false;
4049 }
4050
4051 return true;
4052}
4053
Jamie Madillbe849e42017-05-02 15:49:00 -04004054bool ValidateGetProgramivBase(ValidationContext *context,
4055 GLuint program,
4056 GLenum pname,
4057 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004058{
4059 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004060 if (numParams)
4061 {
4062 *numParams = 1;
4063 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004064
4065 Program *programObject = GetValidProgram(context, program);
4066 if (!programObject)
4067 {
4068 return false;
4069 }
4070
4071 switch (pname)
4072 {
4073 case GL_DELETE_STATUS:
4074 case GL_LINK_STATUS:
4075 case GL_VALIDATE_STATUS:
4076 case GL_INFO_LOG_LENGTH:
4077 case GL_ATTACHED_SHADERS:
4078 case GL_ACTIVE_ATTRIBUTES:
4079 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4080 case GL_ACTIVE_UNIFORMS:
4081 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4082 break;
4083
4084 case GL_PROGRAM_BINARY_LENGTH:
4085 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4086 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004087 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4088 "requires GL_OES_get_program_binary or "
4089 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004090 return false;
4091 }
4092 break;
4093
4094 case GL_ACTIVE_UNIFORM_BLOCKS:
4095 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4096 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4097 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4098 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4099 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4100 if (context->getClientMajorVersion() < 3)
4101 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004102 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004103 return false;
4104 }
4105 break;
4106
Yunchao He61afff12017-03-14 15:34:03 +08004107 case GL_PROGRAM_SEPARABLE:
Xinghua Cao971f8502017-10-17 13:01:24 +08004108 case GL_COMPUTE_WORK_GROUP_SIZE:
jchen1058f67be2017-10-27 08:59:27 +08004109 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004110 if (context->getClientVersion() < Version(3, 1))
4111 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004112 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004113 return false;
4114 }
4115 break;
4116
Geoff Langff5b2d52016-09-07 11:32:23 -04004117 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004118 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004119 return false;
4120 }
4121
4122 return true;
4123}
4124
4125bool ValidateGetProgramivRobustANGLE(Context *context,
4126 GLuint program,
4127 GLenum pname,
4128 GLsizei bufSize,
4129 GLsizei *numParams)
4130{
4131 if (!ValidateRobustEntryPoint(context, bufSize))
4132 {
4133 return false;
4134 }
4135
Jamie Madillbe849e42017-05-02 15:49:00 -04004136 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004137 {
4138 return false;
4139 }
4140
4141 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4142 {
4143 return false;
4144 }
4145
4146 return true;
4147}
4148
Geoff Lang740d9022016-10-07 11:20:52 -04004149bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4150 GLenum target,
4151 GLenum pname,
4152 GLsizei bufSize,
4153 GLsizei *length,
4154 GLint *params)
4155{
4156 if (!ValidateRobustEntryPoint(context, bufSize))
4157 {
4158 return false;
4159 }
4160
4161 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4162 {
4163 return false;
4164 }
4165
4166 if (!ValidateRobustBufferSize(context, bufSize, *length))
4167 {
4168 return false;
4169 }
4170
4171 return true;
4172}
4173
Geoff Langd7d0ed32016-10-07 11:33:51 -04004174bool ValidateGetShaderivRobustANGLE(Context *context,
4175 GLuint shader,
4176 GLenum pname,
4177 GLsizei bufSize,
4178 GLsizei *length,
4179 GLint *params)
4180{
4181 if (!ValidateRobustEntryPoint(context, bufSize))
4182 {
4183 return false;
4184 }
4185
4186 if (!ValidateGetShaderivBase(context, shader, pname, length))
4187 {
4188 return false;
4189 }
4190
4191 if (!ValidateRobustBufferSize(context, bufSize, *length))
4192 {
4193 return false;
4194 }
4195
4196 return true;
4197}
4198
Geoff Langc1984ed2016-10-07 12:41:00 -04004199bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4200 GLenum target,
4201 GLenum pname,
4202 GLsizei bufSize,
4203 GLsizei *length,
4204 GLfloat *params)
4205{
4206 if (!ValidateRobustEntryPoint(context, bufSize))
4207 {
4208 return false;
4209 }
4210
4211 if (!ValidateGetTexParameterBase(context, target, pname, length))
4212 {
4213 return false;
4214 }
4215
4216 if (!ValidateRobustBufferSize(context, bufSize, *length))
4217 {
4218 return false;
4219 }
4220
4221 return true;
4222}
4223
Geoff Langc1984ed2016-10-07 12:41:00 -04004224bool ValidateGetTexParameterivRobustANGLE(Context *context,
4225 GLenum target,
4226 GLenum pname,
4227 GLsizei bufSize,
4228 GLsizei *length,
4229 GLint *params)
4230{
4231 if (!ValidateRobustEntryPoint(context, bufSize))
4232 {
4233 return false;
4234 }
4235
4236 if (!ValidateGetTexParameterBase(context, target, pname, length))
4237 {
4238 return false;
4239 }
4240
4241 if (!ValidateRobustBufferSize(context, bufSize, *length))
4242 {
4243 return false;
4244 }
4245
4246 return true;
4247}
4248
Geoff Langc1984ed2016-10-07 12:41:00 -04004249bool ValidateTexParameterfvRobustANGLE(Context *context,
4250 GLenum target,
4251 GLenum pname,
4252 GLsizei bufSize,
4253 const GLfloat *params)
4254{
4255 if (!ValidateRobustEntryPoint(context, bufSize))
4256 {
4257 return false;
4258 }
4259
4260 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4261}
4262
Geoff Langc1984ed2016-10-07 12:41:00 -04004263bool ValidateTexParameterivRobustANGLE(Context *context,
4264 GLenum target,
4265 GLenum pname,
4266 GLsizei bufSize,
4267 const GLint *params)
4268{
4269 if (!ValidateRobustEntryPoint(context, bufSize))
4270 {
4271 return false;
4272 }
4273
4274 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4275}
4276
Geoff Langc1984ed2016-10-07 12:41:00 -04004277bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4278 GLuint sampler,
4279 GLenum pname,
4280 GLuint bufSize,
4281 GLsizei *length,
4282 GLfloat *params)
4283{
4284 if (!ValidateRobustEntryPoint(context, bufSize))
4285 {
4286 return false;
4287 }
4288
4289 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4290 {
4291 return false;
4292 }
4293
4294 if (!ValidateRobustBufferSize(context, bufSize, *length))
4295 {
4296 return false;
4297 }
4298
4299 return true;
4300}
4301
Geoff Langc1984ed2016-10-07 12:41:00 -04004302bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4303 GLuint sampler,
4304 GLenum pname,
4305 GLuint bufSize,
4306 GLsizei *length,
4307 GLint *params)
4308{
4309 if (!ValidateRobustEntryPoint(context, bufSize))
4310 {
4311 return false;
4312 }
4313
4314 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4315 {
4316 return false;
4317 }
4318
4319 if (!ValidateRobustBufferSize(context, bufSize, *length))
4320 {
4321 return false;
4322 }
4323
4324 return true;
4325}
4326
Geoff Langc1984ed2016-10-07 12:41:00 -04004327bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4328 GLuint sampler,
4329 GLenum pname,
4330 GLsizei bufSize,
4331 const GLfloat *params)
4332{
4333 if (!ValidateRobustEntryPoint(context, bufSize))
4334 {
4335 return false;
4336 }
4337
4338 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4339}
4340
Geoff Langc1984ed2016-10-07 12:41:00 -04004341bool ValidateSamplerParameterivRobustANGLE(Context *context,
4342 GLuint sampler,
4343 GLenum pname,
4344 GLsizei bufSize,
4345 const GLint *params)
4346{
4347 if (!ValidateRobustEntryPoint(context, bufSize))
4348 {
4349 return false;
4350 }
4351
4352 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4353}
4354
Geoff Lang0b031062016-10-13 14:30:04 -04004355bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4356 GLuint index,
4357 GLenum pname,
4358 GLsizei bufSize,
4359 GLsizei *length,
4360 GLfloat *params)
4361{
4362 if (!ValidateRobustEntryPoint(context, bufSize))
4363 {
4364 return false;
4365 }
4366
4367 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4368 {
4369 return false;
4370 }
4371
4372 if (!ValidateRobustBufferSize(context, bufSize, *length))
4373 {
4374 return false;
4375 }
4376
4377 return true;
4378}
4379
Geoff Lang0b031062016-10-13 14:30:04 -04004380bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4381 GLuint index,
4382 GLenum pname,
4383 GLsizei bufSize,
4384 GLsizei *length,
4385 GLint *params)
4386{
4387 if (!ValidateRobustEntryPoint(context, bufSize))
4388 {
4389 return false;
4390 }
4391
4392 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4393 {
4394 return false;
4395 }
4396
4397 if (!ValidateRobustBufferSize(context, bufSize, *length))
4398 {
4399 return false;
4400 }
4401
4402 return true;
4403}
4404
Geoff Lang0b031062016-10-13 14:30:04 -04004405bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4406 GLuint index,
4407 GLenum pname,
4408 GLsizei bufSize,
4409 GLsizei *length,
4410 void **pointer)
4411{
4412 if (!ValidateRobustEntryPoint(context, bufSize))
4413 {
4414 return false;
4415 }
4416
4417 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4418 {
4419 return false;
4420 }
4421
4422 if (!ValidateRobustBufferSize(context, bufSize, *length))
4423 {
4424 return false;
4425 }
4426
4427 return true;
4428}
4429
Geoff Lang0b031062016-10-13 14:30:04 -04004430bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4431 GLuint index,
4432 GLenum pname,
4433 GLsizei bufSize,
4434 GLsizei *length,
4435 GLint *params)
4436{
4437 if (!ValidateRobustEntryPoint(context, bufSize))
4438 {
4439 return false;
4440 }
4441
4442 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4443 {
4444 return false;
4445 }
4446
4447 if (!ValidateRobustBufferSize(context, bufSize, *length))
4448 {
4449 return false;
4450 }
4451
4452 return true;
4453}
4454
Geoff Lang0b031062016-10-13 14:30:04 -04004455bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4456 GLuint index,
4457 GLenum pname,
4458 GLsizei bufSize,
4459 GLsizei *length,
4460 GLuint *params)
4461{
4462 if (!ValidateRobustEntryPoint(context, bufSize))
4463 {
4464 return false;
4465 }
4466
4467 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4468 {
4469 return false;
4470 }
4471
4472 if (!ValidateRobustBufferSize(context, bufSize, *length))
4473 {
4474 return false;
4475 }
4476
4477 return true;
4478}
4479
Geoff Lang6899b872016-10-14 11:30:13 -04004480bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4481 GLuint program,
4482 GLuint uniformBlockIndex,
4483 GLenum pname,
4484 GLsizei bufSize,
4485 GLsizei *length,
4486 GLint *params)
4487{
4488 if (!ValidateRobustEntryPoint(context, bufSize))
4489 {
4490 return false;
4491 }
4492
4493 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4494 {
4495 return false;
4496 }
4497
4498 if (!ValidateRobustBufferSize(context, bufSize, *length))
4499 {
4500 return false;
4501 }
4502
4503 return true;
4504}
4505
Geoff Lang0a9661f2016-10-20 10:59:20 -07004506bool ValidateGetInternalFormativRobustANGLE(Context *context,
4507 GLenum target,
4508 GLenum internalformat,
4509 GLenum pname,
4510 GLsizei bufSize,
4511 GLsizei *length,
4512 GLint *params)
4513{
4514 if (!ValidateRobustEntryPoint(context, bufSize))
4515 {
4516 return false;
4517 }
4518
4519 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4520 {
4521 return false;
4522 }
4523
4524 if (!ValidateRobustBufferSize(context, bufSize, *length))
4525 {
4526 return false;
4527 }
4528
4529 return true;
4530}
4531
Shao80957d92017-02-20 21:25:59 +08004532bool ValidateVertexFormatBase(ValidationContext *context,
4533 GLuint attribIndex,
4534 GLint size,
4535 GLenum type,
4536 GLboolean pureInteger)
4537{
4538 const Caps &caps = context->getCaps();
4539 if (attribIndex >= caps.maxVertexAttributes)
4540 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004541 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004542 return false;
4543 }
4544
4545 if (size < 1 || size > 4)
4546 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004547 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004548 return false;
Shao80957d92017-02-20 21:25:59 +08004549 }
4550
4551 switch (type)
4552 {
4553 case GL_BYTE:
4554 case GL_UNSIGNED_BYTE:
4555 case GL_SHORT:
4556 case GL_UNSIGNED_SHORT:
4557 break;
4558
4559 case GL_INT:
4560 case GL_UNSIGNED_INT:
4561 if (context->getClientMajorVersion() < 3)
4562 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004563 context->handleError(InvalidEnum()
4564 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004565 return false;
4566 }
4567 break;
4568
4569 case GL_FIXED:
4570 case GL_FLOAT:
4571 if (pureInteger)
4572 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004573 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004574 return false;
4575 }
4576 break;
4577
4578 case GL_HALF_FLOAT:
4579 if (context->getClientMajorVersion() < 3)
4580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004581 context->handleError(InvalidEnum()
4582 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004583 return false;
4584 }
4585 if (pureInteger)
4586 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004587 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004588 return false;
4589 }
4590 break;
4591
4592 case GL_INT_2_10_10_10_REV:
4593 case GL_UNSIGNED_INT_2_10_10_10_REV:
4594 if (context->getClientMajorVersion() < 3)
4595 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004596 context->handleError(InvalidEnum()
4597 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004598 return false;
4599 }
4600 if (pureInteger)
4601 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004602 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004603 return false;
4604 }
4605 if (size != 4)
4606 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004607 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4608 "UNSIGNED_INT_2_10_10_10_REV and "
4609 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004610 return false;
4611 }
4612 break;
4613
4614 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004615 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004616 return false;
4617 }
4618
4619 return true;
4620}
4621
Geoff Lang76e65652017-03-27 14:58:02 -04004622// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4623// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4624// specified clear value and the type of a buffer that is being cleared generates an
4625// INVALID_OPERATION error instead of producing undefined results
4626bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4627 GLint drawbuffer,
4628 const GLenum *validComponentTypes,
4629 size_t validComponentTypeCount)
4630{
4631 const FramebufferAttachment *attachment =
4632 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4633 if (attachment)
4634 {
4635 GLenum componentType = attachment->getFormat().info->componentType;
4636 const GLenum *end = validComponentTypes + validComponentTypeCount;
4637 if (std::find(validComponentTypes, end, componentType) == end)
4638 {
4639 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004640 InvalidOperation()
4641 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004642 return false;
4643 }
4644 }
4645
4646 return true;
4647}
4648
Corentin Wallezb2931602017-04-11 15:58:57 -04004649bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4650 GLsizei imageSize,
4651 GLsizei dataSize)
4652{
4653 if (!ValidateRobustEntryPoint(context, dataSize))
4654 {
4655 return false;
4656 }
4657
Corentin Wallez336129f2017-10-17 15:55:40 -04004658 gl::Buffer *pixelUnpackBuffer =
4659 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004660 if (pixelUnpackBuffer == nullptr)
4661 {
4662 if (dataSize < imageSize)
4663 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004664 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004665 }
4666 }
4667 return true;
4668}
4669
Jamie Madillbe849e42017-05-02 15:49:00 -04004670bool ValidateGetBufferParameterBase(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004671 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004672 GLenum pname,
4673 bool pointerVersion,
4674 GLsizei *numParams)
4675{
4676 if (numParams)
4677 {
4678 *numParams = 0;
4679 }
4680
Corentin Walleze4477002017-12-01 14:39:58 -05004681 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004682 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004683 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004684 return false;
4685 }
4686
4687 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4688 if (!buffer)
4689 {
4690 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004691 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004692 return false;
4693 }
4694
4695 const Extensions &extensions = context->getExtensions();
4696
4697 switch (pname)
4698 {
4699 case GL_BUFFER_USAGE:
4700 case GL_BUFFER_SIZE:
4701 break;
4702
4703 case GL_BUFFER_ACCESS_OES:
4704 if (!extensions.mapBuffer)
4705 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004706 context->handleError(InvalidEnum()
4707 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004708 return false;
4709 }
4710 break;
4711
4712 case GL_BUFFER_MAPPED:
4713 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4714 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4715 !extensions.mapBufferRange)
4716 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004717 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4718 "GL_OES_mapbuffer or "
4719 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004720 return false;
4721 }
4722 break;
4723
4724 case GL_BUFFER_MAP_POINTER:
4725 if (!pointerVersion)
4726 {
4727 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004728 InvalidEnum()
4729 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004730 return false;
4731 }
4732 break;
4733
4734 case GL_BUFFER_ACCESS_FLAGS:
4735 case GL_BUFFER_MAP_OFFSET:
4736 case GL_BUFFER_MAP_LENGTH:
4737 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4738 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004739 context->handleError(InvalidEnum()
4740 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004741 return false;
4742 }
4743 break;
4744
4745 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004746 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004747 return false;
4748 }
4749
4750 // All buffer parameter queries return one value.
4751 if (numParams)
4752 {
4753 *numParams = 1;
4754 }
4755
4756 return true;
4757}
4758
4759bool ValidateGetRenderbufferParameterivBase(Context *context,
4760 GLenum target,
4761 GLenum pname,
4762 GLsizei *length)
4763{
4764 if (length)
4765 {
4766 *length = 0;
4767 }
4768
4769 if (target != GL_RENDERBUFFER)
4770 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004771 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004772 return false;
4773 }
4774
4775 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4776 if (renderbuffer == nullptr)
4777 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004778 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004779 return false;
4780 }
4781
4782 switch (pname)
4783 {
4784 case GL_RENDERBUFFER_WIDTH:
4785 case GL_RENDERBUFFER_HEIGHT:
4786 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4787 case GL_RENDERBUFFER_RED_SIZE:
4788 case GL_RENDERBUFFER_GREEN_SIZE:
4789 case GL_RENDERBUFFER_BLUE_SIZE:
4790 case GL_RENDERBUFFER_ALPHA_SIZE:
4791 case GL_RENDERBUFFER_DEPTH_SIZE:
4792 case GL_RENDERBUFFER_STENCIL_SIZE:
4793 break;
4794
4795 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4796 if (!context->getExtensions().framebufferMultisample)
4797 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004798 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004799 return false;
4800 }
4801 break;
4802
4803 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004804 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004805 return false;
4806 }
4807
4808 if (length)
4809 {
4810 *length = 1;
4811 }
4812 return true;
4813}
4814
4815bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4816{
4817 if (length)
4818 {
4819 *length = 0;
4820 }
4821
4822 if (GetValidShader(context, shader) == nullptr)
4823 {
4824 return false;
4825 }
4826
4827 switch (pname)
4828 {
4829 case GL_SHADER_TYPE:
4830 case GL_DELETE_STATUS:
4831 case GL_COMPILE_STATUS:
4832 case GL_INFO_LOG_LENGTH:
4833 case GL_SHADER_SOURCE_LENGTH:
4834 break;
4835
4836 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4837 if (!context->getExtensions().translatedShaderSource)
4838 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004839 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004840 return false;
4841 }
4842 break;
4843
4844 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004845 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004846 return false;
4847 }
4848
4849 if (length)
4850 {
4851 *length = 1;
4852 }
4853 return true;
4854}
4855
4856bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4857{
4858 if (length)
4859 {
4860 *length = 0;
4861 }
4862
4863 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4864 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004865 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004866 return false;
4867 }
4868
4869 if (context->getTargetTexture(target) == nullptr)
4870 {
4871 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004872 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004873 return false;
4874 }
4875
4876 switch (pname)
4877 {
4878 case GL_TEXTURE_MAG_FILTER:
4879 case GL_TEXTURE_MIN_FILTER:
4880 case GL_TEXTURE_WRAP_S:
4881 case GL_TEXTURE_WRAP_T:
4882 break;
4883
4884 case GL_TEXTURE_USAGE_ANGLE:
4885 if (!context->getExtensions().textureUsage)
4886 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004887 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004888 return false;
4889 }
4890 break;
4891
4892 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4893 if (!context->getExtensions().textureFilterAnisotropic)
4894 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004895 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004896 return false;
4897 }
4898 break;
4899
4900 case GL_TEXTURE_IMMUTABLE_FORMAT:
4901 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4902 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004903 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004904 return false;
4905 }
4906 break;
4907
4908 case GL_TEXTURE_WRAP_R:
4909 case GL_TEXTURE_IMMUTABLE_LEVELS:
4910 case GL_TEXTURE_SWIZZLE_R:
4911 case GL_TEXTURE_SWIZZLE_G:
4912 case GL_TEXTURE_SWIZZLE_B:
4913 case GL_TEXTURE_SWIZZLE_A:
4914 case GL_TEXTURE_BASE_LEVEL:
4915 case GL_TEXTURE_MAX_LEVEL:
4916 case GL_TEXTURE_MIN_LOD:
4917 case GL_TEXTURE_MAX_LOD:
4918 case GL_TEXTURE_COMPARE_MODE:
4919 case GL_TEXTURE_COMPARE_FUNC:
4920 if (context->getClientMajorVersion() < 3)
4921 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004922 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004923 return false;
4924 }
4925 break;
4926
4927 case GL_TEXTURE_SRGB_DECODE_EXT:
4928 if (!context->getExtensions().textureSRGBDecode)
4929 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004930 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004931 return false;
4932 }
4933 break;
4934
4935 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004936 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004937 return false;
4938 }
4939
4940 if (length)
4941 {
4942 *length = 1;
4943 }
4944 return true;
4945}
4946
4947bool ValidateGetVertexAttribBase(Context *context,
4948 GLuint index,
4949 GLenum pname,
4950 GLsizei *length,
4951 bool pointer,
4952 bool pureIntegerEntryPoint)
4953{
4954 if (length)
4955 {
4956 *length = 0;
4957 }
4958
4959 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
4960 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004961 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004962 return false;
4963 }
4964
4965 if (index >= context->getCaps().maxVertexAttributes)
4966 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004967 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04004968 return false;
4969 }
4970
4971 if (pointer)
4972 {
4973 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
4974 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004975 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004976 return false;
4977 }
4978 }
4979 else
4980 {
4981 switch (pname)
4982 {
4983 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4984 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4985 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4986 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4987 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4988 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
4989 case GL_CURRENT_VERTEX_ATTRIB:
4990 break;
4991
4992 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
4993 static_assert(
4994 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
4995 "ANGLE extension enums not equal to GL enums.");
4996 if (context->getClientMajorVersion() < 3 &&
4997 !context->getExtensions().instancedArrays)
4998 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004999 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5000 "requires OpenGL ES 3.0 or "
5001 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005002 return false;
5003 }
5004 break;
5005
5006 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5007 if (context->getClientMajorVersion() < 3)
5008 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005009 context->handleError(
5010 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005011 return false;
5012 }
5013 break;
5014
5015 case GL_VERTEX_ATTRIB_BINDING:
5016 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5017 if (context->getClientVersion() < ES_3_1)
5018 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005019 context->handleError(InvalidEnum()
5020 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005021 return false;
5022 }
5023 break;
5024
5025 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005026 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005027 return false;
5028 }
5029 }
5030
5031 if (length)
5032 {
5033 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5034 {
5035 *length = 4;
5036 }
5037 else
5038 {
5039 *length = 1;
5040 }
5041 }
5042
5043 return true;
5044}
5045
Jamie Madill4928b7c2017-06-20 12:57:39 -04005046bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005047 GLint x,
5048 GLint y,
5049 GLsizei width,
5050 GLsizei height,
5051 GLenum format,
5052 GLenum type,
5053 GLsizei bufSize,
5054 GLsizei *length,
5055 GLsizei *columns,
5056 GLsizei *rows,
5057 void *pixels)
5058{
5059 if (length != nullptr)
5060 {
5061 *length = 0;
5062 }
5063 if (rows != nullptr)
5064 {
5065 *rows = 0;
5066 }
5067 if (columns != nullptr)
5068 {
5069 *columns = 0;
5070 }
5071
5072 if (width < 0 || height < 0)
5073 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005074 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005075 return false;
5076 }
5077
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005078 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005079
5080 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5081 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005082 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005083 return false;
5084 }
5085
5086 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5087 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005088 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005089 return false;
5090 }
5091
5092 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5093 ASSERT(framebuffer);
5094
5095 if (framebuffer->getReadBufferState() == GL_NONE)
5096 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005097 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005098 return false;
5099 }
5100
5101 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5102 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5103 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5104 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5105 // situation is an application error that would lead to a crash in ANGLE.
5106 if (readBuffer == nullptr)
5107 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005108 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005109 return false;
5110 }
5111
Martin Radev28031682017-07-28 14:47:56 +03005112 // ANGLE_multiview, Revision 1:
5113 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5114 // current read framebuffer is not NONE.
5115 if (readBuffer->getMultiviewLayout() != GL_NONE)
5116 {
5117 context->handleError(InvalidFramebufferOperation()
5118 << "Attempting to read from a multi-view framebuffer.");
5119 return false;
5120 }
5121
Geoff Lang280ba992017-04-18 16:30:58 -04005122 if (context->getExtensions().webglCompatibility)
5123 {
5124 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5125 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5126 // and type before validating the combination of format and type. However, the
5127 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5128 // verifies that GL_INVALID_OPERATION is generated.
5129 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5130 // dEQP/WebGL.
5131 if (!ValidReadPixelsFormatEnum(context, format))
5132 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005133 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005134 return false;
5135 }
5136
5137 if (!ValidReadPixelsTypeEnum(context, type))
5138 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005139 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005140 return false;
5141 }
5142 }
5143
Jamie Madill4928b7c2017-06-20 12:57:39 -04005144 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5145 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005146 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5147
5148 bool validFormatTypeCombination =
5149 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5150
5151 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5152 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005153 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005154 return false;
5155 }
5156
5157 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005158 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005159 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5160 {
5161 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005162 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005163 return false;
5164 }
5165
5166 // .. the data would be packed to the buffer object such that the memory writes required
5167 // would exceed the data store size.
5168 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5169 const gl::Extents size(width, height, 1);
5170 const auto &pack = context->getGLState().getPackState();
5171
5172 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5173 if (endByteOrErr.isError())
5174 {
5175 context->handleError(endByteOrErr.getError());
5176 return false;
5177 }
5178
5179 size_t endByte = endByteOrErr.getResult();
5180 if (bufSize >= 0)
5181 {
5182 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5183 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005184 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005185 return false;
5186 }
5187 }
5188
5189 if (pixelPackBuffer != nullptr)
5190 {
5191 CheckedNumeric<size_t> checkedEndByte(endByte);
5192 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5193 checkedEndByte += checkedOffset;
5194
5195 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5196 {
5197 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005198 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005199 return false;
5200 }
5201 }
5202
5203 if (pixelPackBuffer == nullptr && length != nullptr)
5204 {
5205 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5206 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005207 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005208 return false;
5209 }
5210
5211 *length = static_cast<GLsizei>(endByte);
5212 }
5213
5214 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5215 angle::CheckedNumeric<int> clippedExtent(length);
5216 if (start < 0)
5217 {
5218 // "subtract" the area that is less than 0
5219 clippedExtent += start;
5220 }
5221
5222 const int readExtent = start + length;
5223 if (readExtent > bufferSize)
5224 {
5225 // Subtract the region to the right of the read buffer
5226 clippedExtent -= (readExtent - bufferSize);
5227 }
5228
5229 if (!clippedExtent.IsValid())
5230 {
5231 return 0;
5232 }
5233
5234 return std::max(clippedExtent.ValueOrDie(), 0);
5235 };
5236
5237 if (columns != nullptr)
5238 {
5239 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5240 }
5241
5242 if (rows != nullptr)
5243 {
5244 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5245 }
5246
5247 return true;
5248}
5249
5250template <typename ParamType>
5251bool ValidateTexParameterBase(Context *context,
5252 GLenum target,
5253 GLenum pname,
5254 GLsizei bufSize,
5255 const ParamType *params)
5256{
5257 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5258 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005259 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005260 return false;
5261 }
5262
5263 if (context->getTargetTexture(target) == nullptr)
5264 {
5265 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005266 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005267 return false;
5268 }
5269
5270 const GLsizei minBufSize = 1;
5271 if (bufSize >= 0 && bufSize < minBufSize)
5272 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005273 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005274 return false;
5275 }
5276
5277 switch (pname)
5278 {
5279 case GL_TEXTURE_WRAP_R:
5280 case GL_TEXTURE_SWIZZLE_R:
5281 case GL_TEXTURE_SWIZZLE_G:
5282 case GL_TEXTURE_SWIZZLE_B:
5283 case GL_TEXTURE_SWIZZLE_A:
5284 case GL_TEXTURE_BASE_LEVEL:
5285 case GL_TEXTURE_MAX_LEVEL:
5286 case GL_TEXTURE_COMPARE_MODE:
5287 case GL_TEXTURE_COMPARE_FUNC:
5288 case GL_TEXTURE_MIN_LOD:
5289 case GL_TEXTURE_MAX_LOD:
5290 if (context->getClientMajorVersion() < 3)
5291 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005292 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005293 return false;
5294 }
5295 if (target == GL_TEXTURE_EXTERNAL_OES &&
5296 !context->getExtensions().eglImageExternalEssl3)
5297 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005298 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5299 "available without "
5300 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005301 return false;
5302 }
5303 break;
5304
5305 default:
5306 break;
5307 }
5308
JiangYizhou4cff8d62017-07-06 14:54:09 +08005309 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5310 {
5311 switch (pname)
5312 {
5313 case GL_TEXTURE_MIN_FILTER:
5314 case GL_TEXTURE_MAG_FILTER:
5315 case GL_TEXTURE_WRAP_S:
5316 case GL_TEXTURE_WRAP_T:
5317 case GL_TEXTURE_WRAP_R:
5318 case GL_TEXTURE_MIN_LOD:
5319 case GL_TEXTURE_MAX_LOD:
5320 case GL_TEXTURE_COMPARE_MODE:
5321 case GL_TEXTURE_COMPARE_FUNC:
5322 context->handleError(InvalidEnum()
5323 << "Invalid parameter for 2D multisampled textures.");
5324 return false;
5325 }
5326 }
5327
Jamie Madillbe849e42017-05-02 15:49:00 -04005328 switch (pname)
5329 {
5330 case GL_TEXTURE_WRAP_S:
5331 case GL_TEXTURE_WRAP_T:
5332 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005333 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005334 bool restrictedWrapModes =
5335 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5336 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5337 {
5338 return false;
5339 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005340 }
5341 break;
5342
5343 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005344 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005345 bool restrictedMinFilter =
5346 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5347 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5348 {
5349 return false;
5350 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005351 }
5352 break;
5353
5354 case GL_TEXTURE_MAG_FILTER:
5355 if (!ValidateTextureMagFilterValue(context, params))
5356 {
5357 return false;
5358 }
5359 break;
5360
5361 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005362 if (!context->getExtensions().textureUsage)
5363 {
5364 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5365 return false;
5366 }
5367
Jamie Madillbe849e42017-05-02 15:49:00 -04005368 switch (ConvertToGLenum(params[0]))
5369 {
5370 case GL_NONE:
5371 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5372 break;
5373
5374 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005375 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005376 return false;
5377 }
5378 break;
5379
5380 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5381 if (!context->getExtensions().textureFilterAnisotropic)
5382 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005383 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005384 return false;
5385 }
5386
5387 // we assume the parameter passed to this validation method is truncated, not rounded
5388 if (params[0] < 1)
5389 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005390 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005391 return false;
5392 }
5393 break;
5394
5395 case GL_TEXTURE_MIN_LOD:
5396 case GL_TEXTURE_MAX_LOD:
5397 // any value is permissible
5398 break;
5399
5400 case GL_TEXTURE_COMPARE_MODE:
5401 if (!ValidateTextureCompareModeValue(context, params))
5402 {
5403 return false;
5404 }
5405 break;
5406
5407 case GL_TEXTURE_COMPARE_FUNC:
5408 if (!ValidateTextureCompareFuncValue(context, params))
5409 {
5410 return false;
5411 }
5412 break;
5413
5414 case GL_TEXTURE_SWIZZLE_R:
5415 case GL_TEXTURE_SWIZZLE_G:
5416 case GL_TEXTURE_SWIZZLE_B:
5417 case GL_TEXTURE_SWIZZLE_A:
5418 switch (ConvertToGLenum(params[0]))
5419 {
5420 case GL_RED:
5421 case GL_GREEN:
5422 case GL_BLUE:
5423 case GL_ALPHA:
5424 case GL_ZERO:
5425 case GL_ONE:
5426 break;
5427
5428 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005429 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005430 return false;
5431 }
5432 break;
5433
5434 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005435 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005436 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005437 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005438 return false;
5439 }
5440 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5441 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005442 context->handleError(InvalidOperation()
5443 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005444 return false;
5445 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005446 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5447 {
5448 context->handleError(InvalidOperation()
5449 << "Base level must be 0 for multisampled textures.");
5450 return false;
5451 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005452 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5453 {
5454 context->handleError(InvalidOperation()
5455 << "Base level must be 0 for rectangle textures.");
5456 return false;
5457 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005458 break;
5459
5460 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005461 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005462 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005463 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005464 return false;
5465 }
5466 break;
5467
5468 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5469 if (context->getClientVersion() < Version(3, 1))
5470 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005471 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005472 return false;
5473 }
5474 switch (ConvertToGLenum(params[0]))
5475 {
5476 case GL_DEPTH_COMPONENT:
5477 case GL_STENCIL_INDEX:
5478 break;
5479
5480 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005481 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005482 return false;
5483 }
5484 break;
5485
5486 case GL_TEXTURE_SRGB_DECODE_EXT:
5487 if (!ValidateTextureSRGBDecodeValue(context, params))
5488 {
5489 return false;
5490 }
5491 break;
5492
5493 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005494 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005495 return false;
5496 }
5497
5498 return true;
5499}
5500
5501template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5502template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5503
Jamie Madill12e957f2017-08-26 21:42:26 -04005504bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5505{
5506 if (index >= MAX_VERTEX_ATTRIBS)
5507 {
5508 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5509 return false;
5510 }
5511
5512 return true;
5513}
5514
5515bool ValidateGetActiveUniformBlockivBase(Context *context,
5516 GLuint program,
5517 GLuint uniformBlockIndex,
5518 GLenum pname,
5519 GLsizei *length)
5520{
5521 if (length)
5522 {
5523 *length = 0;
5524 }
5525
5526 if (context->getClientMajorVersion() < 3)
5527 {
5528 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5529 return false;
5530 }
5531
5532 Program *programObject = GetValidProgram(context, program);
5533 if (!programObject)
5534 {
5535 return false;
5536 }
5537
5538 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5539 {
5540 context->handleError(InvalidValue()
5541 << "uniformBlockIndex exceeds active uniform block count.");
5542 return false;
5543 }
5544
5545 switch (pname)
5546 {
5547 case GL_UNIFORM_BLOCK_BINDING:
5548 case GL_UNIFORM_BLOCK_DATA_SIZE:
5549 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5550 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5551 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5552 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5553 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5554 break;
5555
5556 default:
5557 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5558 return false;
5559 }
5560
5561 if (length)
5562 {
5563 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5564 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005565 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005566 programObject->getUniformBlockByIndex(uniformBlockIndex);
5567 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5568 }
5569 else
5570 {
5571 *length = 1;
5572 }
5573 }
5574
5575 return true;
5576}
5577
Jamie Madill9696d072017-08-26 23:19:57 -04005578template <typename ParamType>
5579bool ValidateSamplerParameterBase(Context *context,
5580 GLuint sampler,
5581 GLenum pname,
5582 GLsizei bufSize,
5583 ParamType *params)
5584{
5585 if (context->getClientMajorVersion() < 3)
5586 {
5587 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5588 return false;
5589 }
5590
5591 if (!context->isSampler(sampler))
5592 {
5593 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5594 return false;
5595 }
5596
5597 const GLsizei minBufSize = 1;
5598 if (bufSize >= 0 && bufSize < minBufSize)
5599 {
5600 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5601 return false;
5602 }
5603
5604 switch (pname)
5605 {
5606 case GL_TEXTURE_WRAP_S:
5607 case GL_TEXTURE_WRAP_T:
5608 case GL_TEXTURE_WRAP_R:
5609 if (!ValidateTextureWrapModeValue(context, params, false))
5610 {
5611 return false;
5612 }
5613 break;
5614
5615 case GL_TEXTURE_MIN_FILTER:
5616 if (!ValidateTextureMinFilterValue(context, params, false))
5617 {
5618 return false;
5619 }
5620 break;
5621
5622 case GL_TEXTURE_MAG_FILTER:
5623 if (!ValidateTextureMagFilterValue(context, params))
5624 {
5625 return false;
5626 }
5627 break;
5628
5629 case GL_TEXTURE_MIN_LOD:
5630 case GL_TEXTURE_MAX_LOD:
5631 // any value is permissible
5632 break;
5633
5634 case GL_TEXTURE_COMPARE_MODE:
5635 if (!ValidateTextureCompareModeValue(context, params))
5636 {
5637 return false;
5638 }
5639 break;
5640
5641 case GL_TEXTURE_COMPARE_FUNC:
5642 if (!ValidateTextureCompareFuncValue(context, params))
5643 {
5644 return false;
5645 }
5646 break;
5647
5648 case GL_TEXTURE_SRGB_DECODE_EXT:
5649 if (!ValidateTextureSRGBDecodeValue(context, params))
5650 {
5651 return false;
5652 }
5653 break;
5654
5655 default:
5656 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5657 return false;
5658 }
5659
5660 return true;
5661}
5662
5663template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5664template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5665
5666bool ValidateGetSamplerParameterBase(Context *context,
5667 GLuint sampler,
5668 GLenum pname,
5669 GLsizei *length)
5670{
5671 if (length)
5672 {
5673 *length = 0;
5674 }
5675
5676 if (context->getClientMajorVersion() < 3)
5677 {
5678 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5679 return false;
5680 }
5681
5682 if (!context->isSampler(sampler))
5683 {
5684 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5685 return false;
5686 }
5687
5688 switch (pname)
5689 {
5690 case GL_TEXTURE_WRAP_S:
5691 case GL_TEXTURE_WRAP_T:
5692 case GL_TEXTURE_WRAP_R:
5693 case GL_TEXTURE_MIN_FILTER:
5694 case GL_TEXTURE_MAG_FILTER:
5695 case GL_TEXTURE_MIN_LOD:
5696 case GL_TEXTURE_MAX_LOD:
5697 case GL_TEXTURE_COMPARE_MODE:
5698 case GL_TEXTURE_COMPARE_FUNC:
5699 break;
5700
5701 case GL_TEXTURE_SRGB_DECODE_EXT:
5702 if (!context->getExtensions().textureSRGBDecode)
5703 {
5704 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5705 return false;
5706 }
5707 break;
5708
5709 default:
5710 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5711 return false;
5712 }
5713
5714 if (length)
5715 {
5716 *length = 1;
5717 }
5718 return true;
5719}
5720
5721bool ValidateGetInternalFormativBase(Context *context,
5722 GLenum target,
5723 GLenum internalformat,
5724 GLenum pname,
5725 GLsizei bufSize,
5726 GLsizei *numParams)
5727{
5728 if (numParams)
5729 {
5730 *numParams = 0;
5731 }
5732
5733 if (context->getClientMajorVersion() < 3)
5734 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005735 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005736 return false;
5737 }
5738
5739 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5740 if (!formatCaps.renderable)
5741 {
5742 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5743 return false;
5744 }
5745
5746 switch (target)
5747 {
5748 case GL_RENDERBUFFER:
5749 break;
5750
5751 case GL_TEXTURE_2D_MULTISAMPLE:
5752 if (context->getClientVersion() < ES_3_1)
5753 {
5754 context->handleError(InvalidOperation()
5755 << "Texture target requires at least OpenGL ES 3.1.");
5756 return false;
5757 }
5758 break;
5759
5760 default:
5761 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5762 return false;
5763 }
5764
5765 if (bufSize < 0)
5766 {
5767 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5768 return false;
5769 }
5770
5771 GLsizei maxWriteParams = 0;
5772 switch (pname)
5773 {
5774 case GL_NUM_SAMPLE_COUNTS:
5775 maxWriteParams = 1;
5776 break;
5777
5778 case GL_SAMPLES:
5779 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5780 break;
5781
5782 default:
5783 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5784 return false;
5785 }
5786
5787 if (numParams)
5788 {
5789 // glGetInternalFormativ will not overflow bufSize
5790 *numParams = std::min(bufSize, maxWriteParams);
5791 }
5792
5793 return true;
5794}
5795
Jamie Madillc29968b2016-01-20 11:17:23 -05005796} // namespace gl