blob: 3e6f497e754779a5ebfdb356bcc02f127b64b9d1 [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
Jamie Madillf0e04492017-08-26 15:28:42 -04001919bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
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
Jamie Madillf0e04492017-08-26 15:28:42 -04001931bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
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
Jamie Madillf0e04492017-08-26 15:28:42 -04001943bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1944{
1945 if (!context->getExtensions().occlusionQueryBoolean &&
1946 !context->getExtensions().disjointTimerQuery)
1947 {
1948 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1949 return false;
1950 }
1951
1952 return true;
1953}
1954
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001955bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001956{
1957 if (!ValidQueryType(context, target))
1958 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001959 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001960 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001961 }
1962
1963 if (id == 0)
1964 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001965 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001966 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001967 }
1968
1969 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1970 // of zero, if the active query object name for <target> is non-zero (for the
1971 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1972 // the active query for either target is non-zero), if <id> is the name of an
1973 // existing query object whose type does not match <target>, or if <id> is the
1974 // active query object name for any query type, the error INVALID_OPERATION is
1975 // generated.
1976
1977 // Ensure no other queries are active
1978 // NOTE: If other queries than occlusion are supported, we will need to check
1979 // separately that:
1980 // a) The query ID passed is not the current active query for any target/type
1981 // b) There are no active queries for the requested target (and in the case
1982 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1983 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001984
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001985 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001986 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001987 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001988 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001989 }
1990
1991 Query *queryObject = context->getQuery(id, true, target);
1992
1993 // check that name was obtained with glGenQueries
1994 if (!queryObject)
1995 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001996 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001997 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001998 }
1999
2000 // check for type mismatch
2001 if (queryObject->getType() != target)
2002 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002003 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04002004 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002005 }
2006
2007 return true;
2008}
2009
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002010bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2011{
2012 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002013 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002014 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002015 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002016 return false;
2017 }
2018
2019 return ValidateBeginQueryBase(context, target, id);
2020}
2021
2022bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002023{
2024 if (!ValidQueryType(context, target))
2025 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002026 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04002027 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002028 }
2029
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002030 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002031
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002032 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002033 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002034 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04002035 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002036 }
2037
Jamie Madill45c785d2014-05-13 14:09:34 -04002038 return true;
2039}
2040
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002041bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2042{
2043 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002044 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002045 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002046 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002047 return false;
2048 }
2049
2050 return ValidateEndQueryBase(context, target);
2051}
2052
2053bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2054{
2055 if (!context->getExtensions().disjointTimerQuery)
2056 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002057 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002058 return false;
2059 }
2060
2061 if (target != GL_TIMESTAMP_EXT)
2062 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002063 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002064 return false;
2065 }
2066
2067 Query *queryObject = context->getQuery(id, true, target);
2068 if (queryObject == nullptr)
2069 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002070 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002071 return false;
2072 }
2073
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002074 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002075 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002076 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002077 return false;
2078 }
2079
2080 return true;
2081}
2082
Geoff Lang2186c382016-10-14 10:54:54 -04002083bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002084{
Geoff Lang2186c382016-10-14 10:54:54 -04002085 if (numParams)
2086 {
2087 *numParams = 0;
2088 }
2089
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002090 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2091 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002092 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002093 return false;
2094 }
2095
2096 switch (pname)
2097 {
2098 case GL_CURRENT_QUERY_EXT:
2099 if (target == GL_TIMESTAMP_EXT)
2100 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002101 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002102 return false;
2103 }
2104 break;
2105 case GL_QUERY_COUNTER_BITS_EXT:
2106 if (!context->getExtensions().disjointTimerQuery ||
2107 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2108 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002109 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002110 return false;
2111 }
2112 break;
2113 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002114 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002115 return false;
2116 }
2117
Geoff Lang2186c382016-10-14 10:54:54 -04002118 if (numParams)
2119 {
2120 // All queries return only one value
2121 *numParams = 1;
2122 }
2123
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002124 return true;
2125}
2126
2127bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2128{
2129 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002130 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002131 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002132 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002133 return false;
2134 }
2135
Geoff Lang2186c382016-10-14 10:54:54 -04002136 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002137}
2138
Geoff Lang2186c382016-10-14 10:54:54 -04002139bool ValidateGetQueryivRobustANGLE(Context *context,
2140 GLenum target,
2141 GLenum pname,
2142 GLsizei bufSize,
2143 GLsizei *length,
2144 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002145{
Geoff Lang2186c382016-10-14 10:54:54 -04002146 if (!ValidateRobustEntryPoint(context, bufSize))
2147 {
2148 return false;
2149 }
2150
2151 if (!ValidateGetQueryivBase(context, target, pname, length))
2152 {
2153 return false;
2154 }
2155
2156 if (!ValidateRobustBufferSize(context, bufSize, *length))
2157 {
2158 return false;
2159 }
2160
2161 return true;
2162}
2163
2164bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2165{
2166 if (numParams)
2167 {
2168 *numParams = 0;
2169 }
2170
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002171 Query *queryObject = context->getQuery(id, false, GL_NONE);
2172
2173 if (!queryObject)
2174 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002175 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002176 return false;
2177 }
2178
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002179 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002180 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002181 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002182 return false;
2183 }
2184
2185 switch (pname)
2186 {
2187 case GL_QUERY_RESULT_EXT:
2188 case GL_QUERY_RESULT_AVAILABLE_EXT:
2189 break;
2190
2191 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002192 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002193 return false;
2194 }
2195
Geoff Lang2186c382016-10-14 10:54:54 -04002196 if (numParams)
2197 {
2198 *numParams = 1;
2199 }
2200
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002201 return true;
2202}
2203
2204bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2205{
2206 if (!context->getExtensions().disjointTimerQuery)
2207 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002208 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002209 return false;
2210 }
Geoff Lang2186c382016-10-14 10:54:54 -04002211 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2212}
2213
2214bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2215 GLuint id,
2216 GLenum pname,
2217 GLsizei bufSize,
2218 GLsizei *length,
2219 GLint *params)
2220{
2221 if (!context->getExtensions().disjointTimerQuery)
2222 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002223 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04002224 return false;
2225 }
2226
2227 if (!ValidateRobustEntryPoint(context, bufSize))
2228 {
2229 return false;
2230 }
2231
2232 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2233 {
2234 return false;
2235 }
2236
2237 if (!ValidateRobustBufferSize(context, bufSize, *length))
2238 {
2239 return false;
2240 }
2241
2242 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002243}
2244
2245bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2246{
2247 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002248 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002249 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002250 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002251 return false;
2252 }
Geoff Lang2186c382016-10-14 10:54:54 -04002253 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2254}
2255
2256bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2257 GLuint id,
2258 GLenum pname,
2259 GLsizei bufSize,
2260 GLsizei *length,
2261 GLuint *params)
2262{
2263 if (!context->getExtensions().disjointTimerQuery &&
2264 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2265 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002266 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002267 return false;
2268 }
2269
2270 if (!ValidateRobustEntryPoint(context, bufSize))
2271 {
2272 return false;
2273 }
2274
2275 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2276 {
2277 return false;
2278 }
2279
2280 if (!ValidateRobustBufferSize(context, bufSize, *length))
2281 {
2282 return false;
2283 }
2284
2285 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002286}
2287
2288bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2289{
2290 if (!context->getExtensions().disjointTimerQuery)
2291 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002292 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002293 return false;
2294 }
Geoff Lang2186c382016-10-14 10:54:54 -04002295 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2296}
2297
2298bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2299 GLuint id,
2300 GLenum pname,
2301 GLsizei bufSize,
2302 GLsizei *length,
2303 GLint64 *params)
2304{
2305 if (!context->getExtensions().disjointTimerQuery)
2306 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002307 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002308 return false;
2309 }
2310
2311 if (!ValidateRobustEntryPoint(context, bufSize))
2312 {
2313 return false;
2314 }
2315
2316 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2317 {
2318 return false;
2319 }
2320
2321 if (!ValidateRobustBufferSize(context, bufSize, *length))
2322 {
2323 return false;
2324 }
2325
2326 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002327}
2328
2329bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2330{
2331 if (!context->getExtensions().disjointTimerQuery)
2332 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002333 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002334 return false;
2335 }
Geoff Lang2186c382016-10-14 10:54:54 -04002336 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2337}
2338
2339bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2340 GLuint id,
2341 GLenum pname,
2342 GLsizei bufSize,
2343 GLsizei *length,
2344 GLuint64 *params)
2345{
2346 if (!context->getExtensions().disjointTimerQuery)
2347 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002348 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002349 return false;
2350 }
2351
2352 if (!ValidateRobustEntryPoint(context, bufSize))
2353 {
2354 return false;
2355 }
2356
2357 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2358 {
2359 return false;
2360 }
2361
2362 if (!ValidateRobustBufferSize(context, bufSize, *length))
2363 {
2364 return false;
2365 }
2366
2367 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002368}
2369
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002370bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002371 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002372 GLuint program,
2373 GLint location,
2374 GLsizei count)
2375{
2376 // Check for ES31 program uniform entry points
2377 if (context->getClientVersion() < Version(3, 1))
2378 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002379 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002380 return false;
2381 }
2382
2383 const LinkedUniform *uniform = nullptr;
2384 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002385 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2386 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002387}
2388
Frank Henigmana98a6472017-02-02 21:38:32 -05002389bool ValidateProgramUniform1iv(gl::Context *context,
2390 GLuint program,
2391 GLint location,
2392 GLsizei count,
2393 const GLint *value)
2394{
2395 // Check for ES31 program uniform entry points
2396 if (context->getClientVersion() < Version(3, 1))
2397 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002398 context->handleError(InvalidOperation());
Frank Henigmana98a6472017-02-02 21:38:32 -05002399 return false;
2400 }
2401
2402 const LinkedUniform *uniform = nullptr;
2403 gl::Program *programObject = GetValidProgram(context, program);
2404 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2405 ValidateUniform1ivValue(context, uniform->type, count, value);
2406}
2407
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002408bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002409 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002410 GLuint program,
2411 GLint location,
2412 GLsizei count,
2413 GLboolean transpose)
2414{
2415 // Check for ES31 program uniform entry points
2416 if (context->getClientVersion() < Version(3, 1))
2417 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002418 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002419 return false;
2420 }
2421
2422 const LinkedUniform *uniform = nullptr;
2423 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002424 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2425 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002426}
2427
Jamie Madillc1d770e2017-04-13 17:31:24 -04002428bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002429{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002430 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002431 gl::Program *programObject = context->getGLState().getProgram();
2432 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2433 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002434}
2435
Jamie Madillbe849e42017-05-02 15:49:00 -04002436bool ValidateUniform1iv(ValidationContext *context,
2437 GLint location,
2438 GLsizei count,
2439 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002440{
2441 const LinkedUniform *uniform = nullptr;
2442 gl::Program *programObject = context->getGLState().getProgram();
2443 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2444 ValidateUniform1ivValue(context, uniform->type, count, value);
2445}
2446
Jamie Madillc1d770e2017-04-13 17:31:24 -04002447bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002448 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002449 GLint location,
2450 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002451 GLboolean transpose)
2452{
2453 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002454 int rows = VariableRowCount(valueType);
2455 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002456 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002457 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002458 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002459 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002460 }
2461
Martin Radev1be913c2016-07-11 17:59:16 +03002462 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002463 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002464 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002465 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002466 }
2467
Jamie Madill62d31cb2015-09-11 13:25:51 -04002468 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002469 gl::Program *programObject = context->getGLState().getProgram();
2470 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2471 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002472}
2473
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002474bool ValidateStateQuery(ValidationContext *context,
2475 GLenum pname,
2476 GLenum *nativeType,
2477 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002478{
2479 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2480 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002481 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002482 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002483 }
2484
Jamie Madill0af26e12015-03-05 19:54:33 -05002485 const Caps &caps = context->getCaps();
2486
Jamie Madill893ab082014-05-16 16:56:10 -04002487 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2488 {
2489 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2490
Jamie Madill0af26e12015-03-05 19:54:33 -05002491 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002492 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002493 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002494 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002495 }
2496 }
2497
2498 switch (pname)
2499 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002500 case GL_TEXTURE_BINDING_2D:
2501 case GL_TEXTURE_BINDING_CUBE_MAP:
2502 case GL_TEXTURE_BINDING_3D:
2503 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002504 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002505 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002506 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2507 if (!context->getExtensions().textureRectangle)
2508 {
2509 context->handleError(InvalidEnum()
2510 << "ANGLE_texture_rectangle extension not present");
2511 return false;
2512 }
2513 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002514 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2515 if (!context->getExtensions().eglStreamConsumerExternal &&
2516 !context->getExtensions().eglImageExternal)
2517 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002518 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2519 "nor GL_OES_EGL_image_external "
2520 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002521 return false;
2522 }
2523 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002524
He Yunchaoced53ae2016-11-29 15:00:51 +08002525 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2526 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002527 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002528 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2529 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002530 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002531 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002532 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002533 }
2534
Jamie Madill51f40ec2016-06-15 14:06:00 -04002535 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2536 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002537
2538 if (framebuffer->getReadBufferState() == GL_NONE)
2539 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002540 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002541 return false;
2542 }
2543
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002544 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002545 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002546 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002547 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002548 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002549 }
2550 }
2551 break;
2552
He Yunchaoced53ae2016-11-29 15:00:51 +08002553 default:
2554 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002555 }
2556
2557 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002558 if (*numParams == 0)
2559 {
2560 return false;
2561 }
2562
2563 return true;
2564}
2565
2566bool ValidateRobustStateQuery(ValidationContext *context,
2567 GLenum pname,
2568 GLsizei bufSize,
2569 GLenum *nativeType,
2570 unsigned int *numParams)
2571{
2572 if (!ValidateRobustEntryPoint(context, bufSize))
2573 {
2574 return false;
2575 }
2576
2577 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2578 {
2579 return false;
2580 }
2581
2582 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002583 {
2584 return false;
2585 }
2586
2587 return true;
2588}
2589
Jamie Madillc29968b2016-01-20 11:17:23 -05002590bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2591 GLenum target,
2592 GLint level,
2593 GLenum internalformat,
2594 bool isSubImage,
2595 GLint xoffset,
2596 GLint yoffset,
2597 GLint zoffset,
2598 GLint x,
2599 GLint y,
2600 GLsizei width,
2601 GLsizei height,
2602 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002603 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002604{
Brandon Jones6cad5662017-06-14 13:25:13 -07002605 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002606 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002607 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2608 return false;
2609 }
2610
2611 if (width < 0 || height < 0)
2612 {
2613 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002614 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002615 }
2616
He Yunchaoced53ae2016-11-29 15:00:51 +08002617 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2618 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002619 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002620 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002621 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002622 }
2623
2624 if (border != 0)
2625 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002626 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002627 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002628 }
2629
2630 if (!ValidMipLevel(context, target, level))
2631 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002632 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002633 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002634 }
2635
Jamie Madill51f40ec2016-06-15 14:06:00 -04002636 const auto &state = context->getGLState();
2637 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002638 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002639 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002640 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002641 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002642 }
2643
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002644 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002645 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002646 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002647 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002648 }
2649
Martin Radev138064f2016-07-15 12:03:41 +03002650 if (readFramebuffer->getReadBufferState() == GL_NONE)
2651 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002652 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002653 return false;
2654 }
2655
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002656 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2657 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002658 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002659 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002660 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2661 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002662 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002663 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002664 return false;
2665 }
2666
Martin Radev04e2c3b2017-07-27 16:54:35 +03002667 // ANGLE_multiview spec, Revision 1:
2668 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2669 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2670 // is not NONE.
2671 if (source->getMultiviewLayout() != GL_NONE)
2672 {
2673 context->handleError(InvalidFramebufferOperation()
2674 << "The active read framebuffer object has multiview attachments.");
2675 return false;
2676 }
2677
Geoff Langaae65a42014-05-26 12:43:44 -04002678 const gl::Caps &caps = context->getCaps();
2679
Geoff Langaae65a42014-05-26 12:43:44 -04002680 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002681 switch (target)
2682 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002683 case GL_TEXTURE_2D:
2684 maxDimension = caps.max2DTextureSize;
2685 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002686
He Yunchaoced53ae2016-11-29 15:00:51 +08002687 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2688 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2689 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2690 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2691 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2692 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2693 maxDimension = caps.maxCubeMapTextureSize;
2694 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002695
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002696 case GL_TEXTURE_RECTANGLE_ANGLE:
2697 maxDimension = caps.maxRectangleTextureSize;
2698 break;
2699
He Yunchaoced53ae2016-11-29 15:00:51 +08002700 case GL_TEXTURE_2D_ARRAY:
2701 maxDimension = caps.max2DTextureSize;
2702 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002703
He Yunchaoced53ae2016-11-29 15:00:51 +08002704 case GL_TEXTURE_3D:
2705 maxDimension = caps.max3DTextureSize;
2706 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002707
He Yunchaoced53ae2016-11-29 15:00:51 +08002708 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002709 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002710 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002711 }
2712
Jamie Madillc29968b2016-01-20 11:17:23 -05002713 gl::Texture *texture =
2714 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002715 if (!texture)
2716 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002717 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002718 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002719 }
2720
Geoff Lang69cce582015-09-17 13:20:36 -04002721 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002722 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002723 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002724 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002725 }
2726
Geoff Langca271392017-04-05 12:30:00 -04002727 const gl::InternalFormat &formatInfo =
2728 gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002729
Geoff Lang966c9402017-04-18 12:38:27 -04002730 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002731 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002732 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002733 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002734 }
2735
2736 if (isSubImage)
2737 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002738 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2739 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2740 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002741 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002742 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002743 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002744 }
2745 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002746 else
2747 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002748 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002749 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002750 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002751 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002752 }
2753
Geoff Langeb66a6e2016-10-31 13:06:12 -04002754 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002755 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002756 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002757 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002758 }
2759
2760 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002761 if (static_cast<int>(width) > maxLevelDimension ||
2762 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002763 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002764 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002765 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002766 }
2767 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002768
Jamie Madill0c8abca2016-07-22 20:21:26 -04002769 if (textureFormatOut)
2770 {
2771 *textureFormatOut = texture->getFormat(target, level);
2772 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002773
2774 // Detect texture copying feedback loops for WebGL.
2775 if (context->getExtensions().webglCompatibility)
2776 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002777 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002778 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002779 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002780 return false;
2781 }
2782 }
2783
Jamie Madill560a8d82014-05-21 13:06:20 -04002784 return true;
2785}
2786
Jiajia Qind9671222016-11-29 16:30:31 +08002787bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002788{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002789 switch (mode)
2790 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002791 case GL_POINTS:
2792 case GL_LINES:
2793 case GL_LINE_LOOP:
2794 case GL_LINE_STRIP:
2795 case GL_TRIANGLES:
2796 case GL_TRIANGLE_STRIP:
2797 case GL_TRIANGLE_FAN:
2798 break;
2799 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002800 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002801 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002802 }
2803
Jamie Madill250d33f2014-06-06 17:09:03 -04002804 if (count < 0)
2805 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002806 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002807 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002808 }
2809
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002810 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002811
Jamie Madill250d33f2014-06-06 17:09:03 -04002812 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002813 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002814 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002815 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002816 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002817 }
2818
Jamie Madillcbcde722017-01-06 14:50:00 -05002819 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2820 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002821 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002822 const Extensions &extensions = context->getExtensions();
2823 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002824 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002825 const FramebufferAttachment *dsAttachment =
2826 framebuffer->getStencilOrDepthStencilAttachment();
2827 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002828 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002829 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002830
2831 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2832 bool differentWritemasks =
2833 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2834 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2835 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2836 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2837
2838 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002839 {
Martin Radevffe754b2017-07-31 10:38:07 +03002840 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002841 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002842 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2843 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002844 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002845 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002846 return false;
2847 }
Jamie Madillac528012014-06-20 13:21:23 -04002848 }
2849
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002850 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002851 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002852 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002853 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002854 }
2855
Geoff Lang7dd2e102014-11-10 15:19:26 -05002856 gl::Program *program = state.getProgram();
2857 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002858 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002859 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002860 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002861 }
2862
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002863 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002864 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002865 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002866 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002867 }
2868
Martin Radevffe754b2017-07-31 10:38:07 +03002869 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002870 {
Martin Radev7e69f762017-07-27 14:54:13 +03002871 const int programNumViews = program->getNumViews();
2872 const int framebufferNumViews = framebuffer->getNumViews();
2873 if (programNumViews != -1 && framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002874 {
2875 context->handleError(InvalidOperation() << "The number of views in the active program "
2876 "and draw framebuffer does not match.");
2877 return false;
2878 }
Martin Radev7e69f762017-07-27 14:54:13 +03002879
2880 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2881 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2882 framebufferNumViews > 1)
2883 {
2884 context->handleError(InvalidOperation()
2885 << "There is an active transform feedback object "
2886 "when the number of views in the active draw "
2887 "framebuffer is greater than 1.");
2888 return false;
2889 }
Martin Radevffe754b2017-07-31 10:38:07 +03002890
2891 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2892 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2893 {
2894 context->handleError(InvalidOperation() << "There is an active query for target "
2895 "GL_TIME_ELAPSED_EXT when the number of "
2896 "views in the active draw framebuffer is "
2897 "greater than 1.");
2898 return false;
2899 }
Martin Radev7cf61662017-07-26 17:10:53 +03002900 }
2901
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002902 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002903 for (unsigned int uniformBlockIndex = 0;
2904 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002905 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002906 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002907 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002908 const OffsetBindingPointer<Buffer> &uniformBuffer =
2909 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002910
Geoff Lang5d124a62015-09-15 13:03:27 -04002911 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002912 {
2913 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002914 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002915 InvalidOperation()
2916 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002917 return false;
2918 }
2919
Geoff Lang5d124a62015-09-15 13:03:27 -04002920 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002921 if (uniformBufferSize == 0)
2922 {
2923 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002924 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002925 }
2926
Jamie Madill62d31cb2015-09-11 13:25:51 -04002927 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002928 {
2929 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002930 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002931 InvalidOperation()
2932 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002933 return false;
2934 }
2935 }
2936
Geoff Lange0cff192017-05-30 13:04:56 -04002937 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002938 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002939 {
Geoff Lange0cff192017-05-30 13:04:56 -04002940 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002941 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2942 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002943 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002944 return false;
2945 }
Geoff Lange0cff192017-05-30 13:04:56 -04002946
Geoff Lang9ab5b822017-05-30 16:19:23 -04002947 // Detect that the vertex shader input types match the attribute types
2948 if (!ValidateVertexShaderAttributeTypeMatch(context))
2949 {
2950 return false;
2951 }
2952
Geoff Lange0cff192017-05-30 13:04:56 -04002953 // Detect that the color buffer types match the fragment shader output types
2954 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2955 {
2956 return false;
2957 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002958 }
2959
Jamie Madill250d33f2014-06-06 17:09:03 -04002960 // No-op if zero count
2961 return (count > 0);
2962}
2963
Jamie Madillc1d770e2017-04-13 17:31:24 -04002964bool ValidateDrawArraysCommon(ValidationContext *context,
2965 GLenum mode,
2966 GLint first,
2967 GLsizei count,
2968 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002969{
Jamie Madillfd716582014-06-06 17:09:04 -04002970 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002971 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002972 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002973 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002974 }
2975
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002976 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002977 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002978 if (curTransformFeedback && curTransformFeedback->isActive() &&
2979 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002980 {
2981 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002982 // that does not match the current transform feedback object's draw mode (if transform
2983 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002984 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002985 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002986 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002987 }
2988
Jiajia Qind9671222016-11-29 16:30:31 +08002989 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002990 {
2991 return false;
2992 }
2993
Corentin Wallez71168a02016-12-19 15:11:18 -08002994 // Check the computation of maxVertex doesn't overflow.
2995 // - first < 0 or count < 0 have been checked as an error condition
2996 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2997 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2998 ASSERT(count > 0 && first >= 0);
2999 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3000 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003001 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003002 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05003003 return false;
3004 }
3005
Corentin Wallez71168a02016-12-19 15:11:18 -08003006 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003007 {
3008 return false;
3009 }
3010
3011 return true;
3012}
3013
He Yunchaoced53ae2016-11-29 15:00:51 +08003014bool ValidateDrawArraysInstanced(Context *context,
3015 GLenum mode,
3016 GLint first,
3017 GLsizei count,
3018 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003019{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003020 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
Geoff Lang87a93302014-09-16 13:29:43 -04003021}
3022
He Yunchaoced53ae2016-11-29 15:00:51 +08003023bool ValidateDrawArraysInstancedANGLE(Context *context,
3024 GLenum mode,
3025 GLint first,
3026 GLsizei count,
3027 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003028{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003029 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003030 {
3031 return false;
3032 }
3033
Corentin Wallez0dc97812017-06-22 14:38:44 -04003034 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003035}
3036
Jiajia Qind9671222016-11-29 16:30:31 +08003037bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003038{
Jamie Madill250d33f2014-06-06 17:09:03 -04003039 switch (type)
3040 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003041 case GL_UNSIGNED_BYTE:
3042 case GL_UNSIGNED_SHORT:
3043 break;
3044 case GL_UNSIGNED_INT:
3045 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3046 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003047 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08003048 return false;
3049 }
3050 break;
3051 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003052 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08003053 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003054 }
3055
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003056 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003057
3058 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003059 if (curTransformFeedback && curTransformFeedback->isActive() &&
3060 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003061 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003062 // It is an invalid operation to call DrawElements, DrawRangeElements or
3063 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003064 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003065 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003066 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003067 }
3068
Jiajia Qind9671222016-11-29 16:30:31 +08003069 return true;
3070}
3071
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003072bool ValidateDrawElementsCommon(ValidationContext *context,
3073 GLenum mode,
3074 GLsizei count,
3075 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003076 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003077 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08003078{
3079 if (!ValidateDrawElementsBase(context, type))
3080 return false;
3081
3082 const State &state = context->getGLState();
3083
Corentin Wallez170efbf2017-05-02 13:45:01 -04003084 if (!ValidateDrawBase(context, mode, count))
3085 {
3086 return false;
3087 }
3088
Jamie Madill250d33f2014-06-06 17:09:03 -04003089 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003090 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003091 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003092 context->handleError(InvalidOperation() << "Index buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -04003093 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003094 }
3095
He Yunchaoced53ae2016-11-29 15:00:51 +08003096 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003097 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003098
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003099 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3100
3101 if (context->getExtensions().webglCompatibility)
3102 {
3103 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3104 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3105 {
3106 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3107 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3108 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003109 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003110 return false;
3111 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003112
3113 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3114 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3115 // error is generated.
3116 if (reinterpret_cast<intptr_t>(indices) < 0)
3117 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003118 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003119 return false;
3120 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003121 }
3122
3123 if (context->getExtensions().webglCompatibility ||
3124 !context->getGLState().areClientArraysEnabled())
3125 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003126 if (!elementArrayBuffer && count > 0)
3127 {
3128 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3129 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3130 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003131 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003132 return false;
3133 }
3134 }
3135
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003136 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003137 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003138 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003139 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003140 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3141 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3142 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3143 constexpr uint64_t kMaxTypeSize = 8;
3144 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3145 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3146 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003147
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003148 uint64_t typeSize = typeBytes;
3149 uint64_t elementCount = static_cast<uint64_t>(count);
3150 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3151
3152 // Doing the multiplication here is overflow-safe
3153 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3154
3155 // The offset can be any value, check for overflows
3156 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3157 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003158 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003159 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003160 return false;
3161 }
3162
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003163 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3164 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003165 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003166 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003167 return false;
3168 }
3169 }
3170 else if (!indices)
3171 {
3172 // This is an application error that would normally result in a crash,
3173 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003174 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04003175 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003176 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003177 }
3178
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003179 // Use the parameter buffer to retrieve and cache the index range.
3180 // TODO: offer fast path, with disabled index validation.
3181 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3182 const auto &params = context->getParams<HasIndexRange>();
3183 const auto &indexRangeOpt = params.getIndexRange();
3184 if (!indexRangeOpt.valid())
3185 {
3186 // Unexpected error.
3187 return false;
3188 }
3189
3190 // If we use an index greater than our maximum supported index range, return an error.
3191 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3192 // return an error if possible here.
3193 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
3194 {
3195 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3196 return false;
3197 }
3198
3199 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
3200 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003201 {
3202 return false;
3203 }
3204
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003205 // No op if there are no real indices in the index data (all are primitive restart).
3206 return (indexRangeOpt.value().vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003207}
3208
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003209bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
3210 GLenum mode,
3211 GLsizei count,
3212 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003213 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003214 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003215{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003216 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003217}
3218
Geoff Lang3edfe032015-09-04 16:38:24 -04003219bool ValidateDrawElementsInstancedANGLE(Context *context,
3220 GLenum mode,
3221 GLsizei count,
3222 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003223 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003224 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003225{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003226 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003227 {
3228 return false;
3229 }
3230
Corentin Wallez0dc97812017-06-22 14:38:44 -04003231 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003232}
3233
He Yunchaoced53ae2016-11-29 15:00:51 +08003234bool ValidateFramebufferTextureBase(Context *context,
3235 GLenum target,
3236 GLenum attachment,
3237 GLuint texture,
3238 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003239{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003240 if (!ValidFramebufferTarget(target))
3241 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003242 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003243 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003244 }
3245
3246 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003247 {
3248 return false;
3249 }
3250
Jamie Madill55ec3b12014-07-03 10:38:57 -04003251 if (texture != 0)
3252 {
3253 gl::Texture *tex = context->getTexture(texture);
3254
Jamie Madillbe849e42017-05-02 15:49:00 -04003255 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003256 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003257 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003258 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003259 }
3260
3261 if (level < 0)
3262 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003263 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003264 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003265 }
3266 }
3267
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003268 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003269 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003270
Jamie Madill84115c92015-04-23 15:00:07 -04003271 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003272 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003273 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003274 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003275 }
3276
3277 return true;
3278}
3279
Geoff Langb1196682014-07-23 13:47:29 -04003280bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003281{
3282 if (program == 0)
3283 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003284 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003285 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003286 }
3287
Dian Xiang769769a2015-09-09 15:20:08 -07003288 gl::Program *programObject = GetValidProgram(context, program);
3289 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003290 {
3291 return false;
3292 }
3293
Jamie Madill0063c512014-08-25 15:47:53 -04003294 if (!programObject || !programObject->isLinked())
3295 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003296 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003297 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003298 }
3299
Geoff Lang7dd2e102014-11-10 15:19:26 -05003300 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003301 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003302 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003303 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003304 }
3305
Jamie Madill0063c512014-08-25 15:47:53 -04003306 return true;
3307}
3308
Geoff Langf41d0ee2016-10-07 13:04:23 -04003309static bool ValidateSizedGetUniform(Context *context,
3310 GLuint program,
3311 GLint location,
3312 GLsizei bufSize,
3313 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003314{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003315 if (length)
3316 {
3317 *length = 0;
3318 }
3319
Jamie Madill78f41802014-08-25 15:47:55 -04003320 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003321 {
Jamie Madill78f41802014-08-25 15:47:55 -04003322 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003323 }
3324
Geoff Langf41d0ee2016-10-07 13:04:23 -04003325 if (bufSize < 0)
3326 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003327 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003328 return false;
3329 }
3330
Jamie Madilla502c742014-08-28 17:19:13 -04003331 gl::Program *programObject = context->getProgram(program);
3332 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003333
Jamie Madill78f41802014-08-25 15:47:55 -04003334 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003335 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003336 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003337 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003338 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003339 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003340 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003341 }
3342
Geoff Langf41d0ee2016-10-07 13:04:23 -04003343 if (length)
3344 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003345 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003346 }
3347
Jamie Madill0063c512014-08-25 15:47:53 -04003348 return true;
3349}
3350
He Yunchaoced53ae2016-11-29 15:00:51 +08003351bool ValidateGetnUniformfvEXT(Context *context,
3352 GLuint program,
3353 GLint location,
3354 GLsizei bufSize,
3355 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003356{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003357 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003358}
3359
He Yunchaoced53ae2016-11-29 15:00:51 +08003360bool ValidateGetnUniformivEXT(Context *context,
3361 GLuint program,
3362 GLint location,
3363 GLsizei bufSize,
3364 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003365{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003366 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3367}
3368
3369bool ValidateGetUniformfvRobustANGLE(Context *context,
3370 GLuint program,
3371 GLint location,
3372 GLsizei bufSize,
3373 GLsizei *length,
3374 GLfloat *params)
3375{
3376 if (!ValidateRobustEntryPoint(context, bufSize))
3377 {
3378 return false;
3379 }
3380
3381 // bufSize is validated in ValidateSizedGetUniform
3382 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3383}
3384
3385bool ValidateGetUniformivRobustANGLE(Context *context,
3386 GLuint program,
3387 GLint location,
3388 GLsizei bufSize,
3389 GLsizei *length,
3390 GLint *params)
3391{
3392 if (!ValidateRobustEntryPoint(context, bufSize))
3393 {
3394 return false;
3395 }
3396
3397 // bufSize is validated in ValidateSizedGetUniform
3398 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3399}
3400
3401bool ValidateGetUniformuivRobustANGLE(Context *context,
3402 GLuint program,
3403 GLint location,
3404 GLsizei bufSize,
3405 GLsizei *length,
3406 GLuint *params)
3407{
3408 if (!ValidateRobustEntryPoint(context, bufSize))
3409 {
3410 return false;
3411 }
3412
3413 if (context->getClientMajorVersion() < 3)
3414 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003415 context->handleError(InvalidOperation() << "Entry point requires at least OpenGL ES 3.0.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003416 return false;
3417 }
3418
3419 // bufSize is validated in ValidateSizedGetUniform
3420 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003421}
3422
He Yunchaoced53ae2016-11-29 15:00:51 +08003423bool ValidateDiscardFramebufferBase(Context *context,
3424 GLenum target,
3425 GLsizei numAttachments,
3426 const GLenum *attachments,
3427 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003428{
3429 if (numAttachments < 0)
3430 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003431 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003432 return false;
3433 }
3434
3435 for (GLsizei i = 0; i < numAttachments; ++i)
3436 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003437 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003438 {
3439 if (defaultFramebuffer)
3440 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003441 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003442 return false;
3443 }
3444
3445 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3446 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003447 context->handleError(InvalidOperation() << "Requested color attachment is "
3448 "greater than the maximum supported "
3449 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003450 return false;
3451 }
3452 }
3453 else
3454 {
3455 switch (attachments[i])
3456 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003457 case GL_DEPTH_ATTACHMENT:
3458 case GL_STENCIL_ATTACHMENT:
3459 case GL_DEPTH_STENCIL_ATTACHMENT:
3460 if (defaultFramebuffer)
3461 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003462 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3463 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003464 return false;
3465 }
3466 break;
3467 case GL_COLOR:
3468 case GL_DEPTH:
3469 case GL_STENCIL:
3470 if (!defaultFramebuffer)
3471 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003472 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3473 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003474 return false;
3475 }
3476 break;
3477 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003478 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003479 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003480 }
3481 }
3482 }
3483
3484 return true;
3485}
3486
Austin Kinross6ee1e782015-05-29 17:05:37 -07003487bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3488{
3489 // Note that debug marker calls must not set error state
3490
3491 if (length < 0)
3492 {
3493 return false;
3494 }
3495
3496 if (marker == nullptr)
3497 {
3498 return false;
3499 }
3500
3501 return true;
3502}
3503
3504bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3505{
3506 // Note that debug marker calls must not set error state
3507
3508 if (length < 0)
3509 {
3510 return false;
3511 }
3512
3513 if (length > 0 && marker == nullptr)
3514 {
3515 return false;
3516 }
3517
3518 return true;
3519}
3520
Geoff Langdcab33b2015-07-21 13:03:16 -04003521bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003522 GLenum target,
3523 egl::Image *image)
3524{
Geoff Langa8406172015-07-21 16:53:39 -04003525 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003527 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003528 return false;
3529 }
3530
3531 switch (target)
3532 {
3533 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003534 if (!context->getExtensions().eglImage)
3535 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003536 context->handleError(InvalidEnum()
3537 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003538 }
3539 break;
3540
3541 case GL_TEXTURE_EXTERNAL_OES:
3542 if (!context->getExtensions().eglImageExternal)
3543 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003544 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3545 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003546 }
Geoff Langa8406172015-07-21 16:53:39 -04003547 break;
3548
3549 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003550 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003551 return false;
3552 }
3553
Jamie Madill61e16b42017-06-19 11:13:23 -04003554 ASSERT(context->getCurrentDisplay());
3555 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003556 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003557 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003558 return false;
3559 }
3560
3561 if (image->getSamples() > 0)
3562 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003563 context->handleError(InvalidOperation()
3564 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003565 return false;
3566 }
3567
Geoff Langca271392017-04-05 12:30:00 -04003568 const TextureCaps &textureCaps =
3569 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003570 if (!textureCaps.texturable)
3571 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003572 context->handleError(InvalidOperation()
3573 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003574 return false;
3575 }
3576
Geoff Langdcab33b2015-07-21 13:03:16 -04003577 return true;
3578}
3579
3580bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003581 GLenum target,
3582 egl::Image *image)
3583{
Geoff Langa8406172015-07-21 16:53:39 -04003584 if (!context->getExtensions().eglImage)
3585 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003586 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003587 return false;
3588 }
3589
3590 switch (target)
3591 {
3592 case GL_RENDERBUFFER:
3593 break;
3594
3595 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003596 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003597 return false;
3598 }
3599
Jamie Madill61e16b42017-06-19 11:13:23 -04003600 ASSERT(context->getCurrentDisplay());
3601 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003602 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003603 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003604 return false;
3605 }
3606
Geoff Langca271392017-04-05 12:30:00 -04003607 const TextureCaps &textureCaps =
3608 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003609 if (!textureCaps.renderable)
3610 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003611 context->handleError(InvalidOperation()
3612 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003613 return false;
3614 }
3615
Geoff Langdcab33b2015-07-21 13:03:16 -04003616 return true;
3617}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003618
3619bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3620{
Geoff Lang36167ab2015-12-07 10:27:14 -05003621 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003622 {
3623 // The default VAO should always exist
3624 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003625 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003626 return false;
3627 }
3628
3629 return true;
3630}
3631
Geoff Langc5629752015-12-07 16:29:04 -05003632bool ValidateProgramBinaryBase(Context *context,
3633 GLuint program,
3634 GLenum binaryFormat,
3635 const void *binary,
3636 GLint length)
3637{
3638 Program *programObject = GetValidProgram(context, program);
3639 if (programObject == nullptr)
3640 {
3641 return false;
3642 }
3643
3644 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3645 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3646 programBinaryFormats.end())
3647 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003648 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003649 return false;
3650 }
3651
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003652 if (context->hasActiveTransformFeedback(program))
3653 {
3654 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003655 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3656 "is associated with an active transform "
3657 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003658 return false;
3659 }
3660
Geoff Langc5629752015-12-07 16:29:04 -05003661 return true;
3662}
3663
3664bool ValidateGetProgramBinaryBase(Context *context,
3665 GLuint program,
3666 GLsizei bufSize,
3667 GLsizei *length,
3668 GLenum *binaryFormat,
3669 void *binary)
3670{
3671 Program *programObject = GetValidProgram(context, program);
3672 if (programObject == nullptr)
3673 {
3674 return false;
3675 }
3676
3677 if (!programObject->isLinked())
3678 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003679 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003680 return false;
3681 }
3682
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003683 if (context->getCaps().programBinaryFormats.empty())
3684 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003685 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003686 return false;
3687 }
3688
Geoff Langc5629752015-12-07 16:29:04 -05003689 return true;
3690}
Jamie Madillc29968b2016-01-20 11:17:23 -05003691
Jamie Madillc29968b2016-01-20 11:17:23 -05003692bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3693{
3694 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003695 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003696 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003697 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3698 return false;
3699 }
3700 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3701 {
3702 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003703 return false;
3704 }
3705
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003706 ASSERT(context->getGLState().getDrawFramebuffer());
3707 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003708 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3709
3710 // This should come first before the check for the default frame buffer
3711 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3712 // rather than INVALID_OPERATION
3713 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3714 {
3715 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3716
3717 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003718 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3719 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003720 {
3721 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003722 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3723 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3724 // 3.1 is still a bit ambiguous about the error, but future specs are
3725 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003726 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003727 return false;
3728 }
3729 else if (bufs[colorAttachment] >= maxColorAttachment)
3730 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003731 context->handleError(InvalidOperation()
3732 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003733 return false;
3734 }
3735 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3736 frameBufferId != 0)
3737 {
3738 // INVALID_OPERATION-GL is bound to buffer and ith argument
3739 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003740 context->handleError(InvalidOperation()
3741 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003742 return false;
3743 }
3744 }
3745
3746 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3747 // and n is not 1 or bufs is bound to value other than BACK and NONE
3748 if (frameBufferId == 0)
3749 {
3750 if (n != 1)
3751 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003752 context->handleError(InvalidOperation()
3753 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003754 return false;
3755 }
3756
3757 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3758 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003759 context->handleError(
3760 InvalidOperation()
3761 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003762 return false;
3763 }
3764 }
3765
3766 return true;
3767}
3768
Geoff Lang496c02d2016-10-20 11:38:11 -07003769bool ValidateGetBufferPointervBase(Context *context,
3770 GLenum target,
3771 GLenum pname,
3772 GLsizei *length,
3773 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003774{
Geoff Lang496c02d2016-10-20 11:38:11 -07003775 if (length)
3776 {
3777 *length = 0;
3778 }
3779
3780 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3781 {
3782 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003783 InvalidOperation()
3784 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003785 return false;
3786 }
3787
Olli Etuaho4f667482016-03-30 15:56:35 +03003788 if (!ValidBufferTarget(context, target))
3789 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003790 context->handleError(InvalidEnum() << "Buffer target not valid: 0x" << std::hex
3791 << std::uppercase << target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003792 return false;
3793 }
3794
Geoff Lang496c02d2016-10-20 11:38:11 -07003795 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003796 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003797 case GL_BUFFER_MAP_POINTER:
3798 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003799
Geoff Lang496c02d2016-10-20 11:38:11 -07003800 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003801 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003802 return false;
3803 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003804
3805 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3806 // target bound to zero generate an INVALID_OPERATION error."
3807 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003808 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003809 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003810 context->handleError(InvalidOperation()
3811 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003812 return false;
3813 }
3814
Geoff Lang496c02d2016-10-20 11:38:11 -07003815 if (length)
3816 {
3817 *length = 1;
3818 }
3819
Olli Etuaho4f667482016-03-30 15:56:35 +03003820 return true;
3821}
3822
3823bool ValidateUnmapBufferBase(Context *context, GLenum target)
3824{
3825 if (!ValidBufferTarget(context, target))
3826 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003827 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003828 return false;
3829 }
3830
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003831 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003832
3833 if (buffer == nullptr || !buffer->isMapped())
3834 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003835 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003836 return false;
3837 }
3838
3839 return true;
3840}
3841
3842bool ValidateMapBufferRangeBase(Context *context,
3843 GLenum target,
3844 GLintptr offset,
3845 GLsizeiptr length,
3846 GLbitfield access)
3847{
3848 if (!ValidBufferTarget(context, target))
3849 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003850 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003851 return false;
3852 }
3853
Brandon Jones6cad5662017-06-14 13:25:13 -07003854 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003855 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003856 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3857 return false;
3858 }
3859
3860 if (length < 0)
3861 {
3862 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003863 return false;
3864 }
3865
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003866 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003867
3868 if (!buffer)
3869 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003870 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003871 return false;
3872 }
3873
3874 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003875 CheckedNumeric<size_t> checkedOffset(offset);
3876 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003877
Jamie Madille2e406c2016-06-02 13:04:10 -04003878 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003879 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003880 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003881 return false;
3882 }
3883
3884 // Check for invalid bits in the mask
3885 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3886 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3887 GL_MAP_UNSYNCHRONIZED_BIT;
3888
3889 if (access & ~(allAccessBits))
3890 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003891 context->handleError(InvalidValue()
3892 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003893 return false;
3894 }
3895
3896 if (length == 0)
3897 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003898 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003899 return false;
3900 }
3901
3902 if (buffer->isMapped())
3903 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003904 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003905 return false;
3906 }
3907
3908 // Check for invalid bit combinations
3909 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3910 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003911 context->handleError(InvalidOperation()
3912 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003913 return false;
3914 }
3915
3916 GLbitfield writeOnlyBits =
3917 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3918
3919 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3920 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003921 context->handleError(InvalidOperation()
3922 << "Invalid access bits when mapping buffer for reading: 0x"
3923 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003924 return false;
3925 }
3926
3927 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3928 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003929 context->handleError(
3930 InvalidOperation()
3931 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003932 return false;
3933 }
Geoff Lang79f71042017-08-14 16:43:43 -04003934
3935 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003936}
3937
3938bool ValidateFlushMappedBufferRangeBase(Context *context,
3939 GLenum target,
3940 GLintptr offset,
3941 GLsizeiptr length)
3942{
Brandon Jones6cad5662017-06-14 13:25:13 -07003943 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003944 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003945 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3946 return false;
3947 }
3948
3949 if (length < 0)
3950 {
3951 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003952 return false;
3953 }
3954
3955 if (!ValidBufferTarget(context, target))
3956 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003957 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003958 return false;
3959 }
3960
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003961 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003962
3963 if (buffer == nullptr)
3964 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003965 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003966 return false;
3967 }
3968
3969 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3970 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003971 context->handleError(InvalidOperation()
3972 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003973 return false;
3974 }
3975
3976 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003977 CheckedNumeric<size_t> checkedOffset(offset);
3978 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003979
Jamie Madille2e406c2016-06-02 13:04:10 -04003980 if (!checkedSize.IsValid() ||
3981 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003982 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003983 context->handleError(InvalidValue()
3984 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003985 return false;
3986 }
3987
3988 return true;
3989}
3990
Olli Etuaho41997e72016-03-10 13:38:39 +02003991bool ValidateGenOrDelete(Context *context, GLint n)
3992{
3993 if (n < 0)
3994 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003995 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003996 return false;
3997 }
3998 return true;
3999}
4000
Geoff Langff5b2d52016-09-07 11:32:23 -04004001bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4002{
4003 if (!context->getExtensions().robustClientMemory)
4004 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004005 context->handleError(InvalidOperation()
4006 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004007 return false;
4008 }
4009
4010 if (bufSize < 0)
4011 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004012 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004013 return false;
4014 }
4015
4016 return true;
4017}
4018
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004019bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4020{
4021 if (bufSize < numParams)
4022 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004023 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4024 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004025 return false;
4026 }
4027
4028 return true;
4029}
4030
Jamie Madillbe849e42017-05-02 15:49:00 -04004031bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
4032 GLenum target,
4033 GLenum attachment,
4034 GLenum pname,
4035 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004036{
Geoff Langff5b2d52016-09-07 11:32:23 -04004037 if (!ValidFramebufferTarget(target))
4038 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004039 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004040 return false;
4041 }
4042
4043 int clientVersion = context->getClientMajorVersion();
4044
4045 switch (pname)
4046 {
4047 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4048 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4049 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4050 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4051 break;
4052
Martin Radeve5285d22017-07-14 16:23:53 +03004053 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4054 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4055 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4056 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4057 if (clientVersion < 3 || !context->getExtensions().multiview)
4058 {
4059 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4060 return false;
4061 }
4062 break;
4063
Geoff Langff5b2d52016-09-07 11:32:23 -04004064 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4065 if (clientVersion < 3 && !context->getExtensions().sRGB)
4066 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004067 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004068 return false;
4069 }
4070 break;
4071
4072 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4073 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4074 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4075 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4076 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4077 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4078 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4079 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4080 if (clientVersion < 3)
4081 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004082 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004083 return false;
4084 }
4085 break;
4086
4087 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004088 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004089 return false;
4090 }
4091
4092 // Determine if the attachment is a valid enum
4093 switch (attachment)
4094 {
4095 case GL_BACK:
4096 case GL_FRONT:
4097 case GL_DEPTH:
4098 case GL_STENCIL:
4099 case GL_DEPTH_STENCIL_ATTACHMENT:
4100 if (clientVersion < 3)
4101 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004102 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004103 return false;
4104 }
4105 break;
4106
4107 case GL_DEPTH_ATTACHMENT:
4108 case GL_STENCIL_ATTACHMENT:
4109 break;
4110
4111 default:
4112 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4113 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4114 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004115 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004116 return false;
4117 }
4118 break;
4119 }
4120
4121 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4122 ASSERT(framebuffer);
4123
4124 if (framebuffer->id() == 0)
4125 {
4126 if (clientVersion < 3)
4127 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004128 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004129 return false;
4130 }
4131
4132 switch (attachment)
4133 {
4134 case GL_BACK:
4135 case GL_DEPTH:
4136 case GL_STENCIL:
4137 break;
4138
4139 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004140 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004141 return false;
4142 }
4143 }
4144 else
4145 {
4146 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4147 {
4148 // Valid attachment query
4149 }
4150 else
4151 {
4152 switch (attachment)
4153 {
4154 case GL_DEPTH_ATTACHMENT:
4155 case GL_STENCIL_ATTACHMENT:
4156 break;
4157
4158 case GL_DEPTH_STENCIL_ATTACHMENT:
4159 if (!framebuffer->hasValidDepthStencil())
4160 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004161 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004162 return false;
4163 }
4164 break;
4165
4166 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004167 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004168 return false;
4169 }
4170 }
4171 }
4172
4173 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4174 if (attachmentObject)
4175 {
4176 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4177 attachmentObject->type() == GL_TEXTURE ||
4178 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4179
4180 switch (pname)
4181 {
4182 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4183 if (attachmentObject->type() != GL_RENDERBUFFER &&
4184 attachmentObject->type() != GL_TEXTURE)
4185 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004186 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004187 return false;
4188 }
4189 break;
4190
4191 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4192 if (attachmentObject->type() != GL_TEXTURE)
4193 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004194 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004195 return false;
4196 }
4197 break;
4198
4199 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4200 if (attachmentObject->type() != GL_TEXTURE)
4201 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004202 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004203 return false;
4204 }
4205 break;
4206
4207 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4208 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4209 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004210 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004211 return false;
4212 }
4213 break;
4214
4215 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4216 if (attachmentObject->type() != GL_TEXTURE)
4217 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004218 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004219 return false;
4220 }
4221 break;
4222
4223 default:
4224 break;
4225 }
4226 }
4227 else
4228 {
4229 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4230 // is NONE, then querying any other pname will generate INVALID_ENUM.
4231
4232 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4233 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4234 // INVALID_OPERATION for all other pnames
4235
4236 switch (pname)
4237 {
4238 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4239 break;
4240
4241 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4242 if (clientVersion < 3)
4243 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004244 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004245 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004246 return false;
4247 }
4248 break;
4249
4250 default:
4251 if (clientVersion < 3)
4252 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004253 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004254 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004255 return false;
4256 }
4257 else
4258 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004259 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004260 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004261 return false;
4262 }
4263 }
4264 }
4265
Martin Radeve5285d22017-07-14 16:23:53 +03004266 if (numParams)
4267 {
4268 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4269 {
4270 // Only when the viewport offsets are queried we can have a varying number of output
4271 // parameters.
4272 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4273 *numParams = numViews * 2;
4274 }
4275 else
4276 {
4277 // For all other queries we can have only one output parameter.
4278 *numParams = 1;
4279 }
4280 }
4281
Geoff Langff5b2d52016-09-07 11:32:23 -04004282 return true;
4283}
4284
4285bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4286 GLenum target,
4287 GLenum attachment,
4288 GLenum pname,
4289 GLsizei bufSize,
4290 GLsizei *numParams)
4291{
4292 if (!ValidateRobustEntryPoint(context, bufSize))
4293 {
4294 return false;
4295 }
4296
Jamie Madillbe849e42017-05-02 15:49:00 -04004297 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4298 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004299 {
4300 return false;
4301 }
4302
4303 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4304 {
4305 return false;
4306 }
4307
4308 return true;
4309}
4310
Geoff Langff5b2d52016-09-07 11:32:23 -04004311bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4312 GLenum target,
4313 GLenum pname,
4314 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004315 GLsizei *length,
4316 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004317{
4318 if (!ValidateRobustEntryPoint(context, bufSize))
4319 {
4320 return false;
4321 }
4322
Geoff Langebebe1c2016-10-14 12:01:31 -04004323 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004324 {
4325 return false;
4326 }
4327
Geoff Langebebe1c2016-10-14 12:01:31 -04004328 if (!ValidateRobustBufferSize(context, bufSize, *length))
4329 {
4330 return false;
4331 }
4332
4333 return true;
4334}
4335
4336bool ValidateGetBufferParameteri64v(ValidationContext *context,
4337 GLenum target,
4338 GLenum pname,
4339 GLint64 *params)
4340{
4341 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4342}
4343
4344bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4345 GLenum target,
4346 GLenum pname,
4347 GLsizei bufSize,
4348 GLsizei *length,
4349 GLint64 *params)
4350{
4351 if (!ValidateRobustEntryPoint(context, bufSize))
4352 {
4353 return false;
4354 }
4355
4356 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4357 {
4358 return false;
4359 }
4360
4361 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004362 {
4363 return false;
4364 }
4365
4366 return true;
4367}
4368
Jamie Madillbe849e42017-05-02 15:49:00 -04004369bool ValidateGetProgramivBase(ValidationContext *context,
4370 GLuint program,
4371 GLenum pname,
4372 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004373{
4374 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004375 if (numParams)
4376 {
4377 *numParams = 1;
4378 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004379
4380 Program *programObject = GetValidProgram(context, program);
4381 if (!programObject)
4382 {
4383 return false;
4384 }
4385
4386 switch (pname)
4387 {
4388 case GL_DELETE_STATUS:
4389 case GL_LINK_STATUS:
4390 case GL_VALIDATE_STATUS:
4391 case GL_INFO_LOG_LENGTH:
4392 case GL_ATTACHED_SHADERS:
4393 case GL_ACTIVE_ATTRIBUTES:
4394 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4395 case GL_ACTIVE_UNIFORMS:
4396 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4397 break;
4398
4399 case GL_PROGRAM_BINARY_LENGTH:
4400 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4401 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004402 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4403 "requires GL_OES_get_program_binary or "
4404 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004405 return false;
4406 }
4407 break;
4408
4409 case GL_ACTIVE_UNIFORM_BLOCKS:
4410 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4411 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4412 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4413 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4414 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4415 if (context->getClientMajorVersion() < 3)
4416 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004417 context->handleError(InvalidEnum() << "Querying requires at least ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004418 return false;
4419 }
4420 break;
4421
Yunchao He61afff12017-03-14 15:34:03 +08004422 case GL_PROGRAM_SEPARABLE:
4423 if (context->getClientVersion() < Version(3, 1))
4424 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004425 context->handleError(InvalidEnum() << "Querying requires at least ES 3.1.");
Yunchao He61afff12017-03-14 15:34:03 +08004426 return false;
4427 }
4428 break;
4429
Geoff Langff5b2d52016-09-07 11:32:23 -04004430 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004431 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004432 return false;
4433 }
4434
4435 return true;
4436}
4437
4438bool ValidateGetProgramivRobustANGLE(Context *context,
4439 GLuint program,
4440 GLenum pname,
4441 GLsizei bufSize,
4442 GLsizei *numParams)
4443{
4444 if (!ValidateRobustEntryPoint(context, bufSize))
4445 {
4446 return false;
4447 }
4448
Jamie Madillbe849e42017-05-02 15:49:00 -04004449 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004450 {
4451 return false;
4452 }
4453
4454 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4455 {
4456 return false;
4457 }
4458
4459 return true;
4460}
4461
Geoff Lang740d9022016-10-07 11:20:52 -04004462bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4463 GLenum target,
4464 GLenum pname,
4465 GLsizei bufSize,
4466 GLsizei *length,
4467 GLint *params)
4468{
4469 if (!ValidateRobustEntryPoint(context, bufSize))
4470 {
4471 return false;
4472 }
4473
4474 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4475 {
4476 return false;
4477 }
4478
4479 if (!ValidateRobustBufferSize(context, bufSize, *length))
4480 {
4481 return false;
4482 }
4483
4484 return true;
4485}
4486
Geoff Langd7d0ed32016-10-07 11:33:51 -04004487bool ValidateGetShaderivRobustANGLE(Context *context,
4488 GLuint shader,
4489 GLenum pname,
4490 GLsizei bufSize,
4491 GLsizei *length,
4492 GLint *params)
4493{
4494 if (!ValidateRobustEntryPoint(context, bufSize))
4495 {
4496 return false;
4497 }
4498
4499 if (!ValidateGetShaderivBase(context, shader, pname, length))
4500 {
4501 return false;
4502 }
4503
4504 if (!ValidateRobustBufferSize(context, bufSize, *length))
4505 {
4506 return false;
4507 }
4508
4509 return true;
4510}
4511
Geoff Langc1984ed2016-10-07 12:41:00 -04004512bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4513 GLenum target,
4514 GLenum pname,
4515 GLsizei bufSize,
4516 GLsizei *length,
4517 GLfloat *params)
4518{
4519 if (!ValidateRobustEntryPoint(context, bufSize))
4520 {
4521 return false;
4522 }
4523
4524 if (!ValidateGetTexParameterBase(context, target, pname, length))
4525 {
4526 return false;
4527 }
4528
4529 if (!ValidateRobustBufferSize(context, bufSize, *length))
4530 {
4531 return false;
4532 }
4533
4534 return true;
4535}
4536
Geoff Langc1984ed2016-10-07 12:41:00 -04004537bool ValidateGetTexParameterivRobustANGLE(Context *context,
4538 GLenum target,
4539 GLenum pname,
4540 GLsizei bufSize,
4541 GLsizei *length,
4542 GLint *params)
4543{
4544 if (!ValidateRobustEntryPoint(context, bufSize))
4545 {
4546 return false;
4547 }
4548
4549 if (!ValidateGetTexParameterBase(context, target, pname, length))
4550 {
4551 return false;
4552 }
4553
4554 if (!ValidateRobustBufferSize(context, bufSize, *length))
4555 {
4556 return false;
4557 }
4558
4559 return true;
4560}
4561
Geoff Langc1984ed2016-10-07 12:41:00 -04004562bool ValidateTexParameterfvRobustANGLE(Context *context,
4563 GLenum target,
4564 GLenum pname,
4565 GLsizei bufSize,
4566 const GLfloat *params)
4567{
4568 if (!ValidateRobustEntryPoint(context, bufSize))
4569 {
4570 return false;
4571 }
4572
4573 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4574}
4575
Geoff Langc1984ed2016-10-07 12:41:00 -04004576bool ValidateTexParameterivRobustANGLE(Context *context,
4577 GLenum target,
4578 GLenum pname,
4579 GLsizei bufSize,
4580 const GLint *params)
4581{
4582 if (!ValidateRobustEntryPoint(context, bufSize))
4583 {
4584 return false;
4585 }
4586
4587 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4588}
4589
4590bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4591{
4592 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4593}
4594
4595bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4596 GLuint sampler,
4597 GLenum pname,
4598 GLuint bufSize,
4599 GLsizei *length,
4600 GLfloat *params)
4601{
4602 if (!ValidateRobustEntryPoint(context, bufSize))
4603 {
4604 return false;
4605 }
4606
4607 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4608 {
4609 return false;
4610 }
4611
4612 if (!ValidateRobustBufferSize(context, bufSize, *length))
4613 {
4614 return false;
4615 }
4616
4617 return true;
4618}
4619
4620bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4621{
4622 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4623}
4624
4625bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4626 GLuint sampler,
4627 GLenum pname,
4628 GLuint bufSize,
4629 GLsizei *length,
4630 GLint *params)
4631{
4632 if (!ValidateRobustEntryPoint(context, bufSize))
4633 {
4634 return false;
4635 }
4636
4637 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4638 {
4639 return false;
4640 }
4641
4642 if (!ValidateRobustBufferSize(context, bufSize, *length))
4643 {
4644 return false;
4645 }
4646
4647 return true;
4648}
4649
4650bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4651{
4652 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4653}
4654
4655bool ValidateSamplerParameterfv(Context *context,
4656 GLuint sampler,
4657 GLenum pname,
4658 const GLfloat *params)
4659{
4660 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4661}
4662
4663bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4664 GLuint sampler,
4665 GLenum pname,
4666 GLsizei bufSize,
4667 const GLfloat *params)
4668{
4669 if (!ValidateRobustEntryPoint(context, bufSize))
4670 {
4671 return false;
4672 }
4673
4674 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4675}
4676
4677bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4678{
4679 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4680}
4681
4682bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4683{
4684 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4685}
4686
4687bool ValidateSamplerParameterivRobustANGLE(Context *context,
4688 GLuint sampler,
4689 GLenum pname,
4690 GLsizei bufSize,
4691 const GLint *params)
4692{
4693 if (!ValidateRobustEntryPoint(context, bufSize))
4694 {
4695 return false;
4696 }
4697
4698 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4699}
4700
Geoff Lang0b031062016-10-13 14:30:04 -04004701bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4702 GLuint index,
4703 GLenum pname,
4704 GLsizei bufSize,
4705 GLsizei *length,
4706 GLfloat *params)
4707{
4708 if (!ValidateRobustEntryPoint(context, bufSize))
4709 {
4710 return false;
4711 }
4712
4713 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4714 {
4715 return false;
4716 }
4717
4718 if (!ValidateRobustBufferSize(context, bufSize, *length))
4719 {
4720 return false;
4721 }
4722
4723 return true;
4724}
4725
Geoff Lang0b031062016-10-13 14:30:04 -04004726bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4727 GLuint index,
4728 GLenum pname,
4729 GLsizei bufSize,
4730 GLsizei *length,
4731 GLint *params)
4732{
4733 if (!ValidateRobustEntryPoint(context, bufSize))
4734 {
4735 return false;
4736 }
4737
4738 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4739 {
4740 return false;
4741 }
4742
4743 if (!ValidateRobustBufferSize(context, bufSize, *length))
4744 {
4745 return false;
4746 }
4747
4748 return true;
4749}
4750
Geoff Lang0b031062016-10-13 14:30:04 -04004751bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4752 GLuint index,
4753 GLenum pname,
4754 GLsizei bufSize,
4755 GLsizei *length,
4756 void **pointer)
4757{
4758 if (!ValidateRobustEntryPoint(context, bufSize))
4759 {
4760 return false;
4761 }
4762
4763 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4764 {
4765 return false;
4766 }
4767
4768 if (!ValidateRobustBufferSize(context, bufSize, *length))
4769 {
4770 return false;
4771 }
4772
4773 return true;
4774}
4775
4776bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
4777{
4778 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4779}
4780
4781bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4782 GLuint index,
4783 GLenum pname,
4784 GLsizei bufSize,
4785 GLsizei *length,
4786 GLint *params)
4787{
4788 if (!ValidateRobustEntryPoint(context, bufSize))
4789 {
4790 return false;
4791 }
4792
4793 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4794 {
4795 return false;
4796 }
4797
4798 if (!ValidateRobustBufferSize(context, bufSize, *length))
4799 {
4800 return false;
4801 }
4802
4803 return true;
4804}
4805
4806bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
4807{
4808 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4809}
4810
4811bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4812 GLuint index,
4813 GLenum pname,
4814 GLsizei bufSize,
4815 GLsizei *length,
4816 GLuint *params)
4817{
4818 if (!ValidateRobustEntryPoint(context, bufSize))
4819 {
4820 return false;
4821 }
4822
4823 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4824 {
4825 return false;
4826 }
4827
4828 if (!ValidateRobustBufferSize(context, bufSize, *length))
4829 {
4830 return false;
4831 }
4832
4833 return true;
4834}
4835
Geoff Lang6899b872016-10-14 11:30:13 -04004836bool ValidateGetActiveUniformBlockiv(Context *context,
4837 GLuint program,
4838 GLuint uniformBlockIndex,
4839 GLenum pname,
4840 GLint *params)
4841{
4842 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
4843}
4844
4845bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4846 GLuint program,
4847 GLuint uniformBlockIndex,
4848 GLenum pname,
4849 GLsizei bufSize,
4850 GLsizei *length,
4851 GLint *params)
4852{
4853 if (!ValidateRobustEntryPoint(context, bufSize))
4854 {
4855 return false;
4856 }
4857
4858 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4859 {
4860 return false;
4861 }
4862
4863 if (!ValidateRobustBufferSize(context, bufSize, *length))
4864 {
4865 return false;
4866 }
4867
4868 return true;
4869}
4870
Geoff Lang0a9661f2016-10-20 10:59:20 -07004871bool ValidateGetInternalFormativ(Context *context,
4872 GLenum target,
4873 GLenum internalformat,
4874 GLenum pname,
4875 GLsizei bufSize,
4876 GLint *params)
4877{
4878 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4879 nullptr);
4880}
4881
4882bool ValidateGetInternalFormativRobustANGLE(Context *context,
4883 GLenum target,
4884 GLenum internalformat,
4885 GLenum pname,
4886 GLsizei bufSize,
4887 GLsizei *length,
4888 GLint *params)
4889{
4890 if (!ValidateRobustEntryPoint(context, bufSize))
4891 {
4892 return false;
4893 }
4894
4895 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4896 {
4897 return false;
4898 }
4899
4900 if (!ValidateRobustBufferSize(context, bufSize, *length))
4901 {
4902 return false;
4903 }
4904
4905 return true;
4906}
4907
Shao80957d92017-02-20 21:25:59 +08004908bool ValidateVertexFormatBase(ValidationContext *context,
4909 GLuint attribIndex,
4910 GLint size,
4911 GLenum type,
4912 GLboolean pureInteger)
4913{
4914 const Caps &caps = context->getCaps();
4915 if (attribIndex >= caps.maxVertexAttributes)
4916 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004917 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004918 return false;
4919 }
4920
4921 if (size < 1 || size > 4)
4922 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004923 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004924 return false;
Shao80957d92017-02-20 21:25:59 +08004925 }
4926
4927 switch (type)
4928 {
4929 case GL_BYTE:
4930 case GL_UNSIGNED_BYTE:
4931 case GL_SHORT:
4932 case GL_UNSIGNED_SHORT:
4933 break;
4934
4935 case GL_INT:
4936 case GL_UNSIGNED_INT:
4937 if (context->getClientMajorVersion() < 3)
4938 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004939 context->handleError(InvalidEnum()
4940 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004941 return false;
4942 }
4943 break;
4944
4945 case GL_FIXED:
4946 case GL_FLOAT:
4947 if (pureInteger)
4948 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004949 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004950 return false;
4951 }
4952 break;
4953
4954 case GL_HALF_FLOAT:
4955 if (context->getClientMajorVersion() < 3)
4956 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004957 context->handleError(InvalidEnum()
4958 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004959 return false;
4960 }
4961 if (pureInteger)
4962 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004963 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004964 return false;
4965 }
4966 break;
4967
4968 case GL_INT_2_10_10_10_REV:
4969 case GL_UNSIGNED_INT_2_10_10_10_REV:
4970 if (context->getClientMajorVersion() < 3)
4971 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004972 context->handleError(InvalidEnum()
4973 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004974 return false;
4975 }
4976 if (pureInteger)
4977 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004978 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004979 return false;
4980 }
4981 if (size != 4)
4982 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004983 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4984 "UNSIGNED_INT_2_10_10_10_REV and "
4985 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004986 return false;
4987 }
4988 break;
4989
4990 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004991 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004992 return false;
4993 }
4994
4995 return true;
4996}
4997
Geoff Lang76e65652017-03-27 14:58:02 -04004998// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4999// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5000// specified clear value and the type of a buffer that is being cleared generates an
5001// INVALID_OPERATION error instead of producing undefined results
5002bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
5003 GLint drawbuffer,
5004 const GLenum *validComponentTypes,
5005 size_t validComponentTypeCount)
5006{
5007 const FramebufferAttachment *attachment =
5008 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5009 if (attachment)
5010 {
5011 GLenum componentType = attachment->getFormat().info->componentType;
5012 const GLenum *end = validComponentTypes + validComponentTypeCount;
5013 if (std::find(validComponentTypes, end, componentType) == end)
5014 {
5015 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005016 InvalidOperation()
5017 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005018 return false;
5019 }
5020 }
5021
5022 return true;
5023}
5024
Corentin Wallezb2931602017-04-11 15:58:57 -04005025bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
5026 GLsizei imageSize,
5027 GLsizei dataSize)
5028{
5029 if (!ValidateRobustEntryPoint(context, dataSize))
5030 {
5031 return false;
5032 }
5033
5034 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
5035 if (pixelUnpackBuffer == nullptr)
5036 {
5037 if (dataSize < imageSize)
5038 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005039 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005040 }
5041 }
5042 return true;
5043}
5044
Jamie Madillbe849e42017-05-02 15:49:00 -04005045bool ValidateGetBufferParameterBase(ValidationContext *context,
5046 GLenum target,
5047 GLenum pname,
5048 bool pointerVersion,
5049 GLsizei *numParams)
5050{
5051 if (numParams)
5052 {
5053 *numParams = 0;
5054 }
5055
5056 if (!ValidBufferTarget(context, target))
5057 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005058 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005059 return false;
5060 }
5061
5062 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5063 if (!buffer)
5064 {
5065 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005066 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005067 return false;
5068 }
5069
5070 const Extensions &extensions = context->getExtensions();
5071
5072 switch (pname)
5073 {
5074 case GL_BUFFER_USAGE:
5075 case GL_BUFFER_SIZE:
5076 break;
5077
5078 case GL_BUFFER_ACCESS_OES:
5079 if (!extensions.mapBuffer)
5080 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005081 context->handleError(InvalidEnum()
5082 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005083 return false;
5084 }
5085 break;
5086
5087 case GL_BUFFER_MAPPED:
5088 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5089 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5090 !extensions.mapBufferRange)
5091 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005092 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5093 "GL_OES_mapbuffer or "
5094 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005095 return false;
5096 }
5097 break;
5098
5099 case GL_BUFFER_MAP_POINTER:
5100 if (!pointerVersion)
5101 {
5102 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005103 InvalidEnum()
5104 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005105 return false;
5106 }
5107 break;
5108
5109 case GL_BUFFER_ACCESS_FLAGS:
5110 case GL_BUFFER_MAP_OFFSET:
5111 case GL_BUFFER_MAP_LENGTH:
5112 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5113 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005114 context->handleError(InvalidEnum()
5115 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005116 return false;
5117 }
5118 break;
5119
5120 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005121 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005122 return false;
5123 }
5124
5125 // All buffer parameter queries return one value.
5126 if (numParams)
5127 {
5128 *numParams = 1;
5129 }
5130
5131 return true;
5132}
5133
5134bool ValidateGetRenderbufferParameterivBase(Context *context,
5135 GLenum target,
5136 GLenum pname,
5137 GLsizei *length)
5138{
5139 if (length)
5140 {
5141 *length = 0;
5142 }
5143
5144 if (target != GL_RENDERBUFFER)
5145 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005146 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005147 return false;
5148 }
5149
5150 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5151 if (renderbuffer == nullptr)
5152 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005153 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005154 return false;
5155 }
5156
5157 switch (pname)
5158 {
5159 case GL_RENDERBUFFER_WIDTH:
5160 case GL_RENDERBUFFER_HEIGHT:
5161 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5162 case GL_RENDERBUFFER_RED_SIZE:
5163 case GL_RENDERBUFFER_GREEN_SIZE:
5164 case GL_RENDERBUFFER_BLUE_SIZE:
5165 case GL_RENDERBUFFER_ALPHA_SIZE:
5166 case GL_RENDERBUFFER_DEPTH_SIZE:
5167 case GL_RENDERBUFFER_STENCIL_SIZE:
5168 break;
5169
5170 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5171 if (!context->getExtensions().framebufferMultisample)
5172 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005173 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005174 return false;
5175 }
5176 break;
5177
5178 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005179 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005180 return false;
5181 }
5182
5183 if (length)
5184 {
5185 *length = 1;
5186 }
5187 return true;
5188}
5189
5190bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5191{
5192 if (length)
5193 {
5194 *length = 0;
5195 }
5196
5197 if (GetValidShader(context, shader) == nullptr)
5198 {
5199 return false;
5200 }
5201
5202 switch (pname)
5203 {
5204 case GL_SHADER_TYPE:
5205 case GL_DELETE_STATUS:
5206 case GL_COMPILE_STATUS:
5207 case GL_INFO_LOG_LENGTH:
5208 case GL_SHADER_SOURCE_LENGTH:
5209 break;
5210
5211 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5212 if (!context->getExtensions().translatedShaderSource)
5213 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005214 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005215 return false;
5216 }
5217 break;
5218
5219 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005220 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005221 return false;
5222 }
5223
5224 if (length)
5225 {
5226 *length = 1;
5227 }
5228 return true;
5229}
5230
5231bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
5232{
5233 if (length)
5234 {
5235 *length = 0;
5236 }
5237
5238 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5239 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005240 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005241 return false;
5242 }
5243
5244 if (context->getTargetTexture(target) == nullptr)
5245 {
5246 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005247 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005248 return false;
5249 }
5250
5251 switch (pname)
5252 {
5253 case GL_TEXTURE_MAG_FILTER:
5254 case GL_TEXTURE_MIN_FILTER:
5255 case GL_TEXTURE_WRAP_S:
5256 case GL_TEXTURE_WRAP_T:
5257 break;
5258
5259 case GL_TEXTURE_USAGE_ANGLE:
5260 if (!context->getExtensions().textureUsage)
5261 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005262 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005263 return false;
5264 }
5265 break;
5266
5267 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5268 if (!context->getExtensions().textureFilterAnisotropic)
5269 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005270 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005271 return false;
5272 }
5273 break;
5274
5275 case GL_TEXTURE_IMMUTABLE_FORMAT:
5276 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5277 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005278 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005279 return false;
5280 }
5281 break;
5282
5283 case GL_TEXTURE_WRAP_R:
5284 case GL_TEXTURE_IMMUTABLE_LEVELS:
5285 case GL_TEXTURE_SWIZZLE_R:
5286 case GL_TEXTURE_SWIZZLE_G:
5287 case GL_TEXTURE_SWIZZLE_B:
5288 case GL_TEXTURE_SWIZZLE_A:
5289 case GL_TEXTURE_BASE_LEVEL:
5290 case GL_TEXTURE_MAX_LEVEL:
5291 case GL_TEXTURE_MIN_LOD:
5292 case GL_TEXTURE_MAX_LOD:
5293 case GL_TEXTURE_COMPARE_MODE:
5294 case GL_TEXTURE_COMPARE_FUNC:
5295 if (context->getClientMajorVersion() < 3)
5296 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005297 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005298 return false;
5299 }
5300 break;
5301
5302 case GL_TEXTURE_SRGB_DECODE_EXT:
5303 if (!context->getExtensions().textureSRGBDecode)
5304 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005305 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005306 return false;
5307 }
5308 break;
5309
5310 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005311 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005312 return false;
5313 }
5314
5315 if (length)
5316 {
5317 *length = 1;
5318 }
5319 return true;
5320}
5321
5322bool ValidateGetVertexAttribBase(Context *context,
5323 GLuint index,
5324 GLenum pname,
5325 GLsizei *length,
5326 bool pointer,
5327 bool pureIntegerEntryPoint)
5328{
5329 if (length)
5330 {
5331 *length = 0;
5332 }
5333
5334 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5335 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005336 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005337 return false;
5338 }
5339
5340 if (index >= context->getCaps().maxVertexAttributes)
5341 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005342 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005343 return false;
5344 }
5345
5346 if (pointer)
5347 {
5348 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5349 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005350 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005351 return false;
5352 }
5353 }
5354 else
5355 {
5356 switch (pname)
5357 {
5358 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5359 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5360 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5361 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5362 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5363 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5364 case GL_CURRENT_VERTEX_ATTRIB:
5365 break;
5366
5367 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5368 static_assert(
5369 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5370 "ANGLE extension enums not equal to GL enums.");
5371 if (context->getClientMajorVersion() < 3 &&
5372 !context->getExtensions().instancedArrays)
5373 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005374 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5375 "requires OpenGL ES 3.0 or "
5376 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005377 return false;
5378 }
5379 break;
5380
5381 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5382 if (context->getClientMajorVersion() < 3)
5383 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005384 context->handleError(
5385 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005386 return false;
5387 }
5388 break;
5389
5390 case GL_VERTEX_ATTRIB_BINDING:
5391 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5392 if (context->getClientVersion() < ES_3_1)
5393 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005394 context->handleError(InvalidEnum()
5395 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005396 return false;
5397 }
5398 break;
5399
5400 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005401 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005402 return false;
5403 }
5404 }
5405
5406 if (length)
5407 {
5408 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5409 {
5410 *length = 4;
5411 }
5412 else
5413 {
5414 *length = 1;
5415 }
5416 }
5417
5418 return true;
5419}
5420
Jamie Madill4928b7c2017-06-20 12:57:39 -04005421bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005422 GLint x,
5423 GLint y,
5424 GLsizei width,
5425 GLsizei height,
5426 GLenum format,
5427 GLenum type,
5428 GLsizei bufSize,
5429 GLsizei *length,
5430 GLsizei *columns,
5431 GLsizei *rows,
5432 void *pixels)
5433{
5434 if (length != nullptr)
5435 {
5436 *length = 0;
5437 }
5438 if (rows != nullptr)
5439 {
5440 *rows = 0;
5441 }
5442 if (columns != nullptr)
5443 {
5444 *columns = 0;
5445 }
5446
5447 if (width < 0 || height < 0)
5448 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005449 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005450 return false;
5451 }
5452
5453 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5454
5455 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5456 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005457 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005458 return false;
5459 }
5460
5461 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005463 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005464 return false;
5465 }
5466
5467 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5468 ASSERT(framebuffer);
5469
5470 if (framebuffer->getReadBufferState() == GL_NONE)
5471 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005472 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005473 return false;
5474 }
5475
5476 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5477 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5478 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5479 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5480 // situation is an application error that would lead to a crash in ANGLE.
5481 if (readBuffer == nullptr)
5482 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005483 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005484 return false;
5485 }
5486
Martin Radev28031682017-07-28 14:47:56 +03005487 // ANGLE_multiview, Revision 1:
5488 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5489 // current read framebuffer is not NONE.
5490 if (readBuffer->getMultiviewLayout() != GL_NONE)
5491 {
5492 context->handleError(InvalidFramebufferOperation()
5493 << "Attempting to read from a multi-view framebuffer.");
5494 return false;
5495 }
5496
Geoff Lang280ba992017-04-18 16:30:58 -04005497 if (context->getExtensions().webglCompatibility)
5498 {
5499 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5500 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5501 // and type before validating the combination of format and type. However, the
5502 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5503 // verifies that GL_INVALID_OPERATION is generated.
5504 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5505 // dEQP/WebGL.
5506 if (!ValidReadPixelsFormatEnum(context, format))
5507 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005508 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005509 return false;
5510 }
5511
5512 if (!ValidReadPixelsTypeEnum(context, type))
5513 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005514 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005515 return false;
5516 }
5517 }
5518
Jamie Madill4928b7c2017-06-20 12:57:39 -04005519 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5520 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005521 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5522
5523 bool validFormatTypeCombination =
5524 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5525
5526 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5527 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005528 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005529 return false;
5530 }
5531
5532 // Check for pixel pack buffer related API errors
5533 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5534 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5535 {
5536 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005537 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005538 return false;
5539 }
5540
5541 // .. the data would be packed to the buffer object such that the memory writes required
5542 // would exceed the data store size.
5543 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5544 const gl::Extents size(width, height, 1);
5545 const auto &pack = context->getGLState().getPackState();
5546
5547 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5548 if (endByteOrErr.isError())
5549 {
5550 context->handleError(endByteOrErr.getError());
5551 return false;
5552 }
5553
5554 size_t endByte = endByteOrErr.getResult();
5555 if (bufSize >= 0)
5556 {
5557 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5558 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005559 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005560 return false;
5561 }
5562 }
5563
5564 if (pixelPackBuffer != nullptr)
5565 {
5566 CheckedNumeric<size_t> checkedEndByte(endByte);
5567 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5568 checkedEndByte += checkedOffset;
5569
5570 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5571 {
5572 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005573 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005574 return false;
5575 }
5576 }
5577
5578 if (pixelPackBuffer == nullptr && length != nullptr)
5579 {
5580 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5581 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005582 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005583 return false;
5584 }
5585
5586 *length = static_cast<GLsizei>(endByte);
5587 }
5588
5589 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5590 angle::CheckedNumeric<int> clippedExtent(length);
5591 if (start < 0)
5592 {
5593 // "subtract" the area that is less than 0
5594 clippedExtent += start;
5595 }
5596
5597 const int readExtent = start + length;
5598 if (readExtent > bufferSize)
5599 {
5600 // Subtract the region to the right of the read buffer
5601 clippedExtent -= (readExtent - bufferSize);
5602 }
5603
5604 if (!clippedExtent.IsValid())
5605 {
5606 return 0;
5607 }
5608
5609 return std::max(clippedExtent.ValueOrDie(), 0);
5610 };
5611
5612 if (columns != nullptr)
5613 {
5614 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5615 }
5616
5617 if (rows != nullptr)
5618 {
5619 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5620 }
5621
5622 return true;
5623}
5624
5625template <typename ParamType>
5626bool ValidateTexParameterBase(Context *context,
5627 GLenum target,
5628 GLenum pname,
5629 GLsizei bufSize,
5630 const ParamType *params)
5631{
5632 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5633 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005634 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005635 return false;
5636 }
5637
5638 if (context->getTargetTexture(target) == nullptr)
5639 {
5640 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005641 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005642 return false;
5643 }
5644
5645 const GLsizei minBufSize = 1;
5646 if (bufSize >= 0 && bufSize < minBufSize)
5647 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005648 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005649 return false;
5650 }
5651
5652 switch (pname)
5653 {
5654 case GL_TEXTURE_WRAP_R:
5655 case GL_TEXTURE_SWIZZLE_R:
5656 case GL_TEXTURE_SWIZZLE_G:
5657 case GL_TEXTURE_SWIZZLE_B:
5658 case GL_TEXTURE_SWIZZLE_A:
5659 case GL_TEXTURE_BASE_LEVEL:
5660 case GL_TEXTURE_MAX_LEVEL:
5661 case GL_TEXTURE_COMPARE_MODE:
5662 case GL_TEXTURE_COMPARE_FUNC:
5663 case GL_TEXTURE_MIN_LOD:
5664 case GL_TEXTURE_MAX_LOD:
5665 if (context->getClientMajorVersion() < 3)
5666 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005667 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005668 return false;
5669 }
5670 if (target == GL_TEXTURE_EXTERNAL_OES &&
5671 !context->getExtensions().eglImageExternalEssl3)
5672 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005673 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5674 "available without "
5675 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005676 return false;
5677 }
5678 break;
5679
5680 default:
5681 break;
5682 }
5683
JiangYizhou4cff8d62017-07-06 14:54:09 +08005684 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5685 {
5686 switch (pname)
5687 {
5688 case GL_TEXTURE_MIN_FILTER:
5689 case GL_TEXTURE_MAG_FILTER:
5690 case GL_TEXTURE_WRAP_S:
5691 case GL_TEXTURE_WRAP_T:
5692 case GL_TEXTURE_WRAP_R:
5693 case GL_TEXTURE_MIN_LOD:
5694 case GL_TEXTURE_MAX_LOD:
5695 case GL_TEXTURE_COMPARE_MODE:
5696 case GL_TEXTURE_COMPARE_FUNC:
5697 context->handleError(InvalidEnum()
5698 << "Invalid parameter for 2D multisampled textures.");
5699 return false;
5700 }
5701 }
5702
Jamie Madillbe849e42017-05-02 15:49:00 -04005703 switch (pname)
5704 {
5705 case GL_TEXTURE_WRAP_S:
5706 case GL_TEXTURE_WRAP_T:
5707 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005708 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005709 bool restrictedWrapModes =
5710 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5711 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5712 {
5713 return false;
5714 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005715 }
5716 break;
5717
5718 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005719 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005720 bool restrictedMinFilter =
5721 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5722 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5723 {
5724 return false;
5725 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005726 }
5727 break;
5728
5729 case GL_TEXTURE_MAG_FILTER:
5730 if (!ValidateTextureMagFilterValue(context, params))
5731 {
5732 return false;
5733 }
5734 break;
5735
5736 case GL_TEXTURE_USAGE_ANGLE:
5737 switch (ConvertToGLenum(params[0]))
5738 {
5739 case GL_NONE:
5740 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5741 break;
5742
5743 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005744 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005745 return false;
5746 }
5747 break;
5748
5749 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5750 if (!context->getExtensions().textureFilterAnisotropic)
5751 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005752 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005753 return false;
5754 }
5755
5756 // we assume the parameter passed to this validation method is truncated, not rounded
5757 if (params[0] < 1)
5758 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005759 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005760 return false;
5761 }
5762 break;
5763
5764 case GL_TEXTURE_MIN_LOD:
5765 case GL_TEXTURE_MAX_LOD:
5766 // any value is permissible
5767 break;
5768
5769 case GL_TEXTURE_COMPARE_MODE:
5770 if (!ValidateTextureCompareModeValue(context, params))
5771 {
5772 return false;
5773 }
5774 break;
5775
5776 case GL_TEXTURE_COMPARE_FUNC:
5777 if (!ValidateTextureCompareFuncValue(context, params))
5778 {
5779 return false;
5780 }
5781 break;
5782
5783 case GL_TEXTURE_SWIZZLE_R:
5784 case GL_TEXTURE_SWIZZLE_G:
5785 case GL_TEXTURE_SWIZZLE_B:
5786 case GL_TEXTURE_SWIZZLE_A:
5787 switch (ConvertToGLenum(params[0]))
5788 {
5789 case GL_RED:
5790 case GL_GREEN:
5791 case GL_BLUE:
5792 case GL_ALPHA:
5793 case GL_ZERO:
5794 case GL_ONE:
5795 break;
5796
5797 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005798 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005799 return false;
5800 }
5801 break;
5802
5803 case GL_TEXTURE_BASE_LEVEL:
5804 if (params[0] < 0)
5805 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005806 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005807 return false;
5808 }
5809 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5810 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005811 context->handleError(InvalidOperation()
5812 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005813 return false;
5814 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005815 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5816 {
5817 context->handleError(InvalidOperation()
5818 << "Base level must be 0 for multisampled textures.");
5819 return false;
5820 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005821 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5822 {
5823 context->handleError(InvalidOperation()
5824 << "Base level must be 0 for rectangle textures.");
5825 return false;
5826 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005827 break;
5828
5829 case GL_TEXTURE_MAX_LEVEL:
5830 if (params[0] < 0)
5831 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005832 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005833 return false;
5834 }
5835 break;
5836
5837 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5838 if (context->getClientVersion() < Version(3, 1))
5839 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005840 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005841 return false;
5842 }
5843 switch (ConvertToGLenum(params[0]))
5844 {
5845 case GL_DEPTH_COMPONENT:
5846 case GL_STENCIL_INDEX:
5847 break;
5848
5849 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005850 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005851 return false;
5852 }
5853 break;
5854
5855 case GL_TEXTURE_SRGB_DECODE_EXT:
5856 if (!ValidateTextureSRGBDecodeValue(context, params))
5857 {
5858 return false;
5859 }
5860 break;
5861
5862 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005863 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005864 return false;
5865 }
5866
5867 return true;
5868}
5869
5870template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5871template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5872
Jamie Madillc29968b2016-01-20 11:17:23 -05005873} // namespace gl