blob: 6b9b390ab76b7766c4783e0ceb6850386dfb7c18 [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"
Jamie Madill231c7f52017-04-26 13:45:37 -040021#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050022#include "libANGLE/VertexArray.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040023#include "libANGLE/formatutils.h"
24#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{
Corentin Wallez92db6942016-12-09 13:10:36 -050036bool ValidateDrawAttribs(ValidationContext *context,
37 GLint primcount,
38 GLint maxVertex,
39 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040040{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070041 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040042 const gl::Program *program = state.getProgram();
43
Corentin Wallez327411e2016-12-09 11:09:17 -050044 bool webglCompatibility = context->getExtensions().webglCompatibility;
45
Jamie Madill231c7f52017-04-26 13:45:37 -040046 const VertexArray *vao = state.getVertexArray();
47 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080048 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madill231c7f52017-04-26 13:45:37 -040049 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040050 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
51 {
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:
179 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat;
180
181 case GL_HALF_FLOAT:
182 return context->getClientVersion() >= ES_3_0 ||
183 context->getExtensions().textureHalfFloat;
184
185 case GL_HALF_FLOAT_OES:
186 return context->getExtensions().colorBufferHalfFloat;
187
188 default:
189 return false;
190 }
191}
192
193bool ValidReadPixelsFormatEnum(ValidationContext *context, GLenum format)
194{
195 switch (format)
196 {
197 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
198 case GL_RGBA:
199 case GL_RGB:
200 case GL_ALPHA:
201 return context->getClientVersion() >= ES_2_0;
202
203 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
204 case GL_RG:
205 case GL_RED:
206 case GL_RGBA_INTEGER:
207 case GL_RGB_INTEGER:
208 case GL_RG_INTEGER:
209 case GL_RED_INTEGER:
210 return context->getClientVersion() >= ES_3_0;
211
212 case GL_SRGB_ALPHA_EXT:
213 case GL_SRGB_EXT:
214 return context->getExtensions().sRGB;
215
216 case GL_BGRA_EXT:
217 return context->getExtensions().readFormatBGRA;
218
219 default:
220 return false;
221 }
222}
223
Geoff Langf607c602016-09-21 11:46:48 -0400224bool ValidReadPixelsFormatType(ValidationContext *context,
225 GLenum framebufferComponentType,
226 GLenum format,
227 GLenum type)
228{
229 switch (framebufferComponentType)
230 {
231 case GL_UNSIGNED_NORMALIZED:
232 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
233 // ReadPixels with BGRA even if the extension is not present
234 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
235 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
236 type == GL_UNSIGNED_BYTE);
237
238 case GL_SIGNED_NORMALIZED:
239 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
240
241 case GL_INT:
242 return (format == GL_RGBA_INTEGER && type == GL_INT);
243
244 case GL_UNSIGNED_INT:
245 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
246
247 case GL_FLOAT:
248 return (format == GL_RGBA && type == GL_FLOAT);
249
250 default:
251 UNREACHABLE();
252 return false;
253 }
254}
255
Geoff Langc1984ed2016-10-07 12:41:00 -0400256template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400257bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400258{
259 switch (ConvertToGLenum(params[0]))
260 {
261 case GL_CLAMP_TO_EDGE:
262 break;
263
264 case GL_REPEAT:
265 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400266 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400267 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400268 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700269 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400270 return false;
271 }
272 break;
273
274 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700275 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400276 return false;
277 }
278
279 return true;
280}
281
282template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400283bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400284{
285 switch (ConvertToGLenum(params[0]))
286 {
287 case GL_NEAREST:
288 case GL_LINEAR:
289 break;
290
291 case GL_NEAREST_MIPMAP_NEAREST:
292 case GL_LINEAR_MIPMAP_NEAREST:
293 case GL_NEAREST_MIPMAP_LINEAR:
294 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400295 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400296 {
297 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700298 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400299 return false;
300 }
301 break;
302
303 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700304 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400305 return false;
306 }
307
308 return true;
309}
310
311template <typename ParamType>
312bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
313{
314 switch (ConvertToGLenum(params[0]))
315 {
316 case GL_NEAREST:
317 case GL_LINEAR:
318 break;
319
320 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700321 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400322 return false;
323 }
324
325 return true;
326}
327
328template <typename ParamType>
329bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
330{
331 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
332 switch (ConvertToGLenum(params[0]))
333 {
334 case GL_NONE:
335 case GL_COMPARE_REF_TO_TEXTURE:
336 break;
337
338 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700339 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400340 return false;
341 }
342
343 return true;
344}
345
346template <typename ParamType>
347bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
348{
349 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
350 switch (ConvertToGLenum(params[0]))
351 {
352 case GL_LEQUAL:
353 case GL_GEQUAL:
354 case GL_LESS:
355 case GL_GREATER:
356 case GL_EQUAL:
357 case GL_NOTEQUAL:
358 case GL_ALWAYS:
359 case GL_NEVER:
360 break;
361
362 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700363 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400364 return false;
365 }
366
367 return true;
368}
369
370template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700371bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
372{
373 if (!context->getExtensions().textureSRGBDecode)
374 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700375 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700376 return false;
377 }
378
379 switch (ConvertToGLenum(params[0]))
380 {
381 case GL_DECODE_EXT:
382 case GL_SKIP_DECODE_EXT:
383 break;
384
385 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700386 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700387 return false;
388 }
389
390 return true;
391}
392
393template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400394bool ValidateSamplerParameterBase(Context *context,
395 GLuint sampler,
396 GLenum pname,
397 GLsizei bufSize,
398 ParamType *params)
399{
400 if (context->getClientMajorVersion() < 3)
401 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700402 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc1984ed2016-10-07 12:41:00 -0400403 return false;
404 }
405
406 if (!context->isSampler(sampler))
407 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700408 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
Geoff Langc1984ed2016-10-07 12:41:00 -0400409 return false;
410 }
411
412 const GLsizei minBufSize = 1;
413 if (bufSize >= 0 && bufSize < minBufSize)
414 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700415 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langc1984ed2016-10-07 12:41:00 -0400416 return false;
417 }
418
419 switch (pname)
420 {
421 case GL_TEXTURE_WRAP_S:
422 case GL_TEXTURE_WRAP_T:
423 case GL_TEXTURE_WRAP_R:
424 if (!ValidateTextureWrapModeValue(context, params, false))
425 {
426 return false;
427 }
428 break;
429
430 case GL_TEXTURE_MIN_FILTER:
431 if (!ValidateTextureMinFilterValue(context, params, false))
432 {
433 return false;
434 }
435 break;
436
437 case GL_TEXTURE_MAG_FILTER:
438 if (!ValidateTextureMagFilterValue(context, params))
439 {
440 return false;
441 }
442 break;
443
444 case GL_TEXTURE_MIN_LOD:
445 case GL_TEXTURE_MAX_LOD:
446 // any value is permissible
447 break;
448
449 case GL_TEXTURE_COMPARE_MODE:
450 if (!ValidateTextureCompareModeValue(context, params))
451 {
452 return false;
453 }
454 break;
455
456 case GL_TEXTURE_COMPARE_FUNC:
457 if (!ValidateTextureCompareFuncValue(context, params))
458 {
459 return false;
460 }
461 break;
462
Geoff Lang81c6b572016-10-19 14:07:52 -0700463 case GL_TEXTURE_SRGB_DECODE_EXT:
464 if (!ValidateTextureSRGBDecodeValue(context, params))
465 {
466 return false;
467 }
468 break;
469
Geoff Langc1984ed2016-10-07 12:41:00 -0400470 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700471 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langc1984ed2016-10-07 12:41:00 -0400472 return false;
473 }
474
475 return true;
476}
477
478bool ValidateGetSamplerParameterBase(Context *context,
479 GLuint sampler,
480 GLenum pname,
481 GLsizei *length)
482{
483 if (length)
484 {
485 *length = 0;
486 }
487
488 if (context->getClientMajorVersion() < 3)
489 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700490 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc1984ed2016-10-07 12:41:00 -0400491 return false;
492 }
493
494 if (!context->isSampler(sampler))
495 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700496 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
Geoff Langc1984ed2016-10-07 12:41:00 -0400497 return false;
498 }
499
500 switch (pname)
501 {
502 case GL_TEXTURE_WRAP_S:
503 case GL_TEXTURE_WRAP_T:
504 case GL_TEXTURE_WRAP_R:
505 case GL_TEXTURE_MIN_FILTER:
506 case GL_TEXTURE_MAG_FILTER:
507 case GL_TEXTURE_MIN_LOD:
508 case GL_TEXTURE_MAX_LOD:
509 case GL_TEXTURE_COMPARE_MODE:
510 case GL_TEXTURE_COMPARE_FUNC:
511 break;
512
Geoff Lang81c6b572016-10-19 14:07:52 -0700513 case GL_TEXTURE_SRGB_DECODE_EXT:
514 if (!context->getExtensions().textureSRGBDecode)
515 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500516 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Geoff Lang81c6b572016-10-19 14:07:52 -0700517 return false;
518 }
519 break;
520
Geoff Langc1984ed2016-10-07 12:41:00 -0400521 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700522 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langc1984ed2016-10-07 12:41:00 -0400523 return false;
524 }
525
526 if (length)
527 {
528 *length = 1;
529 }
530 return true;
531}
532
Geoff Lang6899b872016-10-14 11:30:13 -0400533bool ValidateGetActiveUniformBlockivBase(Context *context,
534 GLuint program,
535 GLuint uniformBlockIndex,
536 GLenum pname,
537 GLsizei *length)
538{
539 if (length)
540 {
541 *length = 0;
542 }
543
544 if (context->getClientMajorVersion() < 3)
545 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500546 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Lang6899b872016-10-14 11:30:13 -0400547 return false;
548 }
549
550 Program *programObject = GetValidProgram(context, program);
551 if (!programObject)
552 {
553 return false;
554 }
555
556 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
557 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500558 context->handleError(InvalidValue()
559 << "uniformBlockIndex exceeds active uniform block count.");
Geoff Lang6899b872016-10-14 11:30:13 -0400560 return false;
561 }
562
563 switch (pname)
564 {
565 case GL_UNIFORM_BLOCK_BINDING:
566 case GL_UNIFORM_BLOCK_DATA_SIZE:
567 case GL_UNIFORM_BLOCK_NAME_LENGTH:
568 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
569 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
570 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
571 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
572 break;
573
574 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700575 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang6899b872016-10-14 11:30:13 -0400576 return false;
577 }
578
579 if (length)
580 {
581 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
582 {
583 const UniformBlock &uniformBlock =
584 programObject->getUniformBlockByIndex(uniformBlockIndex);
jchen10eaef1e52017-06-13 10:44:11 +0800585 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
Geoff Lang6899b872016-10-14 11:30:13 -0400586 }
587 else
588 {
589 *length = 1;
590 }
591 }
592
593 return true;
594}
595
Geoff Lang0a9661f2016-10-20 10:59:20 -0700596bool ValidateGetInternalFormativBase(Context *context,
597 GLenum target,
598 GLenum internalformat,
599 GLenum pname,
600 GLsizei bufSize,
601 GLsizei *numParams)
602{
603 if (numParams)
604 {
605 *numParams = 0;
606 }
607
608 if (context->getClientMajorVersion() < 3)
609 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500610 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700611 return false;
612 }
613
614 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
615 if (!formatCaps.renderable)
616 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500617 context->handleError(InvalidEnum() << "Internal format is not renderable.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700618 return false;
619 }
620
621 switch (target)
622 {
623 case GL_RENDERBUFFER:
624 break;
625
JiangYizhoubddc46b2016-12-09 09:50:51 +0800626 case GL_TEXTURE_2D_MULTISAMPLE:
627 if (context->getClientVersion() < ES_3_1)
628 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500629 context->handleError(InvalidOperation()
630 << "Texture target requires at least OpenGL ES 3.1.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800631 return false;
632 }
633 break;
634
Geoff Lang0a9661f2016-10-20 10:59:20 -0700635 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700636 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
Geoff Lang0a9661f2016-10-20 10:59:20 -0700637 return false;
638 }
639
640 if (bufSize < 0)
641 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700642 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
Geoff Lang0a9661f2016-10-20 10:59:20 -0700643 return false;
644 }
645
646 GLsizei maxWriteParams = 0;
647 switch (pname)
648 {
649 case GL_NUM_SAMPLE_COUNTS:
650 maxWriteParams = 1;
651 break;
652
653 case GL_SAMPLES:
654 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
655 break;
656
657 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700658 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang0a9661f2016-10-20 10:59:20 -0700659 return false;
660 }
661
662 if (numParams)
663 {
664 // glGetInternalFormativ will not overflow bufSize
665 *numParams = std::min(bufSize, maxWriteParams);
666 }
667
668 return true;
669}
670
Jamie Madillc1d770e2017-04-13 17:31:24 -0400671bool ValidateUniformCommonBase(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500672 gl::Program *program,
673 GLint location,
674 GLsizei count,
675 const LinkedUniform **uniformOut)
676{
677 // TODO(Jiajia): Add image uniform check in future.
678 if (count < 0)
679 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700680 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500681 return false;
682 }
683
Brandon Jones6cad5662017-06-14 13:25:13 -0700684 if (!program)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500685 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700686 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
687 return false;
688 }
689
690 if (!program->isLinked())
691 {
692 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500693 return false;
694 }
695
696 if (location == -1)
697 {
698 // Silently ignore the uniform command
699 return false;
700 }
701
702 const auto &uniformLocations = program->getUniformLocations();
Jamie Madillbe849e42017-05-02 15:49:00 -0400703 size_t castedLocation = static_cast<size_t>(location);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500704 if (castedLocation >= uniformLocations.size())
705 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500706 context->handleError(InvalidOperation() << "Invalid uniform location");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500707 return false;
708 }
709
710 const auto &uniformLocation = uniformLocations[castedLocation];
711 if (uniformLocation.ignored)
712 {
713 // Silently ignore the uniform command
714 return false;
715 }
716
717 if (!uniformLocation.used)
718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500719 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500720 return false;
721 }
722
723 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
724
725 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
726 if (!uniform.isArray() && count > 1)
727 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500728 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500729 return false;
730 }
731
732 *uniformOut = &uniform;
733 return true;
734}
735
Frank Henigman999b0fd2017-02-02 21:45:55 -0500736bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -0500737 GLenum uniformType,
738 GLsizei count,
739 const GLint *value)
740{
741 // Value type is GL_INT, because we only get here from glUniform1i{v}.
742 // It is compatible with INT or BOOL.
743 // Do these cheap tests first, for a little extra speed.
744 if (GL_INT == uniformType || GL_BOOL == uniformType)
745 {
746 return true;
747 }
748
749 if (IsSamplerType(uniformType))
750 {
Frank Henigman999b0fd2017-02-02 21:45:55 -0500751 // Check that the values are in range.
752 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
753 for (GLsizei i = 0; i < count; ++i)
754 {
755 if (value[i] < 0 || value[i] >= max)
756 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500757 context->handleError(InvalidValue() << "sampler uniform value out of range");
Frank Henigman999b0fd2017-02-02 21:45:55 -0500758 return false;
759 }
760 }
Frank Henigmana98a6472017-02-02 21:38:32 -0500761 return true;
762 }
763
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500764 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmana98a6472017-02-02 21:38:32 -0500765 return false;
766}
767
Jamie Madillc1d770e2017-04-13 17:31:24 -0400768bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500769{
770 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -0500771 // Do the cheaper test first, for a little extra speed.
772 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500773 {
774 return true;
775 }
776
Brandon Jonesafa75152017-07-21 13:11:29 -0700777 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500778 return false;
779}
780
Jamie Madillc1d770e2017-04-13 17:31:24 -0400781bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500782{
783 // Check that the value type is compatible with uniform type.
784 if (valueType == uniformType)
785 {
786 return true;
787 }
788
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500789 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500790 return false;
791}
792
Geoff Lange0cff192017-05-30 13:04:56 -0400793bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
794{
795 const Program *program = context->getGLState().getProgram();
796 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
797
798 const auto &programOutputTypes = program->getOutputVariableTypes();
799 for (size_t drawBufferIdx = 0; drawBufferIdx < programOutputTypes.size(); drawBufferIdx++)
800 {
801 GLenum outputType = programOutputTypes[drawBufferIdx];
802 GLenum inputType = framebuffer->getDrawbufferWriteType(drawBufferIdx);
803 if (outputType != GL_NONE && inputType != GL_NONE && inputType != outputType)
804 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500805 context->handleError(InvalidOperation() << "Fragment shader output type does not "
806 "match the bound framebuffer attachment "
807 "type.");
Geoff Lange0cff192017-05-30 13:04:56 -0400808 return false;
809 }
810 }
811
812 return true;
813}
814
Geoff Lang9ab5b822017-05-30 16:19:23 -0400815bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
816{
817 const Program *program = context->getGLState().getProgram();
818 const VertexArray *vao = context->getGLState().getVertexArray();
819
820 for (const auto &shaderAttribute : program->getAttributes())
821 {
Geoff Lang69df2422017-07-05 12:42:31 -0400822 // gl_VertexID and gl_InstanceID are active attributes but don't have a bound attribute.
823 if (shaderAttribute.isBuiltIn())
824 {
825 continue;
826 }
827
Geoff Lang9ab5b822017-05-30 16:19:23 -0400828 GLenum shaderInputType = VariableComponentType(shaderAttribute.type);
829
830 const auto &attrib = vao->getVertexAttribute(shaderAttribute.location);
831 const auto &currentValue =
832 context->getGLState().getVertexAttribCurrentValue(shaderAttribute.location);
833 GLenum vertexType = attrib.enabled ? GetVertexAttributeBaseType(attrib) : currentValue.Type;
834
835 if (shaderInputType != GL_NONE && vertexType != GL_NONE && shaderInputType != vertexType)
836 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500837 context->handleError(InvalidOperation() << "Vertex shader input type does not "
838 "match the type of the bound vertex "
839 "attribute.");
Geoff Lang9ab5b822017-05-30 16:19:23 -0400840 return false;
841 }
842 }
843
844 return true;
845}
846
Geoff Langf41a7152016-09-19 15:11:17 -0400847} // anonymous namespace
848
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500849bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400850{
Jamie Madilld7460c72014-01-21 16:38:14 -0500851 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400852 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800853 case GL_TEXTURE_2D:
854 case GL_TEXTURE_CUBE_MAP:
855 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400856
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400857 case GL_TEXTURE_RECTANGLE_ANGLE:
858 return context->getExtensions().textureRectangle;
859
He Yunchaoced53ae2016-11-29 15:00:51 +0800860 case GL_TEXTURE_3D:
861 case GL_TEXTURE_2D_ARRAY:
862 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500863
He Yunchaoced53ae2016-11-29 15:00:51 +0800864 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800865 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400866
He Yunchaoced53ae2016-11-29 15:00:51 +0800867 default:
868 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500869 }
Jamie Madill35d15012013-10-07 10:46:37 -0400870}
871
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500872bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
873{
874 switch (target)
875 {
876 case GL_TEXTURE_2D:
877 case GL_TEXTURE_CUBE_MAP:
878 return true;
879
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400880 case GL_TEXTURE_RECTANGLE_ANGLE:
881 return context->getExtensions().textureRectangle;
882
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500883 default:
884 return false;
885 }
886}
887
888bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
889{
890 switch (target)
891 {
892 case GL_TEXTURE_3D:
893 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300894 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500895
896 default:
897 return false;
898 }
899}
900
Ian Ewellbda75592016-04-18 17:25:54 -0400901// Most texture GL calls are not compatible with external textures, so we have a separate validation
902// function for use in the GL calls that do
903bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
904{
905 return (target == GL_TEXTURE_EXTERNAL_OES) &&
906 (context->getExtensions().eglImageExternal ||
907 context->getExtensions().eglStreamConsumerExternal);
908}
909
Shannon Woods4dfed832014-03-17 20:03:39 -0400910// This function differs from ValidTextureTarget in that the target must be
911// usable as the destination of a 2D operation-- so a cube face is valid, but
912// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400913// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500914bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400915{
916 switch (target)
917 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800918 case GL_TEXTURE_2D:
919 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
920 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
921 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
922 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
923 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
924 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
925 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400926 case GL_TEXTURE_RECTANGLE_ANGLE:
927 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800928 default:
929 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500930 }
931}
932
Jamie Madillbe849e42017-05-02 15:49:00 -0400933bool ValidateDrawElementsInstancedBase(ValidationContext *context,
934 GLenum mode,
935 GLsizei count,
936 GLenum type,
937 const GLvoid *indices,
938 GLsizei primcount)
939{
940 if (primcount < 0)
941 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700942 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400943 return false;
944 }
945
946 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
947 {
948 return false;
949 }
950
951 // No-op zero primitive count
952 return (primcount > 0);
953}
954
955bool ValidateDrawArraysInstancedBase(Context *context,
956 GLenum mode,
957 GLint first,
958 GLsizei count,
959 GLsizei primcount)
960{
961 if (primcount < 0)
962 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700963 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400964 return false;
965 }
966
967 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
968 {
969 return false;
970 }
971
972 // No-op if zero primitive count
973 return (primcount > 0);
974}
975
Corentin Wallez0dc97812017-06-22 14:38:44 -0400976bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400977{
978 // Verify there is at least one active attribute with a divisor of zero
979 const State &state = context->getGLState();
980
981 Program *program = state.getProgram();
982
983 const auto &attribs = state.getVertexArray()->getVertexAttributes();
984 const auto &bindings = state.getVertexArray()->getVertexBindings();
985 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
986 {
987 const VertexAttribute &attrib = attribs[attributeIndex];
988 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300989 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400990 {
991 return true;
992 }
993 }
994
Brandon Jonesafa75152017-07-21 13:11:29 -0700995 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400996 return false;
997}
998
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500999bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1000{
1001 switch (target)
1002 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001003 case GL_TEXTURE_3D:
1004 case GL_TEXTURE_2D_ARRAY:
1005 return true;
1006 default:
1007 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001008 }
1009}
1010
He Yunchao11b038b2016-11-22 21:24:04 +08001011bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
1012{
1013 switch (target)
1014 {
1015 case GL_TEXTURE_2D:
1016 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1017 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1018 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1019 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1020 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1021 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1022 case GL_TEXTURE_3D:
1023 case GL_TEXTURE_2D_ARRAY:
1024 case GL_TEXTURE_2D_MULTISAMPLE:
1025 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001026 case GL_TEXTURE_RECTANGLE_ANGLE:
1027 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +08001028 default:
1029 return false;
1030 }
1031}
1032
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001033bool ValidFramebufferTarget(GLenum target)
1034{
He Yunchaoced53ae2016-11-29 15:00:51 +08001035 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1036 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001037 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001038
1039 switch (target)
1040 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001041 case GL_FRAMEBUFFER:
1042 return true;
1043 case GL_READ_FRAMEBUFFER:
1044 return true;
1045 case GL_DRAW_FRAMEBUFFER:
1046 return true;
1047 default:
1048 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001049 }
1050}
1051
Jamie Madill29639852016-09-02 15:00:09 -04001052bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001053{
1054 switch (target)
1055 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001056 case GL_ARRAY_BUFFER:
1057 case GL_ELEMENT_ARRAY_BUFFER:
1058 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001059
He Yunchaoced53ae2016-11-29 15:00:51 +08001060 case GL_PIXEL_PACK_BUFFER:
1061 case GL_PIXEL_UNPACK_BUFFER:
1062 return (context->getExtensions().pixelBufferObject ||
1063 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001064
He Yunchaoced53ae2016-11-29 15:00:51 +08001065 case GL_COPY_READ_BUFFER:
1066 case GL_COPY_WRITE_BUFFER:
1067 case GL_TRANSFORM_FEEDBACK_BUFFER:
1068 case GL_UNIFORM_BUFFER:
1069 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001070
He Yunchaoced53ae2016-11-29 15:00:51 +08001071 case GL_ATOMIC_COUNTER_BUFFER:
1072 case GL_SHADER_STORAGE_BUFFER:
1073 case GL_DRAW_INDIRECT_BUFFER:
1074 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001075 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001076
He Yunchaoced53ae2016-11-29 15:00:51 +08001077 default:
1078 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001079 }
1080}
1081
Jamie Madillc29968b2016-01-20 11:17:23 -05001082bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001083{
Jamie Madillc29968b2016-01-20 11:17:23 -05001084 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001085 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001086 switch (target)
1087 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001088 case GL_TEXTURE_2D:
1089 maxDimension = caps.max2DTextureSize;
1090 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001091 case GL_TEXTURE_CUBE_MAP:
1092 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1093 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1094 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1095 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1096 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1097 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1098 maxDimension = caps.maxCubeMapTextureSize;
1099 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001100 case GL_TEXTURE_RECTANGLE_ANGLE:
1101 return level == 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08001102 case GL_TEXTURE_3D:
1103 maxDimension = caps.max3DTextureSize;
1104 break;
1105 case GL_TEXTURE_2D_ARRAY:
1106 maxDimension = caps.max2DTextureSize;
1107 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001108 case GL_TEXTURE_2D_MULTISAMPLE:
1109 maxDimension = caps.max2DTextureSize;
1110 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001111 default:
1112 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001113 }
1114
Brandon Jones6cad5662017-06-14 13:25:13 -07001115 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -04001116}
1117
Brandon Jones6cad5662017-06-14 13:25:13 -07001118bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001119 GLenum target,
1120 GLint level,
1121 GLsizei width,
1122 GLsizei height,
1123 GLsizei depth,
1124 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001125{
Brandon Jones6cad5662017-06-14 13:25:13 -07001126 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -04001127 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001128 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -04001129 return false;
1130 }
Austin Kinross08528e12015-10-07 16:24:40 -07001131 // TexSubImage parameters can be NPOT without textureNPOT extension,
1132 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001133 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001134 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001135 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001136 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001137 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001138 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -04001139 return false;
1140 }
1141
1142 if (!ValidMipLevel(context, target, level))
1143 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001144 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -04001145 return false;
1146 }
1147
1148 return true;
1149}
1150
Geoff Lang0d8b7242015-09-09 14:56:53 -04001151bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1152{
1153 // List of compressed format that require that the texture size is smaller than or a multiple of
1154 // the compressed block size.
1155 switch (internalFormat)
1156 {
1157 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1158 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1159 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1160 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langfff7a7d2017-06-02 10:39:17 -04001161 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
1162 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
1163 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
1164 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
Minmin Gonge3939b92015-12-01 15:36:51 -08001165 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001166 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1167 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1168 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1169 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1170 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
1171 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001172 return true;
1173
1174 default:
1175 return false;
1176 }
1177}
1178
Geoff Lang966c9402017-04-18 12:38:27 -04001179bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
1180{
1181 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
1182 (size % blockSize == 0);
1183}
1184
Jamie Madillc29968b2016-01-20 11:17:23 -05001185bool ValidCompressedImageSize(const ValidationContext *context,
1186 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -04001187 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -05001188 GLsizei width,
1189 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001190{
Geoff Langca271392017-04-05 12:30:00 -04001191 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -04001192 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001193 {
1194 return false;
1195 }
1196
Geoff Lang966c9402017-04-18 12:38:27 -04001197 if (width < 0 || height < 0)
1198 {
1199 return false;
1200 }
1201
1202 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1203 {
1204 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
1205 // block size for level 0 but WebGL disallows this.
1206 bool smallerThanBlockSizeAllowed =
1207 level > 0 || !context->getExtensions().webglCompatibility;
1208
1209 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
1210 smallerThanBlockSizeAllowed) ||
1211 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
1212 smallerThanBlockSizeAllowed))
1213 {
1214 return false;
1215 }
1216 }
1217
1218 return true;
1219}
1220
1221bool ValidCompressedSubImageSize(const ValidationContext *context,
1222 GLenum internalFormat,
1223 GLint xoffset,
1224 GLint yoffset,
1225 GLsizei width,
1226 GLsizei height,
1227 size_t textureWidth,
1228 size_t textureHeight)
1229{
1230 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
1231 if (!formatInfo.compressed)
1232 {
1233 return false;
1234 }
1235
Geoff Lang44ff5a72017-02-03 15:15:43 -05001236 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001237 {
1238 return false;
1239 }
1240
Geoff Lang0d8b7242015-09-09 14:56:53 -04001241 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1242 {
Geoff Lang44ff5a72017-02-03 15:15:43 -05001243 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -04001244 yoffset % formatInfo.compressedBlockHeight != 0)
1245 {
1246 return false;
1247 }
1248
1249 // Allowed to either have data that is a multiple of block size or is smaller than the block
1250 // size but fills the entire mip
1251 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
1252 static_cast<size_t>(width) == textureWidth &&
1253 static_cast<size_t>(height) == textureHeight;
1254 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
1255 (height % formatInfo.compressedBlockHeight) == 0;
1256 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -04001257 {
1258 return false;
1259 }
1260 }
1261
Geoff Langd4f180b2013-09-24 13:57:44 -04001262 return true;
1263}
1264
Geoff Langff5b2d52016-09-07 11:32:23 -04001265bool ValidImageDataSize(ValidationContext *context,
1266 GLenum textureTarget,
1267 GLsizei width,
1268 GLsizei height,
1269 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -04001270 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -04001271 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001272 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001273 GLsizei imageSize)
1274{
1275 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1276 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1277 {
1278 // Checks are not required
1279 return true;
1280 }
1281
1282 // ...the data would be unpacked from the buffer object such that the memory reads required
1283 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -04001284 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
1285 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -04001286 const gl::Extents size(width, height, depth);
1287 const auto &unpack = context->getGLState().getUnpackState();
1288
1289 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1290 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1291 if (endByteOrErr.isError())
1292 {
1293 context->handleError(endByteOrErr.getError());
1294 return false;
1295 }
1296
1297 GLuint endByte = endByteOrErr.getResult();
1298
1299 if (pixelUnpackBuffer)
1300 {
1301 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1302 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1303 checkedEndByte += checkedOffset;
1304
1305 if (!checkedEndByte.IsValid() ||
1306 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1307 {
1308 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001309 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04001310 return false;
1311 }
1312 }
1313 else
1314 {
1315 ASSERT(imageSize >= 0);
1316 if (pixels == nullptr && imageSize != 0)
1317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001318 context->handleError(InvalidOperation()
1319 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001320 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001321 }
1322
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001323 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001324 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001325 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001326 return false;
1327 }
1328 }
1329
1330 return true;
1331}
1332
Geoff Lang37dde692014-01-31 16:34:54 -05001333bool ValidQueryType(const Context *context, GLenum queryType)
1334{
He Yunchaoced53ae2016-11-29 15:00:51 +08001335 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1336 "GL extension enums not equal.");
1337 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1338 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001339
1340 switch (queryType)
1341 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001342 case GL_ANY_SAMPLES_PASSED:
1343 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1344 return true;
1345 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1346 return (context->getClientMajorVersion() >= 3);
1347 case GL_TIME_ELAPSED_EXT:
1348 return context->getExtensions().disjointTimerQuery;
1349 case GL_COMMANDS_COMPLETED_CHROMIUM:
1350 return context->getExtensions().syncQuery;
1351 default:
1352 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001353 }
1354}
1355
Geoff Lang2d62ab72017-03-23 16:54:40 -04001356bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
1357 GLenum type,
1358 GLboolean normalized,
1359 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001360 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001361 bool pureInteger)
1362{
1363 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001364 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1365 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1366 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1367 // parameter exceeds 255.
1368 constexpr GLsizei kMaxWebGLStride = 255;
1369 if (stride > kMaxWebGLStride)
1370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001371 context->handleError(InvalidValue()
1372 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001373 return false;
1374 }
1375
1376 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1377 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1378 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1379 // or an INVALID_OPERATION error is generated.
1380 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1381 size_t typeSize = GetVertexFormatTypeSize(internalType);
1382
1383 ASSERT(isPow2(typeSize) && typeSize > 0);
1384 size_t sizeMask = (typeSize - 1);
1385 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1386 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001387 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001388 return false;
1389 }
1390
1391 if ((stride & sizeMask) != 0)
1392 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001393 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001394 return false;
1395 }
1396
1397 return true;
1398}
1399
Jamie Madillef300b12016-10-07 15:12:09 -04001400Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001401{
He Yunchaoced53ae2016-11-29 15:00:51 +08001402 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1403 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1404 // or program object and INVALID_OPERATION if the provided name identifies an object
1405 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001406
Dian Xiang769769a2015-09-09 15:20:08 -07001407 Program *validProgram = context->getProgram(id);
1408
1409 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001410 {
Dian Xiang769769a2015-09-09 15:20:08 -07001411 if (context->getShader(id))
1412 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001413 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001414 }
1415 else
1416 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001417 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001418 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001419 }
Dian Xiang769769a2015-09-09 15:20:08 -07001420
1421 return validProgram;
1422}
1423
Jamie Madillef300b12016-10-07 15:12:09 -04001424Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001425{
1426 // See ValidProgram for spec details.
1427
1428 Shader *validShader = context->getShader(id);
1429
1430 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001431 {
Dian Xiang769769a2015-09-09 15:20:08 -07001432 if (context->getProgram(id))
1433 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001434 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001435 }
1436 else
1437 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001438 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001439 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001440 }
Dian Xiang769769a2015-09-09 15:20:08 -07001441
1442 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001443}
1444
Geoff Langb1196682014-07-23 13:47:29 -04001445bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001446{
1447 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1448 {
1449 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1450
Geoff Langaae65a42014-05-26 12:43:44 -04001451 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001452 {
Martin Radevd178aa42017-07-13 14:03:22 +03001453 context->handleError(
1454 InvalidOperation()
1455 << "attachment index cannot be greater or equal to MAX_COLOR_ATTACHMENTS.");
Geoff Langb1196682014-07-23 13:47:29 -04001456 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001457 }
1458 }
1459 else
1460 {
1461 switch (attachment)
1462 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001463 case GL_DEPTH_ATTACHMENT:
1464 case GL_STENCIL_ATTACHMENT:
1465 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001466
He Yunchaoced53ae2016-11-29 15:00:51 +08001467 case GL_DEPTH_STENCIL_ATTACHMENT:
1468 if (!context->getExtensions().webglCompatibility &&
1469 context->getClientMajorVersion() < 3)
1470 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001471 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001472 return false;
1473 }
1474 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001475
He Yunchaoced53ae2016-11-29 15:00:51 +08001476 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001477 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001478 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001479 }
1480 }
1481
1482 return true;
1483}
1484
Jamie Madille8fb6402017-02-14 17:56:40 -05001485bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001486 GLenum target,
1487 GLsizei samples,
1488 GLenum internalformat,
1489 GLsizei width,
1490 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001491{
1492 switch (target)
1493 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001494 case GL_RENDERBUFFER:
1495 break;
1496 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001497 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001498 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001499 }
1500
1501 if (width < 0 || height < 0 || samples < 0)
1502 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001503 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001504 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001505 }
1506
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001507 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1508 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1509
1510 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001511 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001513 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001514 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001515 }
1516
1517 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1518 // 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 -08001519 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001520 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1521 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001522 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001523 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001524 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001525 }
1526
Geoff Langaae65a42014-05-26 12:43:44 -04001527 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001528 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001529 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001530 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001531 }
1532
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001533 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001534 if (handle == 0)
1535 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001536 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001537 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001538 }
1539
1540 return true;
1541}
1542
He Yunchaoced53ae2016-11-29 15:00:51 +08001543bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1544 GLenum target,
1545 GLenum attachment,
1546 GLenum renderbuffertarget,
1547 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001548{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001549 if (!ValidFramebufferTarget(target))
1550 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001551 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001552 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001553 }
1554
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001555 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001556
Jamie Madill84115c92015-04-23 15:00:07 -04001557 ASSERT(framebuffer);
1558 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001559 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001560 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001561 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001562 }
1563
Jamie Madillb4472272014-07-03 10:38:55 -04001564 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001565 {
Jamie Madillb4472272014-07-03 10:38:55 -04001566 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001567 }
1568
Jamie Madillab9d82c2014-01-21 16:38:14 -05001569 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1570 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1571 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1572 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1573 if (renderbuffer != 0)
1574 {
1575 if (!context->getRenderbuffer(renderbuffer))
1576 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001577 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001578 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001579 }
1580 }
1581
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001582 return true;
1583}
1584
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001585bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001586 GLint srcX0,
1587 GLint srcY0,
1588 GLint srcX1,
1589 GLint srcY1,
1590 GLint dstX0,
1591 GLint dstY0,
1592 GLint dstX1,
1593 GLint dstY1,
1594 GLbitfield mask,
1595 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001596{
1597 switch (filter)
1598 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001599 case GL_NEAREST:
1600 break;
1601 case GL_LINEAR:
1602 break;
1603 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001604 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001605 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001606 }
1607
1608 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1609 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001610 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001611 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001612 }
1613
1614 if (mask == 0)
1615 {
1616 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1617 // buffers are copied.
1618 return false;
1619 }
1620
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001621 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1622 // color buffer, leaving only nearest being unfiltered from above
1623 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001625 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001626 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001627 }
1628
Jamie Madill51f40ec2016-06-15 14:06:00 -04001629 const auto &glState = context->getGLState();
1630 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1631 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001632
1633 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001634 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001635 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001636 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001637 }
1638
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001639 if (readFramebuffer->id() == drawFramebuffer->id())
1640 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001641 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001642 return false;
1643 }
1644
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001645 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001647 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001648 return false;
1649 }
1650
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001651 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001652 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001653 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001654 return false;
1655 }
1656
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001657 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001659 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001660 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001661 }
1662
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001663 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1664
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001665 if (mask & GL_COLOR_BUFFER_BIT)
1666 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001667 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001668 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001669
He Yunchao66a41a22016-12-15 16:45:05 +08001670 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001671 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001672 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001673
Geoff Langa15472a2015-08-11 11:48:03 -04001674 for (size_t drawbufferIdx = 0;
1675 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001676 {
Geoff Langa15472a2015-08-11 11:48:03 -04001677 const FramebufferAttachment *attachment =
1678 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1679 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001680 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001681 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001682
Geoff Langb2f3d052013-08-13 12:49:27 -04001683 // The GL ES 3.0.2 spec (pg 193) states that:
1684 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001685 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1686 // as well
1687 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1688 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001689 // Changes with EXT_color_buffer_float:
1690 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001691 GLenum readComponentType = readFormat.info->componentType;
1692 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001693 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001694 readComponentType == GL_SIGNED_NORMALIZED);
1695 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1696 drawComponentType == GL_SIGNED_NORMALIZED);
1697
1698 if (extensions.colorBufferFloat)
1699 {
1700 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1701 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1702
1703 if (readFixedOrFloat != drawFixedOrFloat)
1704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001705 context->handleError(InvalidOperation()
1706 << "If the read buffer contains fixed-point or "
1707 "floating-point values, the draw buffer must "
1708 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001709 return false;
1710 }
1711 }
1712 else if (readFixedPoint != drawFixedPoint)
1713 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001714 context->handleError(InvalidOperation()
1715 << "If the read buffer contains fixed-point values, "
1716 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001717 return false;
1718 }
1719
1720 if (readComponentType == GL_UNSIGNED_INT &&
1721 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001722 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001723 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001724 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001725 }
1726
Jamie Madill6163c752015-12-07 16:32:59 -05001727 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001728 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001729 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001730 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001731 }
1732
Jamie Madilla3944d42016-07-22 22:13:26 -04001733 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001734 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001735 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001736 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001737 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001738 }
Geoff Lange4915782017-04-12 15:19:07 -04001739
1740 if (context->getExtensions().webglCompatibility &&
1741 *readColorBuffer == *attachment)
1742 {
1743 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001744 InvalidOperation()
1745 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001746 return false;
1747 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001748 }
1749 }
1750
Jamie Madilla3944d42016-07-22 22:13:26 -04001751 if ((readFormat.info->componentType == GL_INT ||
1752 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1753 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001754 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001755 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001756 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001757 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001758 }
He Yunchao66a41a22016-12-15 16:45:05 +08001759 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1760 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1761 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1762 // situation is an application error that would lead to a crash in ANGLE.
1763 else if (drawFramebuffer->hasEnabledDrawBuffer())
1764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001765 context->handleError(
1766 InvalidOperation()
1767 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001768 return false;
1769 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001770 }
1771
He Yunchaoced53ae2016-11-29 15:00:51 +08001772 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001773 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1774 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001775 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001776 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001777 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001778 const gl::FramebufferAttachment *readBuffer =
1779 readFramebuffer->getAttachment(attachments[i]);
1780 const gl::FramebufferAttachment *drawBuffer =
1781 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001782
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001783 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001784 {
Kenneth Russell69382852017-07-21 16:38:44 -04001785 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001786 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001787 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001788 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001789 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001790
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001791 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001792 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001793 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001794 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001795 }
Geoff Lange4915782017-04-12 15:19:07 -04001796
1797 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1798 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001799 context->handleError(
1800 InvalidOperation()
1801 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001802 return false;
1803 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001804 }
He Yunchao66a41a22016-12-15 16:45:05 +08001805 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1806 else if (drawBuffer)
1807 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001808 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1809 "depth/stencil attachment of a "
1810 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001811 return false;
1812 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001813 }
1814 }
1815
Martin Radeva3ed4572017-07-27 18:29:37 +03001816 // ANGLE_multiview, Revision 1:
1817 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1818 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1819 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1820 {
1821 context->handleError(InvalidFramebufferOperation()
1822 << "Attempt to read from a multi-view framebuffer.");
1823 return false;
1824 }
1825 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1826 {
1827 context->handleError(InvalidFramebufferOperation()
1828 << "Attempt to write to a multi-view framebuffer.");
1829 return false;
1830 }
1831
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001832 return true;
1833}
1834
Jamie Madill4928b7c2017-06-20 12:57:39 -04001835bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001836 GLint x,
1837 GLint y,
1838 GLsizei width,
1839 GLsizei height,
1840 GLenum format,
1841 GLenum type,
1842 GLsizei bufSize,
1843 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001844 GLsizei *columns,
1845 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001846 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001847{
1848 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001849 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001850 return false;
1851 }
1852
Geoff Lang62fce5b2016-09-30 10:46:35 -04001853 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001854 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001855 {
Geoff Langb1196682014-07-23 13:47:29 -04001856 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001857 }
1858
Geoff Lang62fce5b2016-09-30 10:46:35 -04001859 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001860 {
Geoff Langb1196682014-07-23 13:47:29 -04001861 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001862 }
1863
Jamie Madillc29968b2016-01-20 11:17:23 -05001864 return true;
1865}
1866
1867bool ValidateReadnPixelsEXT(Context *context,
1868 GLint x,
1869 GLint y,
1870 GLsizei width,
1871 GLsizei height,
1872 GLenum format,
1873 GLenum type,
1874 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001875 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001876{
1877 if (bufSize < 0)
1878 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001879 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001880 return false;
1881 }
1882
Geoff Lang62fce5b2016-09-30 10:46:35 -04001883 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001884 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001885}
Jamie Madill26e91952014-03-05 15:01:27 -05001886
Jamie Madill4928b7c2017-06-20 12:57:39 -04001887bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001888 GLint x,
1889 GLint y,
1890 GLsizei width,
1891 GLsizei height,
1892 GLenum format,
1893 GLenum type,
1894 GLsizei bufSize,
1895 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001896 GLsizei *columns,
1897 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001898 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001899{
1900 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001901 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001902 return false;
1903 }
1904
Geoff Lange93daba2017-03-30 13:54:40 -04001905 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1906 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001907 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001908 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001909 }
1910
Geoff Lang62fce5b2016-09-30 10:46:35 -04001911 if (!ValidateRobustBufferSize(context, bufSize, *length))
1912 {
1913 return false;
1914 }
1915
1916 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001917}
1918
Olli Etuaho41997e72016-03-10 13:38:39 +02001919bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001920{
1921 if (!context->getExtensions().occlusionQueryBoolean &&
1922 !context->getExtensions().disjointTimerQuery)
1923 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001924 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001925 return false;
1926 }
1927
Olli Etuaho41997e72016-03-10 13:38:39 +02001928 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001929}
1930
Olli Etuaho41997e72016-03-10 13:38:39 +02001931bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001932{
1933 if (!context->getExtensions().occlusionQueryBoolean &&
1934 !context->getExtensions().disjointTimerQuery)
1935 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001936 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001937 return false;
1938 }
1939
Olli Etuaho41997e72016-03-10 13:38:39 +02001940 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001941}
1942
1943bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001944{
1945 if (!ValidQueryType(context, target))
1946 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001947 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001948 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001949 }
1950
1951 if (id == 0)
1952 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001953 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001954 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001955 }
1956
1957 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1958 // of zero, if the active query object name for <target> is non-zero (for the
1959 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1960 // the active query for either target is non-zero), if <id> is the name of an
1961 // existing query object whose type does not match <target>, or if <id> is the
1962 // active query object name for any query type, the error INVALID_OPERATION is
1963 // generated.
1964
1965 // Ensure no other queries are active
1966 // NOTE: If other queries than occlusion are supported, we will need to check
1967 // separately that:
1968 // a) The query ID passed is not the current active query for any target/type
1969 // b) There are no active queries for the requested target (and in the case
1970 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1971 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001972
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001973 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001974 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001975 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001976 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001977 }
1978
1979 Query *queryObject = context->getQuery(id, true, target);
1980
1981 // check that name was obtained with glGenQueries
1982 if (!queryObject)
1983 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001984 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001985 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001986 }
1987
1988 // check for type mismatch
1989 if (queryObject->getType() != target)
1990 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001991 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001992 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001993 }
1994
1995 return true;
1996}
1997
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001998bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1999{
2000 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002001 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002002 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002003 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002004 return false;
2005 }
2006
2007 return ValidateBeginQueryBase(context, target, id);
2008}
2009
2010bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002011{
2012 if (!ValidQueryType(context, target))
2013 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002014 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04002015 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002016 }
2017
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002018 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002019
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002020 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002021 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002022 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04002023 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002024 }
2025
Jamie Madill45c785d2014-05-13 14:09:34 -04002026 return true;
2027}
2028
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002029bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2030{
2031 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002032 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002033 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002034 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002035 return false;
2036 }
2037
2038 return ValidateEndQueryBase(context, target);
2039}
2040
2041bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2042{
2043 if (!context->getExtensions().disjointTimerQuery)
2044 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002045 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002046 return false;
2047 }
2048
2049 if (target != GL_TIMESTAMP_EXT)
2050 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002051 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002052 return false;
2053 }
2054
2055 Query *queryObject = context->getQuery(id, true, target);
2056 if (queryObject == nullptr)
2057 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002058 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002059 return false;
2060 }
2061
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002062 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002063 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002064 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002065 return false;
2066 }
2067
2068 return true;
2069}
2070
Geoff Lang2186c382016-10-14 10:54:54 -04002071bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002072{
Geoff Lang2186c382016-10-14 10:54:54 -04002073 if (numParams)
2074 {
2075 *numParams = 0;
2076 }
2077
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002078 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2079 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002080 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002081 return false;
2082 }
2083
2084 switch (pname)
2085 {
2086 case GL_CURRENT_QUERY_EXT:
2087 if (target == GL_TIMESTAMP_EXT)
2088 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002089 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002090 return false;
2091 }
2092 break;
2093 case GL_QUERY_COUNTER_BITS_EXT:
2094 if (!context->getExtensions().disjointTimerQuery ||
2095 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2096 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002097 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002098 return false;
2099 }
2100 break;
2101 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002102 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002103 return false;
2104 }
2105
Geoff Lang2186c382016-10-14 10:54:54 -04002106 if (numParams)
2107 {
2108 // All queries return only one value
2109 *numParams = 1;
2110 }
2111
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002112 return true;
2113}
2114
2115bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2116{
2117 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002118 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002119 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002120 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002121 return false;
2122 }
2123
Geoff Lang2186c382016-10-14 10:54:54 -04002124 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002125}
2126
Geoff Lang2186c382016-10-14 10:54:54 -04002127bool ValidateGetQueryivRobustANGLE(Context *context,
2128 GLenum target,
2129 GLenum pname,
2130 GLsizei bufSize,
2131 GLsizei *length,
2132 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002133{
Geoff Lang2186c382016-10-14 10:54:54 -04002134 if (!ValidateRobustEntryPoint(context, bufSize))
2135 {
2136 return false;
2137 }
2138
2139 if (!ValidateGetQueryivBase(context, target, pname, length))
2140 {
2141 return false;
2142 }
2143
2144 if (!ValidateRobustBufferSize(context, bufSize, *length))
2145 {
2146 return false;
2147 }
2148
2149 return true;
2150}
2151
2152bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2153{
2154 if (numParams)
2155 {
2156 *numParams = 0;
2157 }
2158
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002159 Query *queryObject = context->getQuery(id, false, GL_NONE);
2160
2161 if (!queryObject)
2162 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002163 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002164 return false;
2165 }
2166
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002167 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002168 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002169 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002170 return false;
2171 }
2172
2173 switch (pname)
2174 {
2175 case GL_QUERY_RESULT_EXT:
2176 case GL_QUERY_RESULT_AVAILABLE_EXT:
2177 break;
2178
2179 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002180 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002181 return false;
2182 }
2183
Geoff Lang2186c382016-10-14 10:54:54 -04002184 if (numParams)
2185 {
2186 *numParams = 1;
2187 }
2188
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002189 return true;
2190}
2191
2192bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2193{
2194 if (!context->getExtensions().disjointTimerQuery)
2195 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002196 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002197 return false;
2198 }
Geoff Lang2186c382016-10-14 10:54:54 -04002199 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2200}
2201
2202bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2203 GLuint id,
2204 GLenum pname,
2205 GLsizei bufSize,
2206 GLsizei *length,
2207 GLint *params)
2208{
2209 if (!context->getExtensions().disjointTimerQuery)
2210 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002211 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04002212 return false;
2213 }
2214
2215 if (!ValidateRobustEntryPoint(context, bufSize))
2216 {
2217 return false;
2218 }
2219
2220 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2221 {
2222 return false;
2223 }
2224
2225 if (!ValidateRobustBufferSize(context, bufSize, *length))
2226 {
2227 return false;
2228 }
2229
2230 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002231}
2232
2233bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2234{
2235 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002236 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002237 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002238 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002239 return false;
2240 }
Geoff Lang2186c382016-10-14 10:54:54 -04002241 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2242}
2243
2244bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2245 GLuint id,
2246 GLenum pname,
2247 GLsizei bufSize,
2248 GLsizei *length,
2249 GLuint *params)
2250{
2251 if (!context->getExtensions().disjointTimerQuery &&
2252 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2253 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002254 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002255 return false;
2256 }
2257
2258 if (!ValidateRobustEntryPoint(context, bufSize))
2259 {
2260 return false;
2261 }
2262
2263 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2264 {
2265 return false;
2266 }
2267
2268 if (!ValidateRobustBufferSize(context, bufSize, *length))
2269 {
2270 return false;
2271 }
2272
2273 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002274}
2275
2276bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2277{
2278 if (!context->getExtensions().disjointTimerQuery)
2279 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002280 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002281 return false;
2282 }
Geoff Lang2186c382016-10-14 10:54:54 -04002283 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2284}
2285
2286bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2287 GLuint id,
2288 GLenum pname,
2289 GLsizei bufSize,
2290 GLsizei *length,
2291 GLint64 *params)
2292{
2293 if (!context->getExtensions().disjointTimerQuery)
2294 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002295 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002296 return false;
2297 }
2298
2299 if (!ValidateRobustEntryPoint(context, bufSize))
2300 {
2301 return false;
2302 }
2303
2304 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2305 {
2306 return false;
2307 }
2308
2309 if (!ValidateRobustBufferSize(context, bufSize, *length))
2310 {
2311 return false;
2312 }
2313
2314 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002315}
2316
2317bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2318{
2319 if (!context->getExtensions().disjointTimerQuery)
2320 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002321 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002322 return false;
2323 }
Geoff Lang2186c382016-10-14 10:54:54 -04002324 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2325}
2326
2327bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2328 GLuint id,
2329 GLenum pname,
2330 GLsizei bufSize,
2331 GLsizei *length,
2332 GLuint64 *params)
2333{
2334 if (!context->getExtensions().disjointTimerQuery)
2335 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002336 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002337 return false;
2338 }
2339
2340 if (!ValidateRobustEntryPoint(context, bufSize))
2341 {
2342 return false;
2343 }
2344
2345 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2346 {
2347 return false;
2348 }
2349
2350 if (!ValidateRobustBufferSize(context, bufSize, *length))
2351 {
2352 return false;
2353 }
2354
2355 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002356}
2357
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002358bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002359 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002360 GLuint program,
2361 GLint location,
2362 GLsizei count)
2363{
2364 // Check for ES31 program uniform entry points
2365 if (context->getClientVersion() < Version(3, 1))
2366 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002367 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002368 return false;
2369 }
2370
2371 const LinkedUniform *uniform = nullptr;
2372 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002373 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2374 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002375}
2376
Frank Henigmana98a6472017-02-02 21:38:32 -05002377bool ValidateProgramUniform1iv(gl::Context *context,
2378 GLuint program,
2379 GLint location,
2380 GLsizei count,
2381 const GLint *value)
2382{
2383 // Check for ES31 program uniform entry points
2384 if (context->getClientVersion() < Version(3, 1))
2385 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002386 context->handleError(InvalidOperation());
Frank Henigmana98a6472017-02-02 21:38:32 -05002387 return false;
2388 }
2389
2390 const LinkedUniform *uniform = nullptr;
2391 gl::Program *programObject = GetValidProgram(context, program);
2392 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2393 ValidateUniform1ivValue(context, uniform->type, count, value);
2394}
2395
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002396bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002397 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002398 GLuint program,
2399 GLint location,
2400 GLsizei count,
2401 GLboolean transpose)
2402{
2403 // Check for ES31 program uniform entry points
2404 if (context->getClientVersion() < Version(3, 1))
2405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002406 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002407 return false;
2408 }
2409
2410 const LinkedUniform *uniform = nullptr;
2411 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002412 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2413 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002414}
2415
Jamie Madillc1d770e2017-04-13 17:31:24 -04002416bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002417{
2418 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002419 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002420 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002421 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002422 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002423 }
2424
Jamie Madill62d31cb2015-09-11 13:25:51 -04002425 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002426 gl::Program *programObject = context->getGLState().getProgram();
2427 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2428 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002429}
2430
Jamie Madillbe849e42017-05-02 15:49:00 -04002431bool ValidateUniform1iv(ValidationContext *context,
2432 GLint location,
2433 GLsizei count,
2434 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002435{
2436 const LinkedUniform *uniform = nullptr;
2437 gl::Program *programObject = context->getGLState().getProgram();
2438 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2439 ValidateUniform1ivValue(context, uniform->type, count, value);
2440}
2441
Jamie Madillc1d770e2017-04-13 17:31:24 -04002442bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002443 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002444 GLint location,
2445 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002446 GLboolean transpose)
2447{
2448 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002449 int rows = VariableRowCount(valueType);
2450 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002451 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002452 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002453 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002454 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002455 }
2456
Martin Radev1be913c2016-07-11 17:59:16 +03002457 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002458 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002459 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002460 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002461 }
2462
Jamie Madill62d31cb2015-09-11 13:25:51 -04002463 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002464 gl::Program *programObject = context->getGLState().getProgram();
2465 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2466 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002467}
2468
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002469bool ValidateStateQuery(ValidationContext *context,
2470 GLenum pname,
2471 GLenum *nativeType,
2472 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002473{
2474 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2475 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002476 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002477 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002478 }
2479
Jamie Madill0af26e12015-03-05 19:54:33 -05002480 const Caps &caps = context->getCaps();
2481
Jamie Madill893ab082014-05-16 16:56:10 -04002482 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2483 {
2484 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2485
Jamie Madill0af26e12015-03-05 19:54:33 -05002486 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002488 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002489 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002490 }
2491 }
2492
2493 switch (pname)
2494 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002495 case GL_TEXTURE_BINDING_2D:
2496 case GL_TEXTURE_BINDING_CUBE_MAP:
2497 case GL_TEXTURE_BINDING_3D:
2498 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002499 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002500 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002501 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2502 if (!context->getExtensions().textureRectangle)
2503 {
2504 context->handleError(InvalidEnum()
2505 << "ANGLE_texture_rectangle extension not present");
2506 return false;
2507 }
2508 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002509 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2510 if (!context->getExtensions().eglStreamConsumerExternal &&
2511 !context->getExtensions().eglImageExternal)
2512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002513 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2514 "nor GL_OES_EGL_image_external "
2515 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002516 return false;
2517 }
2518 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002519
He Yunchaoced53ae2016-11-29 15:00:51 +08002520 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2521 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002522 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002523 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2524 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002525 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002526 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002527 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002528 }
2529
Jamie Madill51f40ec2016-06-15 14:06:00 -04002530 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2531 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002532
2533 if (framebuffer->getReadBufferState() == GL_NONE)
2534 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002535 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002536 return false;
2537 }
2538
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002539 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002540 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002541 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002542 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002543 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002544 }
2545 }
2546 break;
2547
He Yunchaoced53ae2016-11-29 15:00:51 +08002548 default:
2549 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002550 }
2551
2552 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002553 if (*numParams == 0)
2554 {
2555 return false;
2556 }
2557
2558 return true;
2559}
2560
2561bool ValidateRobustStateQuery(ValidationContext *context,
2562 GLenum pname,
2563 GLsizei bufSize,
2564 GLenum *nativeType,
2565 unsigned int *numParams)
2566{
2567 if (!ValidateRobustEntryPoint(context, bufSize))
2568 {
2569 return false;
2570 }
2571
2572 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2573 {
2574 return false;
2575 }
2576
2577 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002578 {
2579 return false;
2580 }
2581
2582 return true;
2583}
2584
Jamie Madillc29968b2016-01-20 11:17:23 -05002585bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2586 GLenum target,
2587 GLint level,
2588 GLenum internalformat,
2589 bool isSubImage,
2590 GLint xoffset,
2591 GLint yoffset,
2592 GLint zoffset,
2593 GLint x,
2594 GLint y,
2595 GLsizei width,
2596 GLsizei height,
2597 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002598 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002599{
Brandon Jones6cad5662017-06-14 13:25:13 -07002600 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002601 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002602 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2603 return false;
2604 }
2605
2606 if (width < 0 || height < 0)
2607 {
2608 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002609 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002610 }
2611
He Yunchaoced53ae2016-11-29 15:00:51 +08002612 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2613 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002614 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002615 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002616 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002617 }
2618
2619 if (border != 0)
2620 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002621 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002622 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002623 }
2624
2625 if (!ValidMipLevel(context, target, level))
2626 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002627 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002628 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002629 }
2630
Jamie Madill51f40ec2016-06-15 14:06:00 -04002631 const auto &state = context->getGLState();
2632 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002633 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002634 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002635 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002636 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002637 }
2638
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002639 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002640 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002641 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002642 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002643 }
2644
Martin Radev138064f2016-07-15 12:03:41 +03002645 if (readFramebuffer->getReadBufferState() == GL_NONE)
2646 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002647 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002648 return false;
2649 }
2650
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002651 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2652 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002653 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002654 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002655 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2656 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002657 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002658 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002659 return false;
2660 }
2661
Martin Radev04e2c3b2017-07-27 16:54:35 +03002662 // ANGLE_multiview spec, Revision 1:
2663 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2664 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2665 // is not NONE.
2666 if (source->getMultiviewLayout() != GL_NONE)
2667 {
2668 context->handleError(InvalidFramebufferOperation()
2669 << "The active read framebuffer object has multiview attachments.");
2670 return false;
2671 }
2672
Geoff Langaae65a42014-05-26 12:43:44 -04002673 const gl::Caps &caps = context->getCaps();
2674
Geoff Langaae65a42014-05-26 12:43:44 -04002675 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002676 switch (target)
2677 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002678 case GL_TEXTURE_2D:
2679 maxDimension = caps.max2DTextureSize;
2680 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002681
He Yunchaoced53ae2016-11-29 15:00:51 +08002682 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2683 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2684 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2685 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2686 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2687 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2688 maxDimension = caps.maxCubeMapTextureSize;
2689 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002690
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002691 case GL_TEXTURE_RECTANGLE_ANGLE:
2692 maxDimension = caps.maxRectangleTextureSize;
2693 break;
2694
He Yunchaoced53ae2016-11-29 15:00:51 +08002695 case GL_TEXTURE_2D_ARRAY:
2696 maxDimension = caps.max2DTextureSize;
2697 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002698
He Yunchaoced53ae2016-11-29 15:00:51 +08002699 case GL_TEXTURE_3D:
2700 maxDimension = caps.max3DTextureSize;
2701 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002702
He Yunchaoced53ae2016-11-29 15:00:51 +08002703 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002704 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002705 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002706 }
2707
Jamie Madillc29968b2016-01-20 11:17:23 -05002708 gl::Texture *texture =
2709 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002710 if (!texture)
2711 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002712 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002713 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002714 }
2715
Geoff Lang69cce582015-09-17 13:20:36 -04002716 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002717 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002718 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002719 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002720 }
2721
Geoff Langca271392017-04-05 12:30:00 -04002722 const gl::InternalFormat &formatInfo =
2723 gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002724
Geoff Lang966c9402017-04-18 12:38:27 -04002725 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002726 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002727 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002728 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002729 }
2730
2731 if (isSubImage)
2732 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002733 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2734 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2735 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002736 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002737 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002738 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002739 }
2740 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002741 else
2742 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002743 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002744 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002745 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002746 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002747 }
2748
Geoff Langeb66a6e2016-10-31 13:06:12 -04002749 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002750 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002751 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002752 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002753 }
2754
2755 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002756 if (static_cast<int>(width) > maxLevelDimension ||
2757 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002758 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002759 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002760 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002761 }
2762 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002763
Jamie Madill0c8abca2016-07-22 20:21:26 -04002764 if (textureFormatOut)
2765 {
2766 *textureFormatOut = texture->getFormat(target, level);
2767 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002768
2769 // Detect texture copying feedback loops for WebGL.
2770 if (context->getExtensions().webglCompatibility)
2771 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002772 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002773 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002774 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002775 return false;
2776 }
2777 }
2778
Jamie Madill560a8d82014-05-21 13:06:20 -04002779 return true;
2780}
2781
Jiajia Qind9671222016-11-29 16:30:31 +08002782bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002783{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002784 switch (mode)
2785 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002786 case GL_POINTS:
2787 case GL_LINES:
2788 case GL_LINE_LOOP:
2789 case GL_LINE_STRIP:
2790 case GL_TRIANGLES:
2791 case GL_TRIANGLE_STRIP:
2792 case GL_TRIANGLE_FAN:
2793 break;
2794 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002795 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002796 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002797 }
2798
Jamie Madill250d33f2014-06-06 17:09:03 -04002799 if (count < 0)
2800 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002801 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002802 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002803 }
2804
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002805 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002806
Jamie Madill250d33f2014-06-06 17:09:03 -04002807 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002808 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002809 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002810 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002811 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002812 }
2813
Jamie Madillcbcde722017-01-06 14:50:00 -05002814 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2815 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002816 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002817 const Extensions &extensions = context->getExtensions();
2818 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002819 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002820 const FramebufferAttachment *dsAttachment =
2821 framebuffer->getStencilOrDepthStencilAttachment();
2822 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002823 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002824 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002825
2826 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2827 bool differentWritemasks =
2828 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2829 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2830 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2831 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2832
2833 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002834 {
Martin Radevffe754b2017-07-31 10:38:07 +03002835 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002836 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002837 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2838 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002839 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002840 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002841 return false;
2842 }
Jamie Madillac528012014-06-20 13:21:23 -04002843 }
2844
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002845 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002846 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002847 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002848 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002849 }
2850
Geoff Lang7dd2e102014-11-10 15:19:26 -05002851 gl::Program *program = state.getProgram();
2852 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002853 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002854 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002855 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002856 }
2857
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002858 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002859 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002860 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002861 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002862 }
2863
Martin Radevffe754b2017-07-31 10:38:07 +03002864 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002865 {
Martin Radev7e69f762017-07-27 14:54:13 +03002866 const int programNumViews = program->getNumViews();
2867 const int framebufferNumViews = framebuffer->getNumViews();
2868 if (programNumViews != -1 && framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002869 {
2870 context->handleError(InvalidOperation() << "The number of views in the active program "
2871 "and draw framebuffer does not match.");
2872 return false;
2873 }
Martin Radev7e69f762017-07-27 14:54:13 +03002874
2875 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2876 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2877 framebufferNumViews > 1)
2878 {
2879 context->handleError(InvalidOperation()
2880 << "There is an active transform feedback object "
2881 "when the number of views in the active draw "
2882 "framebuffer is greater than 1.");
2883 return false;
2884 }
Martin Radevffe754b2017-07-31 10:38:07 +03002885
2886 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2887 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2888 {
2889 context->handleError(InvalidOperation() << "There is an active query for target "
2890 "GL_TIME_ELAPSED_EXT when the number of "
2891 "views in the active draw framebuffer is "
2892 "greater than 1.");
2893 return false;
2894 }
Martin Radev7cf61662017-07-26 17:10:53 +03002895 }
2896
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002897 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002898 for (unsigned int uniformBlockIndex = 0;
2899 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002900 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002901 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002902 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002903 const OffsetBindingPointer<Buffer> &uniformBuffer =
2904 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002905
Geoff Lang5d124a62015-09-15 13:03:27 -04002906 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002907 {
2908 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002909 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002910 InvalidOperation()
2911 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002912 return false;
2913 }
2914
Geoff Lang5d124a62015-09-15 13:03:27 -04002915 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002916 if (uniformBufferSize == 0)
2917 {
2918 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002919 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002920 }
2921
Jamie Madill62d31cb2015-09-11 13:25:51 -04002922 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002923 {
2924 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002925 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002926 InvalidOperation()
2927 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002928 return false;
2929 }
2930 }
2931
Geoff Lange0cff192017-05-30 13:04:56 -04002932 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002933 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002934 {
Geoff Lange0cff192017-05-30 13:04:56 -04002935 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002936 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2937 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002938 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002939 return false;
2940 }
Geoff Lange0cff192017-05-30 13:04:56 -04002941
Geoff Lang9ab5b822017-05-30 16:19:23 -04002942 // Detect that the vertex shader input types match the attribute types
2943 if (!ValidateVertexShaderAttributeTypeMatch(context))
2944 {
2945 return false;
2946 }
2947
Geoff Lange0cff192017-05-30 13:04:56 -04002948 // Detect that the color buffer types match the fragment shader output types
2949 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2950 {
2951 return false;
2952 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002953 }
2954
Jamie Madill250d33f2014-06-06 17:09:03 -04002955 // No-op if zero count
2956 return (count > 0);
2957}
2958
Jamie Madillc1d770e2017-04-13 17:31:24 -04002959bool ValidateDrawArraysCommon(ValidationContext *context,
2960 GLenum mode,
2961 GLint first,
2962 GLsizei count,
2963 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002964{
Jamie Madillfd716582014-06-06 17:09:04 -04002965 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002966 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002967 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002968 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002969 }
2970
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002971 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002972 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002973 if (curTransformFeedback && curTransformFeedback->isActive() &&
2974 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002975 {
2976 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002977 // that does not match the current transform feedback object's draw mode (if transform
2978 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002979 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002980 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002981 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002982 }
2983
Jiajia Qind9671222016-11-29 16:30:31 +08002984 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002985 {
2986 return false;
2987 }
2988
Corentin Wallez71168a02016-12-19 15:11:18 -08002989 // Check the computation of maxVertex doesn't overflow.
2990 // - first < 0 or count < 0 have been checked as an error condition
2991 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2992 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2993 ASSERT(count > 0 && first >= 0);
2994 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2995 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002996 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002997 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002998 return false;
2999 }
3000
Corentin Wallez71168a02016-12-19 15:11:18 -08003001 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003002 {
3003 return false;
3004 }
3005
3006 return true;
3007}
3008
He Yunchaoced53ae2016-11-29 15:00:51 +08003009bool ValidateDrawArraysInstanced(Context *context,
3010 GLenum mode,
3011 GLint first,
3012 GLsizei count,
3013 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003014{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003015 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
Geoff Lang87a93302014-09-16 13:29:43 -04003016}
3017
He Yunchaoced53ae2016-11-29 15:00:51 +08003018bool ValidateDrawArraysInstancedANGLE(Context *context,
3019 GLenum mode,
3020 GLint first,
3021 GLsizei count,
3022 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003023{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003024 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003025 {
3026 return false;
3027 }
3028
Corentin Wallez0dc97812017-06-22 14:38:44 -04003029 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003030}
3031
Jiajia Qind9671222016-11-29 16:30:31 +08003032bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003033{
Jamie Madill250d33f2014-06-06 17:09:03 -04003034 switch (type)
3035 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003036 case GL_UNSIGNED_BYTE:
3037 case GL_UNSIGNED_SHORT:
3038 break;
3039 case GL_UNSIGNED_INT:
3040 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3041 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003042 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08003043 return false;
3044 }
3045 break;
3046 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003047 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08003048 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003049 }
3050
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003051 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003052
3053 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003054 if (curTransformFeedback && curTransformFeedback->isActive() &&
3055 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003056 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003057 // It is an invalid operation to call DrawElements, DrawRangeElements or
3058 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003059 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003060 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003061 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003062 }
3063
Jiajia Qind9671222016-11-29 16:30:31 +08003064 return true;
3065}
3066
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003067bool ValidateDrawElementsCommon(ValidationContext *context,
3068 GLenum mode,
3069 GLsizei count,
3070 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003071 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003072 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08003073{
3074 if (!ValidateDrawElementsBase(context, type))
3075 return false;
3076
3077 const State &state = context->getGLState();
3078
Corentin Wallez170efbf2017-05-02 13:45:01 -04003079 if (!ValidateDrawBase(context, mode, count))
3080 {
3081 return false;
3082 }
3083
Jamie Madill250d33f2014-06-06 17:09:03 -04003084 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003085 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003086 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003087 context->handleError(InvalidOperation() << "Index buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -04003088 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003089 }
3090
He Yunchaoced53ae2016-11-29 15:00:51 +08003091 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003092 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003093
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003094 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3095
3096 if (context->getExtensions().webglCompatibility)
3097 {
3098 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3099 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3100 {
3101 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3102 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3103 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003104 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003105 return false;
3106 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003107
3108 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3109 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3110 // error is generated.
3111 if (reinterpret_cast<intptr_t>(indices) < 0)
3112 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003113 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003114 return false;
3115 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003116 }
3117
3118 if (context->getExtensions().webglCompatibility ||
3119 !context->getGLState().areClientArraysEnabled())
3120 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003121 if (!elementArrayBuffer && count > 0)
3122 {
3123 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3124 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3125 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003126 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003127 return false;
3128 }
3129 }
3130
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003131 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003132 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003133 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003134 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003135 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3136 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3137 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3138 constexpr uint64_t kMaxTypeSize = 8;
3139 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3140 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3141 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003142
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003143 uint64_t typeSize = typeBytes;
3144 uint64_t elementCount = static_cast<uint64_t>(count);
3145 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3146
3147 // Doing the multiplication here is overflow-safe
3148 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3149
3150 // The offset can be any value, check for overflows
3151 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3152 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003153 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003154 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003155 return false;
3156 }
3157
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003158 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3159 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003160 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003161 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003162 return false;
3163 }
3164 }
3165 else if (!indices)
3166 {
3167 // This is an application error that would normally result in a crash,
3168 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003169 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04003170 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003171 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003172 }
3173
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003174 // Use the parameter buffer to retrieve and cache the index range.
3175 // TODO: offer fast path, with disabled index validation.
3176 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3177 const auto &params = context->getParams<HasIndexRange>();
3178 const auto &indexRangeOpt = params.getIndexRange();
3179 if (!indexRangeOpt.valid())
3180 {
3181 // Unexpected error.
3182 return false;
3183 }
3184
3185 // If we use an index greater than our maximum supported index range, return an error.
3186 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3187 // return an error if possible here.
3188 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
3189 {
3190 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3191 return false;
3192 }
3193
3194 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
3195 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003196 {
3197 return false;
3198 }
3199
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003200 // No op if there are no real indices in the index data (all are primitive restart).
3201 return (indexRangeOpt.value().vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003202}
3203
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003204bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
3205 GLenum mode,
3206 GLsizei count,
3207 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003208 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003209 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003210{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003211 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003212}
3213
Geoff Lang3edfe032015-09-04 16:38:24 -04003214bool ValidateDrawElementsInstancedANGLE(Context *context,
3215 GLenum mode,
3216 GLsizei count,
3217 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003218 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003219 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003220{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003221 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003222 {
3223 return false;
3224 }
3225
Corentin Wallez0dc97812017-06-22 14:38:44 -04003226 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003227}
3228
He Yunchaoced53ae2016-11-29 15:00:51 +08003229bool ValidateFramebufferTextureBase(Context *context,
3230 GLenum target,
3231 GLenum attachment,
3232 GLuint texture,
3233 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003234{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003235 if (!ValidFramebufferTarget(target))
3236 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003237 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003238 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003239 }
3240
3241 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003242 {
3243 return false;
3244 }
3245
Jamie Madill55ec3b12014-07-03 10:38:57 -04003246 if (texture != 0)
3247 {
3248 gl::Texture *tex = context->getTexture(texture);
3249
Jamie Madillbe849e42017-05-02 15:49:00 -04003250 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003251 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003252 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003253 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003254 }
3255
3256 if (level < 0)
3257 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003258 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003259 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003260 }
3261 }
3262
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003263 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003264 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003265
Jamie Madill84115c92015-04-23 15:00:07 -04003266 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003267 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003268 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003269 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003270 }
3271
3272 return true;
3273}
3274
Geoff Langb1196682014-07-23 13:47:29 -04003275bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003276{
3277 if (program == 0)
3278 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003279 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003280 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003281 }
3282
Dian Xiang769769a2015-09-09 15:20:08 -07003283 gl::Program *programObject = GetValidProgram(context, program);
3284 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003285 {
3286 return false;
3287 }
3288
Jamie Madill0063c512014-08-25 15:47:53 -04003289 if (!programObject || !programObject->isLinked())
3290 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003291 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003292 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003293 }
3294
Geoff Lang7dd2e102014-11-10 15:19:26 -05003295 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003296 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003297 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003298 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003299 }
3300
Jamie Madill0063c512014-08-25 15:47:53 -04003301 return true;
3302}
3303
Geoff Langf41d0ee2016-10-07 13:04:23 -04003304static bool ValidateSizedGetUniform(Context *context,
3305 GLuint program,
3306 GLint location,
3307 GLsizei bufSize,
3308 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003309{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003310 if (length)
3311 {
3312 *length = 0;
3313 }
3314
Jamie Madill78f41802014-08-25 15:47:55 -04003315 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003316 {
Jamie Madill78f41802014-08-25 15:47:55 -04003317 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003318 }
3319
Geoff Langf41d0ee2016-10-07 13:04:23 -04003320 if (bufSize < 0)
3321 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003322 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003323 return false;
3324 }
3325
Jamie Madilla502c742014-08-28 17:19:13 -04003326 gl::Program *programObject = context->getProgram(program);
3327 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003328
Jamie Madill78f41802014-08-25 15:47:55 -04003329 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003330 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003331 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003332 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003333 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003334 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003335 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003336 }
3337
Geoff Langf41d0ee2016-10-07 13:04:23 -04003338 if (length)
3339 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003340 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003341 }
3342
Jamie Madill0063c512014-08-25 15:47:53 -04003343 return true;
3344}
3345
He Yunchaoced53ae2016-11-29 15:00:51 +08003346bool ValidateGetnUniformfvEXT(Context *context,
3347 GLuint program,
3348 GLint location,
3349 GLsizei bufSize,
3350 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003351{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003352 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003353}
3354
He Yunchaoced53ae2016-11-29 15:00:51 +08003355bool ValidateGetnUniformivEXT(Context *context,
3356 GLuint program,
3357 GLint location,
3358 GLsizei bufSize,
3359 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003360{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003361 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3362}
3363
3364bool ValidateGetUniformfvRobustANGLE(Context *context,
3365 GLuint program,
3366 GLint location,
3367 GLsizei bufSize,
3368 GLsizei *length,
3369 GLfloat *params)
3370{
3371 if (!ValidateRobustEntryPoint(context, bufSize))
3372 {
3373 return false;
3374 }
3375
3376 // bufSize is validated in ValidateSizedGetUniform
3377 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3378}
3379
3380bool ValidateGetUniformivRobustANGLE(Context *context,
3381 GLuint program,
3382 GLint location,
3383 GLsizei bufSize,
3384 GLsizei *length,
3385 GLint *params)
3386{
3387 if (!ValidateRobustEntryPoint(context, bufSize))
3388 {
3389 return false;
3390 }
3391
3392 // bufSize is validated in ValidateSizedGetUniform
3393 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3394}
3395
3396bool ValidateGetUniformuivRobustANGLE(Context *context,
3397 GLuint program,
3398 GLint location,
3399 GLsizei bufSize,
3400 GLsizei *length,
3401 GLuint *params)
3402{
3403 if (!ValidateRobustEntryPoint(context, bufSize))
3404 {
3405 return false;
3406 }
3407
3408 if (context->getClientMajorVersion() < 3)
3409 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003410 context->handleError(InvalidOperation() << "Entry point requires at least OpenGL ES 3.0.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003411 return false;
3412 }
3413
3414 // bufSize is validated in ValidateSizedGetUniform
3415 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003416}
3417
He Yunchaoced53ae2016-11-29 15:00:51 +08003418bool ValidateDiscardFramebufferBase(Context *context,
3419 GLenum target,
3420 GLsizei numAttachments,
3421 const GLenum *attachments,
3422 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003423{
3424 if (numAttachments < 0)
3425 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003426 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003427 return false;
3428 }
3429
3430 for (GLsizei i = 0; i < numAttachments; ++i)
3431 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003432 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003433 {
3434 if (defaultFramebuffer)
3435 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003436 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003437 return false;
3438 }
3439
3440 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3441 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003442 context->handleError(InvalidOperation() << "Requested color attachment is "
3443 "greater than the maximum supported "
3444 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003445 return false;
3446 }
3447 }
3448 else
3449 {
3450 switch (attachments[i])
3451 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003452 case GL_DEPTH_ATTACHMENT:
3453 case GL_STENCIL_ATTACHMENT:
3454 case GL_DEPTH_STENCIL_ATTACHMENT:
3455 if (defaultFramebuffer)
3456 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003457 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3458 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003459 return false;
3460 }
3461 break;
3462 case GL_COLOR:
3463 case GL_DEPTH:
3464 case GL_STENCIL:
3465 if (!defaultFramebuffer)
3466 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003467 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3468 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003469 return false;
3470 }
3471 break;
3472 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003473 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003474 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003475 }
3476 }
3477 }
3478
3479 return true;
3480}
3481
Austin Kinross6ee1e782015-05-29 17:05:37 -07003482bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3483{
3484 // Note that debug marker calls must not set error state
3485
3486 if (length < 0)
3487 {
3488 return false;
3489 }
3490
3491 if (marker == nullptr)
3492 {
3493 return false;
3494 }
3495
3496 return true;
3497}
3498
3499bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3500{
3501 // Note that debug marker calls must not set error state
3502
3503 if (length < 0)
3504 {
3505 return false;
3506 }
3507
3508 if (length > 0 && marker == nullptr)
3509 {
3510 return false;
3511 }
3512
3513 return true;
3514}
3515
Geoff Langdcab33b2015-07-21 13:03:16 -04003516bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003517 GLenum target,
3518 egl::Image *image)
3519{
Geoff Langa8406172015-07-21 16:53:39 -04003520 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3521 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003522 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003523 return false;
3524 }
3525
3526 switch (target)
3527 {
3528 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003529 if (!context->getExtensions().eglImage)
3530 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003531 context->handleError(InvalidEnum()
3532 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003533 }
3534 break;
3535
3536 case GL_TEXTURE_EXTERNAL_OES:
3537 if (!context->getExtensions().eglImageExternal)
3538 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003539 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3540 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003541 }
Geoff Langa8406172015-07-21 16:53:39 -04003542 break;
3543
3544 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003545 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003546 return false;
3547 }
3548
Jamie Madill61e16b42017-06-19 11:13:23 -04003549 ASSERT(context->getCurrentDisplay());
3550 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003551 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003552 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003553 return false;
3554 }
3555
3556 if (image->getSamples() > 0)
3557 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003558 context->handleError(InvalidOperation()
3559 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003560 return false;
3561 }
3562
Geoff Langca271392017-04-05 12:30:00 -04003563 const TextureCaps &textureCaps =
3564 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003565 if (!textureCaps.texturable)
3566 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003567 context->handleError(InvalidOperation()
3568 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003569 return false;
3570 }
3571
Geoff Langdcab33b2015-07-21 13:03:16 -04003572 return true;
3573}
3574
3575bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003576 GLenum target,
3577 egl::Image *image)
3578{
Geoff Langa8406172015-07-21 16:53:39 -04003579 if (!context->getExtensions().eglImage)
3580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003581 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003582 return false;
3583 }
3584
3585 switch (target)
3586 {
3587 case GL_RENDERBUFFER:
3588 break;
3589
3590 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003591 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003592 return false;
3593 }
3594
Jamie Madill61e16b42017-06-19 11:13:23 -04003595 ASSERT(context->getCurrentDisplay());
3596 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003597 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003598 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003599 return false;
3600 }
3601
Geoff Langca271392017-04-05 12:30:00 -04003602 const TextureCaps &textureCaps =
3603 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003604 if (!textureCaps.renderable)
3605 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003606 context->handleError(InvalidOperation()
3607 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003608 return false;
3609 }
3610
Geoff Langdcab33b2015-07-21 13:03:16 -04003611 return true;
3612}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003613
3614bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3615{
Geoff Lang36167ab2015-12-07 10:27:14 -05003616 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003617 {
3618 // The default VAO should always exist
3619 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003620 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003621 return false;
3622 }
3623
3624 return true;
3625}
3626
Geoff Langc5629752015-12-07 16:29:04 -05003627bool ValidateProgramBinaryBase(Context *context,
3628 GLuint program,
3629 GLenum binaryFormat,
3630 const void *binary,
3631 GLint length)
3632{
3633 Program *programObject = GetValidProgram(context, program);
3634 if (programObject == nullptr)
3635 {
3636 return false;
3637 }
3638
3639 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3640 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3641 programBinaryFormats.end())
3642 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003643 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003644 return false;
3645 }
3646
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003647 if (context->hasActiveTransformFeedback(program))
3648 {
3649 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003650 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3651 "is associated with an active transform "
3652 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003653 return false;
3654 }
3655
Geoff Langc5629752015-12-07 16:29:04 -05003656 return true;
3657}
3658
3659bool ValidateGetProgramBinaryBase(Context *context,
3660 GLuint program,
3661 GLsizei bufSize,
3662 GLsizei *length,
3663 GLenum *binaryFormat,
3664 void *binary)
3665{
3666 Program *programObject = GetValidProgram(context, program);
3667 if (programObject == nullptr)
3668 {
3669 return false;
3670 }
3671
3672 if (!programObject->isLinked())
3673 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003674 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003675 return false;
3676 }
3677
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003678 if (context->getCaps().programBinaryFormats.empty())
3679 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003680 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003681 return false;
3682 }
3683
Geoff Langc5629752015-12-07 16:29:04 -05003684 return true;
3685}
Jamie Madillc29968b2016-01-20 11:17:23 -05003686
Jamie Madillc29968b2016-01-20 11:17:23 -05003687bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3688{
3689 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003690 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003691 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003692 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3693 return false;
3694 }
3695 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3696 {
3697 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003698 return false;
3699 }
3700
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003701 ASSERT(context->getGLState().getDrawFramebuffer());
3702 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003703 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3704
3705 // This should come first before the check for the default frame buffer
3706 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3707 // rather than INVALID_OPERATION
3708 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3709 {
3710 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3711
3712 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003713 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3714 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003715 {
3716 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003717 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3718 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3719 // 3.1 is still a bit ambiguous about the error, but future specs are
3720 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003721 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003722 return false;
3723 }
3724 else if (bufs[colorAttachment] >= maxColorAttachment)
3725 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003726 context->handleError(InvalidOperation()
3727 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003728 return false;
3729 }
3730 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3731 frameBufferId != 0)
3732 {
3733 // INVALID_OPERATION-GL is bound to buffer and ith argument
3734 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003735 context->handleError(InvalidOperation()
3736 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003737 return false;
3738 }
3739 }
3740
3741 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3742 // and n is not 1 or bufs is bound to value other than BACK and NONE
3743 if (frameBufferId == 0)
3744 {
3745 if (n != 1)
3746 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003747 context->handleError(InvalidOperation()
3748 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003749 return false;
3750 }
3751
3752 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3753 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003754 context->handleError(
3755 InvalidOperation()
3756 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003757 return false;
3758 }
3759 }
3760
3761 return true;
3762}
3763
Geoff Lang496c02d2016-10-20 11:38:11 -07003764bool ValidateGetBufferPointervBase(Context *context,
3765 GLenum target,
3766 GLenum pname,
3767 GLsizei *length,
3768 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003769{
Geoff Lang496c02d2016-10-20 11:38:11 -07003770 if (length)
3771 {
3772 *length = 0;
3773 }
3774
3775 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3776 {
3777 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003778 InvalidOperation()
3779 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003780 return false;
3781 }
3782
Olli Etuaho4f667482016-03-30 15:56:35 +03003783 if (!ValidBufferTarget(context, target))
3784 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003785 context->handleError(InvalidEnum() << "Buffer target not valid: 0x" << std::hex
3786 << std::uppercase << target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003787 return false;
3788 }
3789
Geoff Lang496c02d2016-10-20 11:38:11 -07003790 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003791 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003792 case GL_BUFFER_MAP_POINTER:
3793 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003794
Geoff Lang496c02d2016-10-20 11:38:11 -07003795 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003796 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003797 return false;
3798 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003799
3800 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3801 // target bound to zero generate an INVALID_OPERATION error."
3802 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003803 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003804 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003805 context->handleError(InvalidOperation()
3806 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003807 return false;
3808 }
3809
Geoff Lang496c02d2016-10-20 11:38:11 -07003810 if (length)
3811 {
3812 *length = 1;
3813 }
3814
Olli Etuaho4f667482016-03-30 15:56:35 +03003815 return true;
3816}
3817
3818bool ValidateUnmapBufferBase(Context *context, GLenum target)
3819{
3820 if (!ValidBufferTarget(context, target))
3821 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003822 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003823 return false;
3824 }
3825
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003826 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003827
3828 if (buffer == nullptr || !buffer->isMapped())
3829 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003830 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003831 return false;
3832 }
3833
3834 return true;
3835}
3836
3837bool ValidateMapBufferRangeBase(Context *context,
3838 GLenum target,
3839 GLintptr offset,
3840 GLsizeiptr length,
3841 GLbitfield access)
3842{
3843 if (!ValidBufferTarget(context, target))
3844 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003845 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003846 return false;
3847 }
3848
Brandon Jones6cad5662017-06-14 13:25:13 -07003849 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003850 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003851 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3852 return false;
3853 }
3854
3855 if (length < 0)
3856 {
3857 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003858 return false;
3859 }
3860
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003861 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003862
3863 if (!buffer)
3864 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003865 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003866 return false;
3867 }
3868
3869 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003870 CheckedNumeric<size_t> checkedOffset(offset);
3871 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003872
Jamie Madille2e406c2016-06-02 13:04:10 -04003873 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003874 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003875 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003876 return false;
3877 }
3878
3879 // Check for invalid bits in the mask
3880 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3881 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3882 GL_MAP_UNSYNCHRONIZED_BIT;
3883
3884 if (access & ~(allAccessBits))
3885 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003886 context->handleError(InvalidValue()
3887 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003888 return false;
3889 }
3890
3891 if (length == 0)
3892 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003893 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003894 return false;
3895 }
3896
3897 if (buffer->isMapped())
3898 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003899 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003900 return false;
3901 }
3902
3903 // Check for invalid bit combinations
3904 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3905 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003906 context->handleError(InvalidOperation()
3907 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003908 return false;
3909 }
3910
3911 GLbitfield writeOnlyBits =
3912 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3913
3914 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3915 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003916 context->handleError(InvalidOperation()
3917 << "Invalid access bits when mapping buffer for reading: 0x"
3918 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003919 return false;
3920 }
3921
3922 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3923 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003924 context->handleError(
3925 InvalidOperation()
3926 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003927 return false;
3928 }
Geoff Lang79f71042017-08-14 16:43:43 -04003929
3930 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003931}
3932
3933bool ValidateFlushMappedBufferRangeBase(Context *context,
3934 GLenum target,
3935 GLintptr offset,
3936 GLsizeiptr length)
3937{
Brandon Jones6cad5662017-06-14 13:25:13 -07003938 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003939 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003940 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3941 return false;
3942 }
3943
3944 if (length < 0)
3945 {
3946 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003947 return false;
3948 }
3949
3950 if (!ValidBufferTarget(context, target))
3951 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003952 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003953 return false;
3954 }
3955
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003956 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003957
3958 if (buffer == nullptr)
3959 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003960 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003961 return false;
3962 }
3963
3964 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3965 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003966 context->handleError(InvalidOperation()
3967 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003968 return false;
3969 }
3970
3971 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003972 CheckedNumeric<size_t> checkedOffset(offset);
3973 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003974
Jamie Madille2e406c2016-06-02 13:04:10 -04003975 if (!checkedSize.IsValid() ||
3976 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003977 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003978 context->handleError(InvalidValue()
3979 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003980 return false;
3981 }
3982
3983 return true;
3984}
3985
Olli Etuaho41997e72016-03-10 13:38:39 +02003986bool ValidateGenOrDelete(Context *context, GLint n)
3987{
3988 if (n < 0)
3989 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003990 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003991 return false;
3992 }
3993 return true;
3994}
3995
Geoff Langff5b2d52016-09-07 11:32:23 -04003996bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3997{
3998 if (!context->getExtensions().robustClientMemory)
3999 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004000 context->handleError(InvalidOperation()
4001 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004002 return false;
4003 }
4004
4005 if (bufSize < 0)
4006 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004007 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004008 return false;
4009 }
4010
4011 return true;
4012}
4013
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004014bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4015{
4016 if (bufSize < numParams)
4017 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004018 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4019 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004020 return false;
4021 }
4022
4023 return true;
4024}
4025
Jamie Madillbe849e42017-05-02 15:49:00 -04004026bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
4027 GLenum target,
4028 GLenum attachment,
4029 GLenum pname,
4030 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004031{
Geoff Langff5b2d52016-09-07 11:32:23 -04004032 if (!ValidFramebufferTarget(target))
4033 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004034 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004035 return false;
4036 }
4037
4038 int clientVersion = context->getClientMajorVersion();
4039
4040 switch (pname)
4041 {
4042 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4043 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4044 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4045 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4046 break;
4047
Martin Radeve5285d22017-07-14 16:23:53 +03004048 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4049 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4050 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4051 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4052 if (clientVersion < 3 || !context->getExtensions().multiview)
4053 {
4054 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4055 return false;
4056 }
4057 break;
4058
Geoff Langff5b2d52016-09-07 11:32:23 -04004059 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4060 if (clientVersion < 3 && !context->getExtensions().sRGB)
4061 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004062 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004063 return false;
4064 }
4065 break;
4066
4067 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4068 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4069 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4070 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4071 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4072 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4073 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4074 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4075 if (clientVersion < 3)
4076 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004077 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004078 return false;
4079 }
4080 break;
4081
4082 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004083 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004084 return false;
4085 }
4086
4087 // Determine if the attachment is a valid enum
4088 switch (attachment)
4089 {
4090 case GL_BACK:
4091 case GL_FRONT:
4092 case GL_DEPTH:
4093 case GL_STENCIL:
4094 case GL_DEPTH_STENCIL_ATTACHMENT:
4095 if (clientVersion < 3)
4096 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004097 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004098 return false;
4099 }
4100 break;
4101
4102 case GL_DEPTH_ATTACHMENT:
4103 case GL_STENCIL_ATTACHMENT:
4104 break;
4105
4106 default:
4107 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4108 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4109 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004110 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004111 return false;
4112 }
4113 break;
4114 }
4115
4116 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4117 ASSERT(framebuffer);
4118
4119 if (framebuffer->id() == 0)
4120 {
4121 if (clientVersion < 3)
4122 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004123 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004124 return false;
4125 }
4126
4127 switch (attachment)
4128 {
4129 case GL_BACK:
4130 case GL_DEPTH:
4131 case GL_STENCIL:
4132 break;
4133
4134 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004135 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004136 return false;
4137 }
4138 }
4139 else
4140 {
4141 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4142 {
4143 // Valid attachment query
4144 }
4145 else
4146 {
4147 switch (attachment)
4148 {
4149 case GL_DEPTH_ATTACHMENT:
4150 case GL_STENCIL_ATTACHMENT:
4151 break;
4152
4153 case GL_DEPTH_STENCIL_ATTACHMENT:
4154 if (!framebuffer->hasValidDepthStencil())
4155 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004156 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004157 return false;
4158 }
4159 break;
4160
4161 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004162 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004163 return false;
4164 }
4165 }
4166 }
4167
4168 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4169 if (attachmentObject)
4170 {
4171 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4172 attachmentObject->type() == GL_TEXTURE ||
4173 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4174
4175 switch (pname)
4176 {
4177 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4178 if (attachmentObject->type() != GL_RENDERBUFFER &&
4179 attachmentObject->type() != GL_TEXTURE)
4180 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004181 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004182 return false;
4183 }
4184 break;
4185
4186 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4187 if (attachmentObject->type() != GL_TEXTURE)
4188 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004189 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004190 return false;
4191 }
4192 break;
4193
4194 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4195 if (attachmentObject->type() != GL_TEXTURE)
4196 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004197 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004198 return false;
4199 }
4200 break;
4201
4202 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4203 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4204 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004205 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004206 return false;
4207 }
4208 break;
4209
4210 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4211 if (attachmentObject->type() != GL_TEXTURE)
4212 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004213 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004214 return false;
4215 }
4216 break;
4217
4218 default:
4219 break;
4220 }
4221 }
4222 else
4223 {
4224 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4225 // is NONE, then querying any other pname will generate INVALID_ENUM.
4226
4227 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4228 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4229 // INVALID_OPERATION for all other pnames
4230
4231 switch (pname)
4232 {
4233 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4234 break;
4235
4236 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4237 if (clientVersion < 3)
4238 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004239 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004240 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004241 return false;
4242 }
4243 break;
4244
4245 default:
4246 if (clientVersion < 3)
4247 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004248 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004249 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004250 return false;
4251 }
4252 else
4253 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004254 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004255 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004256 return false;
4257 }
4258 }
4259 }
4260
Martin Radeve5285d22017-07-14 16:23:53 +03004261 if (numParams)
4262 {
4263 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4264 {
4265 // Only when the viewport offsets are queried we can have a varying number of output
4266 // parameters.
4267 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4268 *numParams = numViews * 2;
4269 }
4270 else
4271 {
4272 // For all other queries we can have only one output parameter.
4273 *numParams = 1;
4274 }
4275 }
4276
Geoff Langff5b2d52016-09-07 11:32:23 -04004277 return true;
4278}
4279
4280bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4281 GLenum target,
4282 GLenum attachment,
4283 GLenum pname,
4284 GLsizei bufSize,
4285 GLsizei *numParams)
4286{
4287 if (!ValidateRobustEntryPoint(context, bufSize))
4288 {
4289 return false;
4290 }
4291
Jamie Madillbe849e42017-05-02 15:49:00 -04004292 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4293 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004294 {
4295 return false;
4296 }
4297
4298 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4299 {
4300 return false;
4301 }
4302
4303 return true;
4304}
4305
Geoff Langff5b2d52016-09-07 11:32:23 -04004306bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4307 GLenum target,
4308 GLenum pname,
4309 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004310 GLsizei *length,
4311 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004312{
4313 if (!ValidateRobustEntryPoint(context, bufSize))
4314 {
4315 return false;
4316 }
4317
Geoff Langebebe1c2016-10-14 12:01:31 -04004318 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004319 {
4320 return false;
4321 }
4322
Geoff Langebebe1c2016-10-14 12:01:31 -04004323 if (!ValidateRobustBufferSize(context, bufSize, *length))
4324 {
4325 return false;
4326 }
4327
4328 return true;
4329}
4330
4331bool ValidateGetBufferParameteri64v(ValidationContext *context,
4332 GLenum target,
4333 GLenum pname,
4334 GLint64 *params)
4335{
4336 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4337}
4338
4339bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4340 GLenum target,
4341 GLenum pname,
4342 GLsizei bufSize,
4343 GLsizei *length,
4344 GLint64 *params)
4345{
4346 if (!ValidateRobustEntryPoint(context, bufSize))
4347 {
4348 return false;
4349 }
4350
4351 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4352 {
4353 return false;
4354 }
4355
4356 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004357 {
4358 return false;
4359 }
4360
4361 return true;
4362}
4363
Jamie Madillbe849e42017-05-02 15:49:00 -04004364bool ValidateGetProgramivBase(ValidationContext *context,
4365 GLuint program,
4366 GLenum pname,
4367 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004368{
4369 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004370 if (numParams)
4371 {
4372 *numParams = 1;
4373 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004374
4375 Program *programObject = GetValidProgram(context, program);
4376 if (!programObject)
4377 {
4378 return false;
4379 }
4380
4381 switch (pname)
4382 {
4383 case GL_DELETE_STATUS:
4384 case GL_LINK_STATUS:
4385 case GL_VALIDATE_STATUS:
4386 case GL_INFO_LOG_LENGTH:
4387 case GL_ATTACHED_SHADERS:
4388 case GL_ACTIVE_ATTRIBUTES:
4389 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4390 case GL_ACTIVE_UNIFORMS:
4391 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4392 break;
4393
4394 case GL_PROGRAM_BINARY_LENGTH:
4395 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004397 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4398 "requires GL_OES_get_program_binary or "
4399 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004400 return false;
4401 }
4402 break;
4403
4404 case GL_ACTIVE_UNIFORM_BLOCKS:
4405 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4406 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4407 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4408 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4409 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4410 if (context->getClientMajorVersion() < 3)
4411 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004412 context->handleError(InvalidEnum() << "Querying requires at least ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004413 return false;
4414 }
4415 break;
4416
Yunchao He61afff12017-03-14 15:34:03 +08004417 case GL_PROGRAM_SEPARABLE:
4418 if (context->getClientVersion() < Version(3, 1))
4419 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004420 context->handleError(InvalidEnum() << "Querying requires at least ES 3.1.");
Yunchao He61afff12017-03-14 15:34:03 +08004421 return false;
4422 }
4423 break;
4424
Geoff Langff5b2d52016-09-07 11:32:23 -04004425 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004426 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004427 return false;
4428 }
4429
4430 return true;
4431}
4432
4433bool ValidateGetProgramivRobustANGLE(Context *context,
4434 GLuint program,
4435 GLenum pname,
4436 GLsizei bufSize,
4437 GLsizei *numParams)
4438{
4439 if (!ValidateRobustEntryPoint(context, bufSize))
4440 {
4441 return false;
4442 }
4443
Jamie Madillbe849e42017-05-02 15:49:00 -04004444 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004445 {
4446 return false;
4447 }
4448
4449 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4450 {
4451 return false;
4452 }
4453
4454 return true;
4455}
4456
Geoff Lang740d9022016-10-07 11:20:52 -04004457bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4458 GLenum target,
4459 GLenum pname,
4460 GLsizei bufSize,
4461 GLsizei *length,
4462 GLint *params)
4463{
4464 if (!ValidateRobustEntryPoint(context, bufSize))
4465 {
4466 return false;
4467 }
4468
4469 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4470 {
4471 return false;
4472 }
4473
4474 if (!ValidateRobustBufferSize(context, bufSize, *length))
4475 {
4476 return false;
4477 }
4478
4479 return true;
4480}
4481
Geoff Langd7d0ed32016-10-07 11:33:51 -04004482bool ValidateGetShaderivRobustANGLE(Context *context,
4483 GLuint shader,
4484 GLenum pname,
4485 GLsizei bufSize,
4486 GLsizei *length,
4487 GLint *params)
4488{
4489 if (!ValidateRobustEntryPoint(context, bufSize))
4490 {
4491 return false;
4492 }
4493
4494 if (!ValidateGetShaderivBase(context, shader, pname, length))
4495 {
4496 return false;
4497 }
4498
4499 if (!ValidateRobustBufferSize(context, bufSize, *length))
4500 {
4501 return false;
4502 }
4503
4504 return true;
4505}
4506
Geoff Langc1984ed2016-10-07 12:41:00 -04004507bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4508 GLenum target,
4509 GLenum pname,
4510 GLsizei bufSize,
4511 GLsizei *length,
4512 GLfloat *params)
4513{
4514 if (!ValidateRobustEntryPoint(context, bufSize))
4515 {
4516 return false;
4517 }
4518
4519 if (!ValidateGetTexParameterBase(context, target, pname, length))
4520 {
4521 return false;
4522 }
4523
4524 if (!ValidateRobustBufferSize(context, bufSize, *length))
4525 {
4526 return false;
4527 }
4528
4529 return true;
4530}
4531
Geoff Langc1984ed2016-10-07 12:41:00 -04004532bool ValidateGetTexParameterivRobustANGLE(Context *context,
4533 GLenum target,
4534 GLenum pname,
4535 GLsizei bufSize,
4536 GLsizei *length,
4537 GLint *params)
4538{
4539 if (!ValidateRobustEntryPoint(context, bufSize))
4540 {
4541 return false;
4542 }
4543
4544 if (!ValidateGetTexParameterBase(context, target, pname, length))
4545 {
4546 return false;
4547 }
4548
4549 if (!ValidateRobustBufferSize(context, bufSize, *length))
4550 {
4551 return false;
4552 }
4553
4554 return true;
4555}
4556
Geoff Langc1984ed2016-10-07 12:41:00 -04004557bool ValidateTexParameterfvRobustANGLE(Context *context,
4558 GLenum target,
4559 GLenum pname,
4560 GLsizei bufSize,
4561 const GLfloat *params)
4562{
4563 if (!ValidateRobustEntryPoint(context, bufSize))
4564 {
4565 return false;
4566 }
4567
4568 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4569}
4570
Geoff Langc1984ed2016-10-07 12:41:00 -04004571bool ValidateTexParameterivRobustANGLE(Context *context,
4572 GLenum target,
4573 GLenum pname,
4574 GLsizei bufSize,
4575 const GLint *params)
4576{
4577 if (!ValidateRobustEntryPoint(context, bufSize))
4578 {
4579 return false;
4580 }
4581
4582 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4583}
4584
4585bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4586{
4587 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4588}
4589
4590bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4591 GLuint sampler,
4592 GLenum pname,
4593 GLuint bufSize,
4594 GLsizei *length,
4595 GLfloat *params)
4596{
4597 if (!ValidateRobustEntryPoint(context, bufSize))
4598 {
4599 return false;
4600 }
4601
4602 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4603 {
4604 return false;
4605 }
4606
4607 if (!ValidateRobustBufferSize(context, bufSize, *length))
4608 {
4609 return false;
4610 }
4611
4612 return true;
4613}
4614
4615bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4616{
4617 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4618}
4619
4620bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4621 GLuint sampler,
4622 GLenum pname,
4623 GLuint bufSize,
4624 GLsizei *length,
4625 GLint *params)
4626{
4627 if (!ValidateRobustEntryPoint(context, bufSize))
4628 {
4629 return false;
4630 }
4631
4632 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4633 {
4634 return false;
4635 }
4636
4637 if (!ValidateRobustBufferSize(context, bufSize, *length))
4638 {
4639 return false;
4640 }
4641
4642 return true;
4643}
4644
4645bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4646{
4647 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4648}
4649
4650bool ValidateSamplerParameterfv(Context *context,
4651 GLuint sampler,
4652 GLenum pname,
4653 const GLfloat *params)
4654{
4655 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4656}
4657
4658bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4659 GLuint sampler,
4660 GLenum pname,
4661 GLsizei bufSize,
4662 const GLfloat *params)
4663{
4664 if (!ValidateRobustEntryPoint(context, bufSize))
4665 {
4666 return false;
4667 }
4668
4669 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4670}
4671
4672bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4673{
4674 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4675}
4676
4677bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4678{
4679 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4680}
4681
4682bool ValidateSamplerParameterivRobustANGLE(Context *context,
4683 GLuint sampler,
4684 GLenum pname,
4685 GLsizei bufSize,
4686 const GLint *params)
4687{
4688 if (!ValidateRobustEntryPoint(context, bufSize))
4689 {
4690 return false;
4691 }
4692
4693 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4694}
4695
Geoff Lang0b031062016-10-13 14:30:04 -04004696bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4697 GLuint index,
4698 GLenum pname,
4699 GLsizei bufSize,
4700 GLsizei *length,
4701 GLfloat *params)
4702{
4703 if (!ValidateRobustEntryPoint(context, bufSize))
4704 {
4705 return false;
4706 }
4707
4708 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4709 {
4710 return false;
4711 }
4712
4713 if (!ValidateRobustBufferSize(context, bufSize, *length))
4714 {
4715 return false;
4716 }
4717
4718 return true;
4719}
4720
Geoff Lang0b031062016-10-13 14:30:04 -04004721bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4722 GLuint index,
4723 GLenum pname,
4724 GLsizei bufSize,
4725 GLsizei *length,
4726 GLint *params)
4727{
4728 if (!ValidateRobustEntryPoint(context, bufSize))
4729 {
4730 return false;
4731 }
4732
4733 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4734 {
4735 return false;
4736 }
4737
4738 if (!ValidateRobustBufferSize(context, bufSize, *length))
4739 {
4740 return false;
4741 }
4742
4743 return true;
4744}
4745
Geoff Lang0b031062016-10-13 14:30:04 -04004746bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4747 GLuint index,
4748 GLenum pname,
4749 GLsizei bufSize,
4750 GLsizei *length,
4751 void **pointer)
4752{
4753 if (!ValidateRobustEntryPoint(context, bufSize))
4754 {
4755 return false;
4756 }
4757
4758 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4759 {
4760 return false;
4761 }
4762
4763 if (!ValidateRobustBufferSize(context, bufSize, *length))
4764 {
4765 return false;
4766 }
4767
4768 return true;
4769}
4770
4771bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
4772{
4773 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4774}
4775
4776bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4777 GLuint index,
4778 GLenum pname,
4779 GLsizei bufSize,
4780 GLsizei *length,
4781 GLint *params)
4782{
4783 if (!ValidateRobustEntryPoint(context, bufSize))
4784 {
4785 return false;
4786 }
4787
4788 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4789 {
4790 return false;
4791 }
4792
4793 if (!ValidateRobustBufferSize(context, bufSize, *length))
4794 {
4795 return false;
4796 }
4797
4798 return true;
4799}
4800
4801bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
4802{
4803 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4804}
4805
4806bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4807 GLuint index,
4808 GLenum pname,
4809 GLsizei bufSize,
4810 GLsizei *length,
4811 GLuint *params)
4812{
4813 if (!ValidateRobustEntryPoint(context, bufSize))
4814 {
4815 return false;
4816 }
4817
4818 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4819 {
4820 return false;
4821 }
4822
4823 if (!ValidateRobustBufferSize(context, bufSize, *length))
4824 {
4825 return false;
4826 }
4827
4828 return true;
4829}
4830
Geoff Lang6899b872016-10-14 11:30:13 -04004831bool ValidateGetActiveUniformBlockiv(Context *context,
4832 GLuint program,
4833 GLuint uniformBlockIndex,
4834 GLenum pname,
4835 GLint *params)
4836{
4837 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
4838}
4839
4840bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4841 GLuint program,
4842 GLuint uniformBlockIndex,
4843 GLenum pname,
4844 GLsizei bufSize,
4845 GLsizei *length,
4846 GLint *params)
4847{
4848 if (!ValidateRobustEntryPoint(context, bufSize))
4849 {
4850 return false;
4851 }
4852
4853 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4854 {
4855 return false;
4856 }
4857
4858 if (!ValidateRobustBufferSize(context, bufSize, *length))
4859 {
4860 return false;
4861 }
4862
4863 return true;
4864}
4865
Geoff Lang0a9661f2016-10-20 10:59:20 -07004866bool ValidateGetInternalFormativ(Context *context,
4867 GLenum target,
4868 GLenum internalformat,
4869 GLenum pname,
4870 GLsizei bufSize,
4871 GLint *params)
4872{
4873 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4874 nullptr);
4875}
4876
4877bool ValidateGetInternalFormativRobustANGLE(Context *context,
4878 GLenum target,
4879 GLenum internalformat,
4880 GLenum pname,
4881 GLsizei bufSize,
4882 GLsizei *length,
4883 GLint *params)
4884{
4885 if (!ValidateRobustEntryPoint(context, bufSize))
4886 {
4887 return false;
4888 }
4889
4890 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4891 {
4892 return false;
4893 }
4894
4895 if (!ValidateRobustBufferSize(context, bufSize, *length))
4896 {
4897 return false;
4898 }
4899
4900 return true;
4901}
4902
Shao80957d92017-02-20 21:25:59 +08004903bool ValidateVertexFormatBase(ValidationContext *context,
4904 GLuint attribIndex,
4905 GLint size,
4906 GLenum type,
4907 GLboolean pureInteger)
4908{
4909 const Caps &caps = context->getCaps();
4910 if (attribIndex >= caps.maxVertexAttributes)
4911 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004912 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004913 return false;
4914 }
4915
4916 if (size < 1 || size > 4)
4917 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004918 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004919 return false;
Shao80957d92017-02-20 21:25:59 +08004920 }
4921
4922 switch (type)
4923 {
4924 case GL_BYTE:
4925 case GL_UNSIGNED_BYTE:
4926 case GL_SHORT:
4927 case GL_UNSIGNED_SHORT:
4928 break;
4929
4930 case GL_INT:
4931 case GL_UNSIGNED_INT:
4932 if (context->getClientMajorVersion() < 3)
4933 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004934 context->handleError(InvalidEnum()
4935 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004936 return false;
4937 }
4938 break;
4939
4940 case GL_FIXED:
4941 case GL_FLOAT:
4942 if (pureInteger)
4943 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004944 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004945 return false;
4946 }
4947 break;
4948
4949 case GL_HALF_FLOAT:
4950 if (context->getClientMajorVersion() < 3)
4951 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004952 context->handleError(InvalidEnum()
4953 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004954 return false;
4955 }
4956 if (pureInteger)
4957 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004958 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004959 return false;
4960 }
4961 break;
4962
4963 case GL_INT_2_10_10_10_REV:
4964 case GL_UNSIGNED_INT_2_10_10_10_REV:
4965 if (context->getClientMajorVersion() < 3)
4966 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004967 context->handleError(InvalidEnum()
4968 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004969 return false;
4970 }
4971 if (pureInteger)
4972 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004973 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004974 return false;
4975 }
4976 if (size != 4)
4977 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004978 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4979 "UNSIGNED_INT_2_10_10_10_REV and "
4980 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004981 return false;
4982 }
4983 break;
4984
4985 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004986 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004987 return false;
4988 }
4989
4990 return true;
4991}
4992
Geoff Lang76e65652017-03-27 14:58:02 -04004993// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4994// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4995// specified clear value and the type of a buffer that is being cleared generates an
4996// INVALID_OPERATION error instead of producing undefined results
4997bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4998 GLint drawbuffer,
4999 const GLenum *validComponentTypes,
5000 size_t validComponentTypeCount)
5001{
5002 const FramebufferAttachment *attachment =
5003 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5004 if (attachment)
5005 {
5006 GLenum componentType = attachment->getFormat().info->componentType;
5007 const GLenum *end = validComponentTypes + validComponentTypeCount;
5008 if (std::find(validComponentTypes, end, componentType) == end)
5009 {
5010 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005011 InvalidOperation()
5012 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005013 return false;
5014 }
5015 }
5016
5017 return true;
5018}
5019
Corentin Wallezb2931602017-04-11 15:58:57 -04005020bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
5021 GLsizei imageSize,
5022 GLsizei dataSize)
5023{
5024 if (!ValidateRobustEntryPoint(context, dataSize))
5025 {
5026 return false;
5027 }
5028
5029 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
5030 if (pixelUnpackBuffer == nullptr)
5031 {
5032 if (dataSize < imageSize)
5033 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005034 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005035 }
5036 }
5037 return true;
5038}
5039
Jamie Madillbe849e42017-05-02 15:49:00 -04005040bool ValidateGetBufferParameterBase(ValidationContext *context,
5041 GLenum target,
5042 GLenum pname,
5043 bool pointerVersion,
5044 GLsizei *numParams)
5045{
5046 if (numParams)
5047 {
5048 *numParams = 0;
5049 }
5050
5051 if (!ValidBufferTarget(context, target))
5052 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005053 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005054 return false;
5055 }
5056
5057 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5058 if (!buffer)
5059 {
5060 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005061 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005062 return false;
5063 }
5064
5065 const Extensions &extensions = context->getExtensions();
5066
5067 switch (pname)
5068 {
5069 case GL_BUFFER_USAGE:
5070 case GL_BUFFER_SIZE:
5071 break;
5072
5073 case GL_BUFFER_ACCESS_OES:
5074 if (!extensions.mapBuffer)
5075 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005076 context->handleError(InvalidEnum()
5077 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005078 return false;
5079 }
5080 break;
5081
5082 case GL_BUFFER_MAPPED:
5083 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5084 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5085 !extensions.mapBufferRange)
5086 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005087 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5088 "GL_OES_mapbuffer or "
5089 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005090 return false;
5091 }
5092 break;
5093
5094 case GL_BUFFER_MAP_POINTER:
5095 if (!pointerVersion)
5096 {
5097 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005098 InvalidEnum()
5099 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005100 return false;
5101 }
5102 break;
5103
5104 case GL_BUFFER_ACCESS_FLAGS:
5105 case GL_BUFFER_MAP_OFFSET:
5106 case GL_BUFFER_MAP_LENGTH:
5107 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5108 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005109 context->handleError(InvalidEnum()
5110 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005111 return false;
5112 }
5113 break;
5114
5115 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005116 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005117 return false;
5118 }
5119
5120 // All buffer parameter queries return one value.
5121 if (numParams)
5122 {
5123 *numParams = 1;
5124 }
5125
5126 return true;
5127}
5128
5129bool ValidateGetRenderbufferParameterivBase(Context *context,
5130 GLenum target,
5131 GLenum pname,
5132 GLsizei *length)
5133{
5134 if (length)
5135 {
5136 *length = 0;
5137 }
5138
5139 if (target != GL_RENDERBUFFER)
5140 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005141 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005142 return false;
5143 }
5144
5145 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5146 if (renderbuffer == nullptr)
5147 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005148 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005149 return false;
5150 }
5151
5152 switch (pname)
5153 {
5154 case GL_RENDERBUFFER_WIDTH:
5155 case GL_RENDERBUFFER_HEIGHT:
5156 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5157 case GL_RENDERBUFFER_RED_SIZE:
5158 case GL_RENDERBUFFER_GREEN_SIZE:
5159 case GL_RENDERBUFFER_BLUE_SIZE:
5160 case GL_RENDERBUFFER_ALPHA_SIZE:
5161 case GL_RENDERBUFFER_DEPTH_SIZE:
5162 case GL_RENDERBUFFER_STENCIL_SIZE:
5163 break;
5164
5165 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5166 if (!context->getExtensions().framebufferMultisample)
5167 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005168 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005169 return false;
5170 }
5171 break;
5172
5173 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005174 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005175 return false;
5176 }
5177
5178 if (length)
5179 {
5180 *length = 1;
5181 }
5182 return true;
5183}
5184
5185bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5186{
5187 if (length)
5188 {
5189 *length = 0;
5190 }
5191
5192 if (GetValidShader(context, shader) == nullptr)
5193 {
5194 return false;
5195 }
5196
5197 switch (pname)
5198 {
5199 case GL_SHADER_TYPE:
5200 case GL_DELETE_STATUS:
5201 case GL_COMPILE_STATUS:
5202 case GL_INFO_LOG_LENGTH:
5203 case GL_SHADER_SOURCE_LENGTH:
5204 break;
5205
5206 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5207 if (!context->getExtensions().translatedShaderSource)
5208 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005209 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005210 return false;
5211 }
5212 break;
5213
5214 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005215 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005216 return false;
5217 }
5218
5219 if (length)
5220 {
5221 *length = 1;
5222 }
5223 return true;
5224}
5225
5226bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
5227{
5228 if (length)
5229 {
5230 *length = 0;
5231 }
5232
5233 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5234 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005235 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005236 return false;
5237 }
5238
5239 if (context->getTargetTexture(target) == nullptr)
5240 {
5241 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005242 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005243 return false;
5244 }
5245
5246 switch (pname)
5247 {
5248 case GL_TEXTURE_MAG_FILTER:
5249 case GL_TEXTURE_MIN_FILTER:
5250 case GL_TEXTURE_WRAP_S:
5251 case GL_TEXTURE_WRAP_T:
5252 break;
5253
5254 case GL_TEXTURE_USAGE_ANGLE:
5255 if (!context->getExtensions().textureUsage)
5256 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005257 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005258 return false;
5259 }
5260 break;
5261
5262 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5263 if (!context->getExtensions().textureFilterAnisotropic)
5264 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005265 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005266 return false;
5267 }
5268 break;
5269
5270 case GL_TEXTURE_IMMUTABLE_FORMAT:
5271 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5272 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005273 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005274 return false;
5275 }
5276 break;
5277
5278 case GL_TEXTURE_WRAP_R:
5279 case GL_TEXTURE_IMMUTABLE_LEVELS:
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_MIN_LOD:
5287 case GL_TEXTURE_MAX_LOD:
5288 case GL_TEXTURE_COMPARE_MODE:
5289 case GL_TEXTURE_COMPARE_FUNC:
5290 if (context->getClientMajorVersion() < 3)
5291 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005292 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005293 return false;
5294 }
5295 break;
5296
5297 case GL_TEXTURE_SRGB_DECODE_EXT:
5298 if (!context->getExtensions().textureSRGBDecode)
5299 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005300 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005301 return false;
5302 }
5303 break;
5304
5305 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005306 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005307 return false;
5308 }
5309
5310 if (length)
5311 {
5312 *length = 1;
5313 }
5314 return true;
5315}
5316
5317bool ValidateGetVertexAttribBase(Context *context,
5318 GLuint index,
5319 GLenum pname,
5320 GLsizei *length,
5321 bool pointer,
5322 bool pureIntegerEntryPoint)
5323{
5324 if (length)
5325 {
5326 *length = 0;
5327 }
5328
5329 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5330 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005331 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005332 return false;
5333 }
5334
5335 if (index >= context->getCaps().maxVertexAttributes)
5336 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005337 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005338 return false;
5339 }
5340
5341 if (pointer)
5342 {
5343 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5344 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005345 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005346 return false;
5347 }
5348 }
5349 else
5350 {
5351 switch (pname)
5352 {
5353 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5354 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5355 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5356 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5357 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5358 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5359 case GL_CURRENT_VERTEX_ATTRIB:
5360 break;
5361
5362 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5363 static_assert(
5364 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5365 "ANGLE extension enums not equal to GL enums.");
5366 if (context->getClientMajorVersion() < 3 &&
5367 !context->getExtensions().instancedArrays)
5368 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005369 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5370 "requires OpenGL ES 3.0 or "
5371 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005372 return false;
5373 }
5374 break;
5375
5376 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5377 if (context->getClientMajorVersion() < 3)
5378 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005379 context->handleError(
5380 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005381 return false;
5382 }
5383 break;
5384
5385 case GL_VERTEX_ATTRIB_BINDING:
5386 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5387 if (context->getClientVersion() < ES_3_1)
5388 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005389 context->handleError(InvalidEnum()
5390 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005391 return false;
5392 }
5393 break;
5394
5395 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005396 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005397 return false;
5398 }
5399 }
5400
5401 if (length)
5402 {
5403 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5404 {
5405 *length = 4;
5406 }
5407 else
5408 {
5409 *length = 1;
5410 }
5411 }
5412
5413 return true;
5414}
5415
Jamie Madill4928b7c2017-06-20 12:57:39 -04005416bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005417 GLint x,
5418 GLint y,
5419 GLsizei width,
5420 GLsizei height,
5421 GLenum format,
5422 GLenum type,
5423 GLsizei bufSize,
5424 GLsizei *length,
5425 GLsizei *columns,
5426 GLsizei *rows,
5427 void *pixels)
5428{
5429 if (length != nullptr)
5430 {
5431 *length = 0;
5432 }
5433 if (rows != nullptr)
5434 {
5435 *rows = 0;
5436 }
5437 if (columns != nullptr)
5438 {
5439 *columns = 0;
5440 }
5441
5442 if (width < 0 || height < 0)
5443 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005444 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005445 return false;
5446 }
5447
5448 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5449
5450 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5451 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005452 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005453 return false;
5454 }
5455
5456 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5457 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005458 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005459 return false;
5460 }
5461
5462 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5463 ASSERT(framebuffer);
5464
5465 if (framebuffer->getReadBufferState() == GL_NONE)
5466 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005467 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005468 return false;
5469 }
5470
5471 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5472 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5473 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5474 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5475 // situation is an application error that would lead to a crash in ANGLE.
5476 if (readBuffer == nullptr)
5477 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005478 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005479 return false;
5480 }
5481
Martin Radev28031682017-07-28 14:47:56 +03005482 // ANGLE_multiview, Revision 1:
5483 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5484 // current read framebuffer is not NONE.
5485 if (readBuffer->getMultiviewLayout() != GL_NONE)
5486 {
5487 context->handleError(InvalidFramebufferOperation()
5488 << "Attempting to read from a multi-view framebuffer.");
5489 return false;
5490 }
5491
Geoff Lang280ba992017-04-18 16:30:58 -04005492 if (context->getExtensions().webglCompatibility)
5493 {
5494 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5495 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5496 // and type before validating the combination of format and type. However, the
5497 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5498 // verifies that GL_INVALID_OPERATION is generated.
5499 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5500 // dEQP/WebGL.
5501 if (!ValidReadPixelsFormatEnum(context, format))
5502 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005503 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005504 return false;
5505 }
5506
5507 if (!ValidReadPixelsTypeEnum(context, type))
5508 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005509 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005510 return false;
5511 }
5512 }
5513
Jamie Madill4928b7c2017-06-20 12:57:39 -04005514 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5515 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005516 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5517
5518 bool validFormatTypeCombination =
5519 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5520
5521 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5522 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005523 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005524 return false;
5525 }
5526
5527 // Check for pixel pack buffer related API errors
5528 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5529 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5530 {
5531 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005532 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005533 return false;
5534 }
5535
5536 // .. the data would be packed to the buffer object such that the memory writes required
5537 // would exceed the data store size.
5538 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5539 const gl::Extents size(width, height, 1);
5540 const auto &pack = context->getGLState().getPackState();
5541
5542 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5543 if (endByteOrErr.isError())
5544 {
5545 context->handleError(endByteOrErr.getError());
5546 return false;
5547 }
5548
5549 size_t endByte = endByteOrErr.getResult();
5550 if (bufSize >= 0)
5551 {
5552 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5553 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005554 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005555 return false;
5556 }
5557 }
5558
5559 if (pixelPackBuffer != nullptr)
5560 {
5561 CheckedNumeric<size_t> checkedEndByte(endByte);
5562 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5563 checkedEndByte += checkedOffset;
5564
5565 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5566 {
5567 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005568 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005569 return false;
5570 }
5571 }
5572
5573 if (pixelPackBuffer == nullptr && length != nullptr)
5574 {
5575 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5576 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005577 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005578 return false;
5579 }
5580
5581 *length = static_cast<GLsizei>(endByte);
5582 }
5583
5584 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5585 angle::CheckedNumeric<int> clippedExtent(length);
5586 if (start < 0)
5587 {
5588 // "subtract" the area that is less than 0
5589 clippedExtent += start;
5590 }
5591
5592 const int readExtent = start + length;
5593 if (readExtent > bufferSize)
5594 {
5595 // Subtract the region to the right of the read buffer
5596 clippedExtent -= (readExtent - bufferSize);
5597 }
5598
5599 if (!clippedExtent.IsValid())
5600 {
5601 return 0;
5602 }
5603
5604 return std::max(clippedExtent.ValueOrDie(), 0);
5605 };
5606
5607 if (columns != nullptr)
5608 {
5609 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5610 }
5611
5612 if (rows != nullptr)
5613 {
5614 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5615 }
5616
5617 return true;
5618}
5619
5620template <typename ParamType>
5621bool ValidateTexParameterBase(Context *context,
5622 GLenum target,
5623 GLenum pname,
5624 GLsizei bufSize,
5625 const ParamType *params)
5626{
5627 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5628 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005629 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005630 return false;
5631 }
5632
5633 if (context->getTargetTexture(target) == nullptr)
5634 {
5635 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005636 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005637 return false;
5638 }
5639
5640 const GLsizei minBufSize = 1;
5641 if (bufSize >= 0 && bufSize < minBufSize)
5642 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005643 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005644 return false;
5645 }
5646
5647 switch (pname)
5648 {
5649 case GL_TEXTURE_WRAP_R:
5650 case GL_TEXTURE_SWIZZLE_R:
5651 case GL_TEXTURE_SWIZZLE_G:
5652 case GL_TEXTURE_SWIZZLE_B:
5653 case GL_TEXTURE_SWIZZLE_A:
5654 case GL_TEXTURE_BASE_LEVEL:
5655 case GL_TEXTURE_MAX_LEVEL:
5656 case GL_TEXTURE_COMPARE_MODE:
5657 case GL_TEXTURE_COMPARE_FUNC:
5658 case GL_TEXTURE_MIN_LOD:
5659 case GL_TEXTURE_MAX_LOD:
5660 if (context->getClientMajorVersion() < 3)
5661 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005662 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005663 return false;
5664 }
5665 if (target == GL_TEXTURE_EXTERNAL_OES &&
5666 !context->getExtensions().eglImageExternalEssl3)
5667 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005668 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5669 "available without "
5670 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005671 return false;
5672 }
5673 break;
5674
5675 default:
5676 break;
5677 }
5678
JiangYizhou4cff8d62017-07-06 14:54:09 +08005679 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5680 {
5681 switch (pname)
5682 {
5683 case GL_TEXTURE_MIN_FILTER:
5684 case GL_TEXTURE_MAG_FILTER:
5685 case GL_TEXTURE_WRAP_S:
5686 case GL_TEXTURE_WRAP_T:
5687 case GL_TEXTURE_WRAP_R:
5688 case GL_TEXTURE_MIN_LOD:
5689 case GL_TEXTURE_MAX_LOD:
5690 case GL_TEXTURE_COMPARE_MODE:
5691 case GL_TEXTURE_COMPARE_FUNC:
5692 context->handleError(InvalidEnum()
5693 << "Invalid parameter for 2D multisampled textures.");
5694 return false;
5695 }
5696 }
5697
Jamie Madillbe849e42017-05-02 15:49:00 -04005698 switch (pname)
5699 {
5700 case GL_TEXTURE_WRAP_S:
5701 case GL_TEXTURE_WRAP_T:
5702 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005703 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005704 bool restrictedWrapModes =
5705 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5706 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5707 {
5708 return false;
5709 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005710 }
5711 break;
5712
5713 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005714 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005715 bool restrictedMinFilter =
5716 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5717 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5718 {
5719 return false;
5720 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005721 }
5722 break;
5723
5724 case GL_TEXTURE_MAG_FILTER:
5725 if (!ValidateTextureMagFilterValue(context, params))
5726 {
5727 return false;
5728 }
5729 break;
5730
5731 case GL_TEXTURE_USAGE_ANGLE:
5732 switch (ConvertToGLenum(params[0]))
5733 {
5734 case GL_NONE:
5735 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5736 break;
5737
5738 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005739 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005740 return false;
5741 }
5742 break;
5743
5744 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5745 if (!context->getExtensions().textureFilterAnisotropic)
5746 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005747 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005748 return false;
5749 }
5750
5751 // we assume the parameter passed to this validation method is truncated, not rounded
5752 if (params[0] < 1)
5753 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005754 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005755 return false;
5756 }
5757 break;
5758
5759 case GL_TEXTURE_MIN_LOD:
5760 case GL_TEXTURE_MAX_LOD:
5761 // any value is permissible
5762 break;
5763
5764 case GL_TEXTURE_COMPARE_MODE:
5765 if (!ValidateTextureCompareModeValue(context, params))
5766 {
5767 return false;
5768 }
5769 break;
5770
5771 case GL_TEXTURE_COMPARE_FUNC:
5772 if (!ValidateTextureCompareFuncValue(context, params))
5773 {
5774 return false;
5775 }
5776 break;
5777
5778 case GL_TEXTURE_SWIZZLE_R:
5779 case GL_TEXTURE_SWIZZLE_G:
5780 case GL_TEXTURE_SWIZZLE_B:
5781 case GL_TEXTURE_SWIZZLE_A:
5782 switch (ConvertToGLenum(params[0]))
5783 {
5784 case GL_RED:
5785 case GL_GREEN:
5786 case GL_BLUE:
5787 case GL_ALPHA:
5788 case GL_ZERO:
5789 case GL_ONE:
5790 break;
5791
5792 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005793 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005794 return false;
5795 }
5796 break;
5797
5798 case GL_TEXTURE_BASE_LEVEL:
5799 if (params[0] < 0)
5800 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005801 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005802 return false;
5803 }
5804 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5805 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005806 context->handleError(InvalidOperation()
5807 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005808 return false;
5809 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005810 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5811 {
5812 context->handleError(InvalidOperation()
5813 << "Base level must be 0 for multisampled textures.");
5814 return false;
5815 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005816 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5817 {
5818 context->handleError(InvalidOperation()
5819 << "Base level must be 0 for rectangle textures.");
5820 return false;
5821 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005822 break;
5823
5824 case GL_TEXTURE_MAX_LEVEL:
5825 if (params[0] < 0)
5826 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005827 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005828 return false;
5829 }
5830 break;
5831
5832 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5833 if (context->getClientVersion() < Version(3, 1))
5834 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005835 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005836 return false;
5837 }
5838 switch (ConvertToGLenum(params[0]))
5839 {
5840 case GL_DEPTH_COMPONENT:
5841 case GL_STENCIL_INDEX:
5842 break;
5843
5844 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005845 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005846 return false;
5847 }
5848 break;
5849
5850 case GL_TEXTURE_SRGB_DECODE_EXT:
5851 if (!ValidateTextureSRGBDecodeValue(context, params))
5852 {
5853 return false;
5854 }
5855 break;
5856
5857 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005858 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005859 return false;
5860 }
5861
5862 return true;
5863}
5864
5865template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5866template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5867
Jamie Madillc29968b2016-01-20 11:17:23 -05005868} // namespace gl