blob: 2f68f57c788f7e3d7d5567c2017530f7f643e0d2 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040012#include "libANGLE/Display.h"
Brandon Jones6cad5662017-06-14 13:25:13 -070013#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Framebuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
Geoff Langa8406172015-07-21 16:53:39 -040016#include "libANGLE/Image.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050017#include "libANGLE/Program.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Query.h"
19#include "libANGLE/Texture.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/TransformFeedback.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040021#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050022#include "libANGLE/VertexArray.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040023#include "libANGLE/formatutils.h"
24#include "libANGLE/validationES2.h"
25#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040026
27#include "common/mathutil.h"
28#include "common/utilities.h"
29
Jamie Madille2e406c2016-06-02 13:04:10 -040030using namespace angle;
31
Geoff Lange8ebe7f2013-08-05 15:03:13 -040032namespace gl
33{
Jamie Madill1ca74672015-07-21 15:14:11 -040034namespace
35{
Corentin Wallez92db6942016-12-09 13:10:36 -050036bool ValidateDrawAttribs(ValidationContext *context,
37 GLint primcount,
38 GLint maxVertex,
39 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040040{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070041 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040042 const gl::Program *program = state.getProgram();
43
Corentin Wallez327411e2016-12-09 11:09:17 -050044 bool webglCompatibility = context->getExtensions().webglCompatibility;
45
Jamie Madill231c7f52017-04-26 13:45:37 -040046 const VertexArray *vao = state.getVertexArray();
47 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080048 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madill231c7f52017-04-26 13:45:37 -040049 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040050 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
51 {
52 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallez672f7f32017-06-15 17:42:17 -040053
54 // No need to range check for disabled attribs.
55 if (!attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040056 {
Corentin Wallezfd456442016-12-21 17:57:00 -050057 continue;
58 }
Jamie Madill1ca74672015-07-21 15:14:11 -040059
Jamie Madill231c7f52017-04-26 13:45:37 -040060 // If we have no buffer, then we either get an error, or there are no more checks to be
61 // done.
Corentin Wallez672f7f32017-06-15 17:42:17 -040062 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
63 gl::Buffer *buffer = binding.getBuffer().get();
Corentin Wallezfd456442016-12-21 17:57:00 -050064 if (!buffer)
65 {
Geoff Langfeb8c682017-02-13 16:07:35 -050066 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -050067 {
68 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050069 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
70 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
71 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
72 // error.
Brandon Jonesafa75152017-07-21 13:11:29 -070073 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
Corentin Wallezfd456442016-12-21 17:57:00 -050074 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050075 }
Corentin Wallezfd456442016-12-21 17:57:00 -050076 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040077 {
78 // This is an application error that would normally result in a crash,
79 // but we catch it and return an error
Brandon Jonesafa75152017-07-21 13:11:29 -070080 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
Jamie Madill1ca74672015-07-21 15:14:11 -040081 return false;
82 }
Corentin Wallezfd456442016-12-21 17:57:00 -050083 continue;
84 }
85
Corentin Wallez672f7f32017-06-15 17:42:17 -040086 // This needs to come after the check for client arrays as even unused attributes cannot use
87 // client-side arrays
88 if (!program->isAttribLocationActive(attributeIndex))
89 {
90 continue;
91 }
92
Corentin Wallezfd456442016-12-21 17:57:00 -050093 // If we're drawing zero vertices, we have enough data.
94 if (vertexCount <= 0 || primcount <= 0)
95 {
96 continue;
97 }
98
99 GLint maxVertexElement = 0;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300100 GLuint divisor = binding.getDivisor();
101 if (divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500102 {
103 maxVertexElement = maxVertex;
104 }
105 else
106 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300107 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500108 }
109
110 // We do manual overflow checks here instead of using safe_math.h because it was
111 // a bottleneck. Thanks to some properties of GL we know inequalities that can
112 // help us make the overflow checks faster.
113
114 // The max possible attribSize is 16 for a vector of 4 32 bit values.
115 constexpr uint64_t kMaxAttribSize = 16;
116 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
117 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
118
119 // We know attribStride is given as a GLsizei which is typedefed to int.
120 // We also know an upper bound for attribSize.
121 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800122 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500123 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
124 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
125
126 // Computing the max offset using uint64_t without attrib.offset is overflow
127 // safe. Note: Last vertex element does not take the full stride!
128 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
129 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
130
131 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800132 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
133 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500134 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700135 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500136 return false;
137 }
138 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
139
140 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
141 // We can return INVALID_OPERATION if our vertex attribute does not have
142 // enough backing data.
143 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
144 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700145 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500146 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400147 }
148 }
149
150 return true;
151}
152
Geoff Lang280ba992017-04-18 16:30:58 -0400153bool ValidReadPixelsTypeEnum(ValidationContext *context, GLenum type)
154{
155 switch (type)
156 {
157 // Types referenced in Table 3.4 of the ES 2.0.25 spec
158 case GL_UNSIGNED_BYTE:
159 case GL_UNSIGNED_SHORT_4_4_4_4:
160 case GL_UNSIGNED_SHORT_5_5_5_1:
161 case GL_UNSIGNED_SHORT_5_6_5:
162 return context->getClientVersion() >= ES_2_0;
163
164 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
165 case GL_BYTE:
166 case GL_INT:
167 case GL_SHORT:
168 case GL_UNSIGNED_INT:
169 case GL_UNSIGNED_INT_10F_11F_11F_REV:
170 case GL_UNSIGNED_INT_24_8:
171 case GL_UNSIGNED_INT_2_10_10_10_REV:
172 case GL_UNSIGNED_INT_5_9_9_9_REV:
173 case GL_UNSIGNED_SHORT:
174 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
175 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
176 return context->getClientVersion() >= ES_3_0;
177
178 case GL_FLOAT:
179 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat;
180
181 case GL_HALF_FLOAT:
182 return context->getClientVersion() >= ES_3_0 ||
183 context->getExtensions().textureHalfFloat;
184
185 case GL_HALF_FLOAT_OES:
186 return context->getExtensions().colorBufferHalfFloat;
187
188 default:
189 return false;
190 }
191}
192
193bool ValidReadPixelsFormatEnum(ValidationContext *context, GLenum format)
194{
195 switch (format)
196 {
197 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
198 case GL_RGBA:
199 case GL_RGB:
200 case GL_ALPHA:
201 return context->getClientVersion() >= ES_2_0;
202
203 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
204 case GL_RG:
205 case GL_RED:
206 case GL_RGBA_INTEGER:
207 case GL_RGB_INTEGER:
208 case GL_RG_INTEGER:
209 case GL_RED_INTEGER:
210 return context->getClientVersion() >= ES_3_0;
211
212 case GL_SRGB_ALPHA_EXT:
213 case GL_SRGB_EXT:
214 return context->getExtensions().sRGB;
215
216 case GL_BGRA_EXT:
217 return context->getExtensions().readFormatBGRA;
218
219 default:
220 return false;
221 }
222}
223
Geoff Langf607c602016-09-21 11:46:48 -0400224bool ValidReadPixelsFormatType(ValidationContext *context,
225 GLenum framebufferComponentType,
226 GLenum format,
227 GLenum type)
228{
229 switch (framebufferComponentType)
230 {
231 case GL_UNSIGNED_NORMALIZED:
232 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
233 // ReadPixels with BGRA even if the extension is not present
234 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
235 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
236 type == GL_UNSIGNED_BYTE);
237
238 case GL_SIGNED_NORMALIZED:
239 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
240
241 case GL_INT:
242 return (format == GL_RGBA_INTEGER && type == GL_INT);
243
244 case GL_UNSIGNED_INT:
245 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
246
247 case GL_FLOAT:
248 return (format == GL_RGBA && type == GL_FLOAT);
249
250 default:
251 UNREACHABLE();
252 return false;
253 }
254}
255
Geoff Langc1984ed2016-10-07 12:41:00 -0400256template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400257bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400258{
259 switch (ConvertToGLenum(params[0]))
260 {
261 case GL_CLAMP_TO_EDGE:
262 break;
263
264 case GL_REPEAT:
265 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400266 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400267 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400268 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700269 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400270 return false;
271 }
272 break;
273
274 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700275 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400276 return false;
277 }
278
279 return true;
280}
281
282template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400283bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400284{
285 switch (ConvertToGLenum(params[0]))
286 {
287 case GL_NEAREST:
288 case GL_LINEAR:
289 break;
290
291 case GL_NEAREST_MIPMAP_NEAREST:
292 case GL_LINEAR_MIPMAP_NEAREST:
293 case GL_NEAREST_MIPMAP_LINEAR:
294 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400295 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400296 {
297 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700298 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400299 return false;
300 }
301 break;
302
303 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700304 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400305 return false;
306 }
307
308 return true;
309}
310
311template <typename ParamType>
312bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
313{
314 switch (ConvertToGLenum(params[0]))
315 {
316 case GL_NEAREST:
317 case GL_LINEAR:
318 break;
319
320 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700321 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400322 return false;
323 }
324
325 return true;
326}
327
328template <typename ParamType>
329bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
330{
331 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
332 switch (ConvertToGLenum(params[0]))
333 {
334 case GL_NONE:
335 case GL_COMPARE_REF_TO_TEXTURE:
336 break;
337
338 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700339 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400340 return false;
341 }
342
343 return true;
344}
345
346template <typename ParamType>
347bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
348{
349 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
350 switch (ConvertToGLenum(params[0]))
351 {
352 case GL_LEQUAL:
353 case GL_GEQUAL:
354 case GL_LESS:
355 case GL_GREATER:
356 case GL_EQUAL:
357 case GL_NOTEQUAL:
358 case GL_ALWAYS:
359 case GL_NEVER:
360 break;
361
362 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700363 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400364 return false;
365 }
366
367 return true;
368}
369
370template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700371bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
372{
373 if (!context->getExtensions().textureSRGBDecode)
374 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700375 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700376 return false;
377 }
378
379 switch (ConvertToGLenum(params[0]))
380 {
381 case GL_DECODE_EXT:
382 case GL_SKIP_DECODE_EXT:
383 break;
384
385 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700386 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700387 return false;
388 }
389
390 return true;
391}
392
393template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400394bool ValidateSamplerParameterBase(Context *context,
395 GLuint sampler,
396 GLenum pname,
397 GLsizei bufSize,
398 ParamType *params)
399{
400 if (context->getClientMajorVersion() < 3)
401 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700402 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc1984ed2016-10-07 12:41:00 -0400403 return false;
404 }
405
406 if (!context->isSampler(sampler))
407 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700408 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
Geoff Langc1984ed2016-10-07 12:41:00 -0400409 return false;
410 }
411
412 const GLsizei minBufSize = 1;
413 if (bufSize >= 0 && bufSize < minBufSize)
414 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700415 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langc1984ed2016-10-07 12:41:00 -0400416 return false;
417 }
418
419 switch (pname)
420 {
421 case GL_TEXTURE_WRAP_S:
422 case GL_TEXTURE_WRAP_T:
423 case GL_TEXTURE_WRAP_R:
424 if (!ValidateTextureWrapModeValue(context, params, false))
425 {
426 return false;
427 }
428 break;
429
430 case GL_TEXTURE_MIN_FILTER:
431 if (!ValidateTextureMinFilterValue(context, params, false))
432 {
433 return false;
434 }
435 break;
436
437 case GL_TEXTURE_MAG_FILTER:
438 if (!ValidateTextureMagFilterValue(context, params))
439 {
440 return false;
441 }
442 break;
443
444 case GL_TEXTURE_MIN_LOD:
445 case GL_TEXTURE_MAX_LOD:
446 // any value is permissible
447 break;
448
449 case GL_TEXTURE_COMPARE_MODE:
450 if (!ValidateTextureCompareModeValue(context, params))
451 {
452 return false;
453 }
454 break;
455
456 case GL_TEXTURE_COMPARE_FUNC:
457 if (!ValidateTextureCompareFuncValue(context, params))
458 {
459 return false;
460 }
461 break;
462
Geoff Lang81c6b572016-10-19 14:07:52 -0700463 case GL_TEXTURE_SRGB_DECODE_EXT:
464 if (!ValidateTextureSRGBDecodeValue(context, params))
465 {
466 return false;
467 }
468 break;
469
Geoff Langc1984ed2016-10-07 12:41:00 -0400470 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700471 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langc1984ed2016-10-07 12:41:00 -0400472 return false;
473 }
474
475 return true;
476}
477
478bool ValidateGetSamplerParameterBase(Context *context,
479 GLuint sampler,
480 GLenum pname,
481 GLsizei *length)
482{
483 if (length)
484 {
485 *length = 0;
486 }
487
488 if (context->getClientMajorVersion() < 3)
489 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700490 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc1984ed2016-10-07 12:41:00 -0400491 return false;
492 }
493
494 if (!context->isSampler(sampler))
495 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700496 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
Geoff Langc1984ed2016-10-07 12:41:00 -0400497 return false;
498 }
499
500 switch (pname)
501 {
502 case GL_TEXTURE_WRAP_S:
503 case GL_TEXTURE_WRAP_T:
504 case GL_TEXTURE_WRAP_R:
505 case GL_TEXTURE_MIN_FILTER:
506 case GL_TEXTURE_MAG_FILTER:
507 case GL_TEXTURE_MIN_LOD:
508 case GL_TEXTURE_MAX_LOD:
509 case GL_TEXTURE_COMPARE_MODE:
510 case GL_TEXTURE_COMPARE_FUNC:
511 break;
512
Geoff Lang81c6b572016-10-19 14:07:52 -0700513 case GL_TEXTURE_SRGB_DECODE_EXT:
514 if (!context->getExtensions().textureSRGBDecode)
515 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500516 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Geoff Lang81c6b572016-10-19 14:07:52 -0700517 return false;
518 }
519 break;
520
Geoff Langc1984ed2016-10-07 12:41:00 -0400521 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700522 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langc1984ed2016-10-07 12:41:00 -0400523 return false;
524 }
525
526 if (length)
527 {
528 *length = 1;
529 }
530 return true;
531}
532
Geoff Lang6899b872016-10-14 11:30:13 -0400533bool ValidateGetActiveUniformBlockivBase(Context *context,
534 GLuint program,
535 GLuint uniformBlockIndex,
536 GLenum pname,
537 GLsizei *length)
538{
539 if (length)
540 {
541 *length = 0;
542 }
543
544 if (context->getClientMajorVersion() < 3)
545 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500546 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Lang6899b872016-10-14 11:30:13 -0400547 return false;
548 }
549
550 Program *programObject = GetValidProgram(context, program);
551 if (!programObject)
552 {
553 return false;
554 }
555
556 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
557 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500558 context->handleError(InvalidValue()
559 << "uniformBlockIndex exceeds active uniform block count.");
Geoff Lang6899b872016-10-14 11:30:13 -0400560 return false;
561 }
562
563 switch (pname)
564 {
565 case GL_UNIFORM_BLOCK_BINDING:
566 case GL_UNIFORM_BLOCK_DATA_SIZE:
567 case GL_UNIFORM_BLOCK_NAME_LENGTH:
568 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
569 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
570 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
571 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
572 break;
573
574 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700575 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang6899b872016-10-14 11:30:13 -0400576 return false;
577 }
578
579 if (length)
580 {
581 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
582 {
583 const UniformBlock &uniformBlock =
584 programObject->getUniformBlockByIndex(uniformBlockIndex);
jchen10eaef1e52017-06-13 10:44:11 +0800585 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
Geoff Lang6899b872016-10-14 11:30:13 -0400586 }
587 else
588 {
589 *length = 1;
590 }
591 }
592
593 return true;
594}
595
Geoff Lang0a9661f2016-10-20 10:59:20 -0700596bool ValidateGetInternalFormativBase(Context *context,
597 GLenum target,
598 GLenum internalformat,
599 GLenum pname,
600 GLsizei bufSize,
601 GLsizei *numParams)
602{
603 if (numParams)
604 {
605 *numParams = 0;
606 }
607
608 if (context->getClientMajorVersion() < 3)
609 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500610 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700611 return false;
612 }
613
614 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
615 if (!formatCaps.renderable)
616 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500617 context->handleError(InvalidEnum() << "Internal format is not renderable.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700618 return false;
619 }
620
621 switch (target)
622 {
623 case GL_RENDERBUFFER:
624 break;
625
JiangYizhoubddc46b2016-12-09 09:50:51 +0800626 case GL_TEXTURE_2D_MULTISAMPLE:
627 if (context->getClientVersion() < ES_3_1)
628 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500629 context->handleError(InvalidOperation()
630 << "Texture target requires at least OpenGL ES 3.1.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800631 return false;
632 }
633 break;
634
Geoff Lang0a9661f2016-10-20 10:59:20 -0700635 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700636 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
Geoff Lang0a9661f2016-10-20 10:59:20 -0700637 return false;
638 }
639
640 if (bufSize < 0)
641 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700642 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
Geoff Lang0a9661f2016-10-20 10:59:20 -0700643 return false;
644 }
645
646 GLsizei maxWriteParams = 0;
647 switch (pname)
648 {
649 case GL_NUM_SAMPLE_COUNTS:
650 maxWriteParams = 1;
651 break;
652
653 case GL_SAMPLES:
654 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
655 break;
656
657 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700658 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang0a9661f2016-10-20 10:59:20 -0700659 return false;
660 }
661
662 if (numParams)
663 {
664 // glGetInternalFormativ will not overflow bufSize
665 *numParams = std::min(bufSize, maxWriteParams);
666 }
667
668 return true;
669}
670
Jamie Madillc1d770e2017-04-13 17:31:24 -0400671bool ValidateUniformCommonBase(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500672 gl::Program *program,
673 GLint location,
674 GLsizei count,
675 const LinkedUniform **uniformOut)
676{
677 // TODO(Jiajia): Add image uniform check in future.
678 if (count < 0)
679 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700680 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500681 return false;
682 }
683
Brandon Jones6cad5662017-06-14 13:25:13 -0700684 if (!program)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500685 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700686 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
687 return false;
688 }
689
690 if (!program->isLinked())
691 {
692 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500693 return false;
694 }
695
696 if (location == -1)
697 {
698 // Silently ignore the uniform command
699 return false;
700 }
701
702 const auto &uniformLocations = program->getUniformLocations();
Jamie Madillbe849e42017-05-02 15:49:00 -0400703 size_t castedLocation = static_cast<size_t>(location);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500704 if (castedLocation >= uniformLocations.size())
705 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500706 context->handleError(InvalidOperation() << "Invalid uniform location");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500707 return false;
708 }
709
710 const auto &uniformLocation = uniformLocations[castedLocation];
711 if (uniformLocation.ignored)
712 {
713 // Silently ignore the uniform command
714 return false;
715 }
716
717 if (!uniformLocation.used)
718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500719 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500720 return false;
721 }
722
723 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
724
725 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
726 if (!uniform.isArray() && count > 1)
727 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500728 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500729 return false;
730 }
731
732 *uniformOut = &uniform;
733 return true;
734}
735
Frank Henigman999b0fd2017-02-02 21:45:55 -0500736bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -0500737 GLenum uniformType,
738 GLsizei count,
739 const GLint *value)
740{
741 // Value type is GL_INT, because we only get here from glUniform1i{v}.
742 // It is compatible with INT or BOOL.
743 // Do these cheap tests first, for a little extra speed.
744 if (GL_INT == uniformType || GL_BOOL == uniformType)
745 {
746 return true;
747 }
748
749 if (IsSamplerType(uniformType))
750 {
Frank Henigman999b0fd2017-02-02 21:45:55 -0500751 // Check that the values are in range.
752 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
753 for (GLsizei i = 0; i < count; ++i)
754 {
755 if (value[i] < 0 || value[i] >= max)
756 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500757 context->handleError(InvalidValue() << "sampler uniform value out of range");
Frank Henigman999b0fd2017-02-02 21:45:55 -0500758 return false;
759 }
760 }
Frank Henigmana98a6472017-02-02 21:38:32 -0500761 return true;
762 }
763
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500764 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmana98a6472017-02-02 21:38:32 -0500765 return false;
766}
767
Jamie Madillc1d770e2017-04-13 17:31:24 -0400768bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500769{
770 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -0500771 // Do the cheaper test first, for a little extra speed.
772 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500773 {
774 return true;
775 }
776
Brandon Jonesafa75152017-07-21 13:11:29 -0700777 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500778 return false;
779}
780
Jamie Madillc1d770e2017-04-13 17:31:24 -0400781bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500782{
783 // Check that the value type is compatible with uniform type.
784 if (valueType == uniformType)
785 {
786 return true;
787 }
788
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500789 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500790 return false;
791}
792
Geoff Lange0cff192017-05-30 13:04:56 -0400793bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
794{
795 const Program *program = context->getGLState().getProgram();
796 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
797
798 const auto &programOutputTypes = program->getOutputVariableTypes();
799 for (size_t drawBufferIdx = 0; drawBufferIdx < programOutputTypes.size(); drawBufferIdx++)
800 {
801 GLenum outputType = programOutputTypes[drawBufferIdx];
802 GLenum inputType = framebuffer->getDrawbufferWriteType(drawBufferIdx);
803 if (outputType != GL_NONE && inputType != GL_NONE && inputType != outputType)
804 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500805 context->handleError(InvalidOperation() << "Fragment shader output type does not "
806 "match the bound framebuffer attachment "
807 "type.");
Geoff Lange0cff192017-05-30 13:04:56 -0400808 return false;
809 }
810 }
811
812 return true;
813}
814
Geoff Lang9ab5b822017-05-30 16:19:23 -0400815bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
816{
817 const Program *program = context->getGLState().getProgram();
818 const VertexArray *vao = context->getGLState().getVertexArray();
819
820 for (const auto &shaderAttribute : program->getAttributes())
821 {
Geoff Lang69df2422017-07-05 12:42:31 -0400822 // gl_VertexID and gl_InstanceID are active attributes but don't have a bound attribute.
823 if (shaderAttribute.isBuiltIn())
824 {
825 continue;
826 }
827
Geoff Lang9ab5b822017-05-30 16:19:23 -0400828 GLenum shaderInputType = VariableComponentType(shaderAttribute.type);
829
830 const auto &attrib = vao->getVertexAttribute(shaderAttribute.location);
831 const auto &currentValue =
832 context->getGLState().getVertexAttribCurrentValue(shaderAttribute.location);
833 GLenum vertexType = attrib.enabled ? GetVertexAttributeBaseType(attrib) : currentValue.Type;
834
835 if (shaderInputType != GL_NONE && vertexType != GL_NONE && shaderInputType != vertexType)
836 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500837 context->handleError(InvalidOperation() << "Vertex shader input type does not "
838 "match the type of the bound vertex "
839 "attribute.");
Geoff Lang9ab5b822017-05-30 16:19:23 -0400840 return false;
841 }
842 }
843
844 return true;
845}
846
Geoff Langf41a7152016-09-19 15:11:17 -0400847} // anonymous namespace
848
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500849bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400850{
Jamie Madilld7460c72014-01-21 16:38:14 -0500851 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400852 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800853 case GL_TEXTURE_2D:
854 case GL_TEXTURE_CUBE_MAP:
855 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400856
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400857 case GL_TEXTURE_RECTANGLE_ANGLE:
858 return context->getExtensions().textureRectangle;
859
He Yunchaoced53ae2016-11-29 15:00:51 +0800860 case GL_TEXTURE_3D:
861 case GL_TEXTURE_2D_ARRAY:
862 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500863
He Yunchaoced53ae2016-11-29 15:00:51 +0800864 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800865 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400866
He Yunchaoced53ae2016-11-29 15:00:51 +0800867 default:
868 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500869 }
Jamie Madill35d15012013-10-07 10:46:37 -0400870}
871
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500872bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
873{
874 switch (target)
875 {
876 case GL_TEXTURE_2D:
877 case GL_TEXTURE_CUBE_MAP:
878 return true;
879
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400880 case GL_TEXTURE_RECTANGLE_ANGLE:
881 return context->getExtensions().textureRectangle;
882
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500883 default:
884 return false;
885 }
886}
887
888bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
889{
890 switch (target)
891 {
892 case GL_TEXTURE_3D:
893 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300894 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500895
896 default:
897 return false;
898 }
899}
900
Ian Ewellbda75592016-04-18 17:25:54 -0400901// Most texture GL calls are not compatible with external textures, so we have a separate validation
902// function for use in the GL calls that do
903bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
904{
905 return (target == GL_TEXTURE_EXTERNAL_OES) &&
906 (context->getExtensions().eglImageExternal ||
907 context->getExtensions().eglStreamConsumerExternal);
908}
909
Shannon Woods4dfed832014-03-17 20:03:39 -0400910// This function differs from ValidTextureTarget in that the target must be
911// usable as the destination of a 2D operation-- so a cube face is valid, but
912// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400913// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500914bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400915{
916 switch (target)
917 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800918 case GL_TEXTURE_2D:
919 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
920 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
921 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
922 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
923 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
924 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
925 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400926 case GL_TEXTURE_RECTANGLE_ANGLE:
927 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800928 default:
929 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500930 }
931}
932
Jamie Madillbe849e42017-05-02 15:49:00 -0400933bool ValidateDrawElementsInstancedBase(ValidationContext *context,
934 GLenum mode,
935 GLsizei count,
936 GLenum type,
937 const GLvoid *indices,
938 GLsizei primcount)
939{
940 if (primcount < 0)
941 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700942 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400943 return false;
944 }
945
946 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
947 {
948 return false;
949 }
950
951 // No-op zero primitive count
952 return (primcount > 0);
953}
954
955bool ValidateDrawArraysInstancedBase(Context *context,
956 GLenum mode,
957 GLint first,
958 GLsizei count,
959 GLsizei primcount)
960{
961 if (primcount < 0)
962 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700963 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400964 return false;
965 }
966
967 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
968 {
969 return false;
970 }
971
972 // No-op if zero primitive count
973 return (primcount > 0);
974}
975
Corentin Wallez0dc97812017-06-22 14:38:44 -0400976bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400977{
978 // Verify there is at least one active attribute with a divisor of zero
979 const State &state = context->getGLState();
980
981 Program *program = state.getProgram();
982
983 const auto &attribs = state.getVertexArray()->getVertexAttributes();
984 const auto &bindings = state.getVertexArray()->getVertexBindings();
985 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
986 {
987 const VertexAttribute &attrib = attribs[attributeIndex];
988 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300989 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400990 {
991 return true;
992 }
993 }
994
Brandon Jonesafa75152017-07-21 13:11:29 -0700995 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400996 return false;
997}
998
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500999bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1000{
1001 switch (target)
1002 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001003 case GL_TEXTURE_3D:
1004 case GL_TEXTURE_2D_ARRAY:
1005 return true;
1006 default:
1007 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001008 }
1009}
1010
He Yunchao11b038b2016-11-22 21:24:04 +08001011bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
1012{
1013 switch (target)
1014 {
1015 case GL_TEXTURE_2D:
1016 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1017 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1018 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1019 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1020 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1021 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1022 case GL_TEXTURE_3D:
1023 case GL_TEXTURE_2D_ARRAY:
1024 case GL_TEXTURE_2D_MULTISAMPLE:
1025 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001026 case GL_TEXTURE_RECTANGLE_ANGLE:
1027 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +08001028 default:
1029 return false;
1030 }
1031}
1032
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001033bool ValidFramebufferTarget(GLenum target)
1034{
He Yunchaoced53ae2016-11-29 15:00:51 +08001035 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1036 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001037 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001038
1039 switch (target)
1040 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001041 case GL_FRAMEBUFFER:
1042 return true;
1043 case GL_READ_FRAMEBUFFER:
1044 return true;
1045 case GL_DRAW_FRAMEBUFFER:
1046 return true;
1047 default:
1048 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001049 }
1050}
1051
Jamie Madill29639852016-09-02 15:00:09 -04001052bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001053{
1054 switch (target)
1055 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001056 case GL_ARRAY_BUFFER:
1057 case GL_ELEMENT_ARRAY_BUFFER:
1058 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001059
He Yunchaoced53ae2016-11-29 15:00:51 +08001060 case GL_PIXEL_PACK_BUFFER:
1061 case GL_PIXEL_UNPACK_BUFFER:
1062 return (context->getExtensions().pixelBufferObject ||
1063 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001064
He Yunchaoced53ae2016-11-29 15:00:51 +08001065 case GL_COPY_READ_BUFFER:
1066 case GL_COPY_WRITE_BUFFER:
1067 case GL_TRANSFORM_FEEDBACK_BUFFER:
1068 case GL_UNIFORM_BUFFER:
1069 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001070
He Yunchaoced53ae2016-11-29 15:00:51 +08001071 case GL_ATOMIC_COUNTER_BUFFER:
1072 case GL_SHADER_STORAGE_BUFFER:
1073 case GL_DRAW_INDIRECT_BUFFER:
1074 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001075 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001076
He Yunchaoced53ae2016-11-29 15:00:51 +08001077 default:
1078 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001079 }
1080}
1081
Jamie Madillc29968b2016-01-20 11:17:23 -05001082bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001083{
Jamie Madillc29968b2016-01-20 11:17:23 -05001084 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001085 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001086 switch (target)
1087 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001088 case GL_TEXTURE_2D:
1089 maxDimension = caps.max2DTextureSize;
1090 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001091 case GL_TEXTURE_CUBE_MAP:
1092 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1093 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1094 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1095 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1096 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1097 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1098 maxDimension = caps.maxCubeMapTextureSize;
1099 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001100 case GL_TEXTURE_RECTANGLE_ANGLE:
1101 return level == 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08001102 case GL_TEXTURE_3D:
1103 maxDimension = caps.max3DTextureSize;
1104 break;
1105 case GL_TEXTURE_2D_ARRAY:
1106 maxDimension = caps.max2DTextureSize;
1107 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001108 case GL_TEXTURE_2D_MULTISAMPLE:
1109 maxDimension = caps.max2DTextureSize;
1110 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001111 default:
1112 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001113 }
1114
Brandon Jones6cad5662017-06-14 13:25:13 -07001115 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -04001116}
1117
Brandon Jones6cad5662017-06-14 13:25:13 -07001118bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001119 GLenum target,
1120 GLint level,
1121 GLsizei width,
1122 GLsizei height,
1123 GLsizei depth,
1124 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001125{
Brandon Jones6cad5662017-06-14 13:25:13 -07001126 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -04001127 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001128 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -04001129 return false;
1130 }
Austin Kinross08528e12015-10-07 16:24:40 -07001131 // TexSubImage parameters can be NPOT without textureNPOT extension,
1132 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001133 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001134 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001135 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001136 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001137 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001138 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -04001139 return false;
1140 }
1141
1142 if (!ValidMipLevel(context, target, level))
1143 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001144 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -04001145 return false;
1146 }
1147
1148 return true;
1149}
1150
Geoff Lang0d8b7242015-09-09 14:56:53 -04001151bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1152{
1153 // List of compressed format that require that the texture size is smaller than or a multiple of
1154 // the compressed block size.
1155 switch (internalFormat)
1156 {
1157 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1158 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1159 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1160 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langfff7a7d2017-06-02 10:39:17 -04001161 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
1162 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
1163 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
1164 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
Minmin Gonge3939b92015-12-01 15:36:51 -08001165 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001166 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1167 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1168 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1169 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1170 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
1171 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001172 return true;
1173
1174 default:
1175 return false;
1176 }
1177}
1178
Geoff Lang966c9402017-04-18 12:38:27 -04001179bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
1180{
1181 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
1182 (size % blockSize == 0);
1183}
1184
Jamie Madillc29968b2016-01-20 11:17:23 -05001185bool ValidCompressedImageSize(const ValidationContext *context,
1186 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -04001187 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -05001188 GLsizei width,
1189 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001190{
Geoff Langca271392017-04-05 12:30:00 -04001191 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -04001192 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001193 {
1194 return false;
1195 }
1196
Geoff Lang966c9402017-04-18 12:38:27 -04001197 if (width < 0 || height < 0)
1198 {
1199 return false;
1200 }
1201
1202 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1203 {
1204 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
1205 // block size for level 0 but WebGL disallows this.
1206 bool smallerThanBlockSizeAllowed =
1207 level > 0 || !context->getExtensions().webglCompatibility;
1208
1209 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
1210 smallerThanBlockSizeAllowed) ||
1211 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
1212 smallerThanBlockSizeAllowed))
1213 {
1214 return false;
1215 }
1216 }
1217
1218 return true;
1219}
1220
1221bool ValidCompressedSubImageSize(const ValidationContext *context,
1222 GLenum internalFormat,
1223 GLint xoffset,
1224 GLint yoffset,
1225 GLsizei width,
1226 GLsizei height,
1227 size_t textureWidth,
1228 size_t textureHeight)
1229{
1230 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
1231 if (!formatInfo.compressed)
1232 {
1233 return false;
1234 }
1235
Geoff Lang44ff5a72017-02-03 15:15:43 -05001236 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001237 {
1238 return false;
1239 }
1240
Geoff Lang0d8b7242015-09-09 14:56:53 -04001241 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1242 {
Geoff Lang44ff5a72017-02-03 15:15:43 -05001243 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -04001244 yoffset % formatInfo.compressedBlockHeight != 0)
1245 {
1246 return false;
1247 }
1248
1249 // Allowed to either have data that is a multiple of block size or is smaller than the block
1250 // size but fills the entire mip
1251 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
1252 static_cast<size_t>(width) == textureWidth &&
1253 static_cast<size_t>(height) == textureHeight;
1254 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
1255 (height % formatInfo.compressedBlockHeight) == 0;
1256 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -04001257 {
1258 return false;
1259 }
1260 }
1261
Geoff Langd4f180b2013-09-24 13:57:44 -04001262 return true;
1263}
1264
Geoff Langff5b2d52016-09-07 11:32:23 -04001265bool ValidImageDataSize(ValidationContext *context,
1266 GLenum textureTarget,
1267 GLsizei width,
1268 GLsizei height,
1269 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -04001270 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -04001271 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001272 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001273 GLsizei imageSize)
1274{
1275 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1276 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1277 {
1278 // Checks are not required
1279 return true;
1280 }
1281
1282 // ...the data would be unpacked from the buffer object such that the memory reads required
1283 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -04001284 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
1285 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -04001286 const gl::Extents size(width, height, depth);
1287 const auto &unpack = context->getGLState().getUnpackState();
1288
1289 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1290 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1291 if (endByteOrErr.isError())
1292 {
1293 context->handleError(endByteOrErr.getError());
1294 return false;
1295 }
1296
1297 GLuint endByte = endByteOrErr.getResult();
1298
1299 if (pixelUnpackBuffer)
1300 {
1301 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1302 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1303 checkedEndByte += checkedOffset;
1304
1305 if (!checkedEndByte.IsValid() ||
1306 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1307 {
1308 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001309 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04001310 return false;
1311 }
1312 }
1313 else
1314 {
1315 ASSERT(imageSize >= 0);
1316 if (pixels == nullptr && imageSize != 0)
1317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001318 context->handleError(InvalidOperation()
1319 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001320 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001321 }
1322
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001323 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001324 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001325 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001326 return false;
1327 }
1328 }
1329
1330 return true;
1331}
1332
Geoff Lang37dde692014-01-31 16:34:54 -05001333bool ValidQueryType(const Context *context, GLenum queryType)
1334{
He Yunchaoced53ae2016-11-29 15:00:51 +08001335 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1336 "GL extension enums not equal.");
1337 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1338 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001339
1340 switch (queryType)
1341 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001342 case GL_ANY_SAMPLES_PASSED:
1343 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1344 return true;
1345 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1346 return (context->getClientMajorVersion() >= 3);
1347 case GL_TIME_ELAPSED_EXT:
1348 return context->getExtensions().disjointTimerQuery;
1349 case GL_COMMANDS_COMPLETED_CHROMIUM:
1350 return context->getExtensions().syncQuery;
1351 default:
1352 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001353 }
1354}
1355
Geoff Lang2d62ab72017-03-23 16:54:40 -04001356bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
1357 GLenum type,
1358 GLboolean normalized,
1359 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001360 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001361 bool pureInteger)
1362{
1363 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001364 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1365 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1366 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1367 // parameter exceeds 255.
1368 constexpr GLsizei kMaxWebGLStride = 255;
1369 if (stride > kMaxWebGLStride)
1370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001371 context->handleError(InvalidValue()
1372 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001373 return false;
1374 }
1375
1376 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1377 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1378 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1379 // or an INVALID_OPERATION error is generated.
1380 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1381 size_t typeSize = GetVertexFormatTypeSize(internalType);
1382
1383 ASSERT(isPow2(typeSize) && typeSize > 0);
1384 size_t sizeMask = (typeSize - 1);
1385 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1386 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001387 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001388 return false;
1389 }
1390
1391 if ((stride & sizeMask) != 0)
1392 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001393 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001394 return false;
1395 }
1396
1397 return true;
1398}
1399
Jamie Madillef300b12016-10-07 15:12:09 -04001400Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001401{
He Yunchaoced53ae2016-11-29 15:00:51 +08001402 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1403 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1404 // or program object and INVALID_OPERATION if the provided name identifies an object
1405 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001406
Dian Xiang769769a2015-09-09 15:20:08 -07001407 Program *validProgram = context->getProgram(id);
1408
1409 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001410 {
Dian Xiang769769a2015-09-09 15:20:08 -07001411 if (context->getShader(id))
1412 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001413 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001414 }
1415 else
1416 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001417 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001418 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001419 }
Dian Xiang769769a2015-09-09 15:20:08 -07001420
1421 return validProgram;
1422}
1423
Jamie Madillef300b12016-10-07 15:12:09 -04001424Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001425{
1426 // See ValidProgram for spec details.
1427
1428 Shader *validShader = context->getShader(id);
1429
1430 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001431 {
Dian Xiang769769a2015-09-09 15:20:08 -07001432 if (context->getProgram(id))
1433 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001434 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001435 }
1436 else
1437 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001438 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001439 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001440 }
Dian Xiang769769a2015-09-09 15:20:08 -07001441
1442 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001443}
1444
Geoff Langb1196682014-07-23 13:47:29 -04001445bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001446{
1447 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1448 {
1449 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1450
Geoff Langaae65a42014-05-26 12:43:44 -04001451 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001452 {
Martin Radevd178aa42017-07-13 14:03:22 +03001453 context->handleError(
1454 InvalidOperation()
1455 << "attachment index cannot be greater or equal to MAX_COLOR_ATTACHMENTS.");
Geoff Langb1196682014-07-23 13:47:29 -04001456 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001457 }
1458 }
1459 else
1460 {
1461 switch (attachment)
1462 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001463 case GL_DEPTH_ATTACHMENT:
1464 case GL_STENCIL_ATTACHMENT:
1465 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001466
He Yunchaoced53ae2016-11-29 15:00:51 +08001467 case GL_DEPTH_STENCIL_ATTACHMENT:
1468 if (!context->getExtensions().webglCompatibility &&
1469 context->getClientMajorVersion() < 3)
1470 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001471 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001472 return false;
1473 }
1474 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001475
He Yunchaoced53ae2016-11-29 15:00:51 +08001476 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001477 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001478 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001479 }
1480 }
1481
1482 return true;
1483}
1484
Jamie Madille8fb6402017-02-14 17:56:40 -05001485bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001486 GLenum target,
1487 GLsizei samples,
1488 GLenum internalformat,
1489 GLsizei width,
1490 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001491{
1492 switch (target)
1493 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001494 case GL_RENDERBUFFER:
1495 break;
1496 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001497 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001498 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001499 }
1500
1501 if (width < 0 || height < 0 || samples < 0)
1502 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001503 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001504 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001505 }
1506
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001507 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1508 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1509
1510 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001511 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001513 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001514 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001515 }
1516
1517 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1518 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
Corentin Walleze0902642014-11-04 12:32:15 -08001519 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001520 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1521 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001522 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001523 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001524 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001525 }
1526
Geoff Langaae65a42014-05-26 12:43:44 -04001527 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001528 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001529 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001530 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001531 }
1532
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001533 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001534 if (handle == 0)
1535 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001536 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001537 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001538 }
1539
1540 return true;
1541}
1542
He Yunchaoced53ae2016-11-29 15:00:51 +08001543bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1544 GLenum target,
1545 GLenum attachment,
1546 GLenum renderbuffertarget,
1547 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001548{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001549 if (!ValidFramebufferTarget(target))
1550 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001551 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001552 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001553 }
1554
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001555 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001556
Jamie Madill84115c92015-04-23 15:00:07 -04001557 ASSERT(framebuffer);
1558 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001559 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001560 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001561 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001562 }
1563
Jamie Madillb4472272014-07-03 10:38:55 -04001564 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001565 {
Jamie Madillb4472272014-07-03 10:38:55 -04001566 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001567 }
1568
Jamie Madillab9d82c2014-01-21 16:38:14 -05001569 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1570 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1571 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1572 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1573 if (renderbuffer != 0)
1574 {
1575 if (!context->getRenderbuffer(renderbuffer))
1576 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001577 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001578 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001579 }
1580 }
1581
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001582 return true;
1583}
1584
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001585bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001586 GLint srcX0,
1587 GLint srcY0,
1588 GLint srcX1,
1589 GLint srcY1,
1590 GLint dstX0,
1591 GLint dstY0,
1592 GLint dstX1,
1593 GLint dstY1,
1594 GLbitfield mask,
1595 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001596{
1597 switch (filter)
1598 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001599 case GL_NEAREST:
1600 break;
1601 case GL_LINEAR:
1602 break;
1603 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001604 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001605 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001606 }
1607
1608 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1609 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001610 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001611 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001612 }
1613
1614 if (mask == 0)
1615 {
1616 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1617 // buffers are copied.
1618 return false;
1619 }
1620
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001621 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1622 // color buffer, leaving only nearest being unfiltered from above
1623 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001625 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001626 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001627 }
1628
Jamie Madill51f40ec2016-06-15 14:06:00 -04001629 const auto &glState = context->getGLState();
1630 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1631 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001632
1633 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001634 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001635 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001636 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001637 }
1638
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001639 if (readFramebuffer->id() == drawFramebuffer->id())
1640 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001641 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001642 return false;
1643 }
1644
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001645 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001647 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001648 return false;
1649 }
1650
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001651 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001652 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001653 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001654 return false;
1655 }
1656
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001657 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001659 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001660 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001661 }
1662
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001663 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1664
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001665 if (mask & GL_COLOR_BUFFER_BIT)
1666 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001667 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001668 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001669
He Yunchao66a41a22016-12-15 16:45:05 +08001670 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001671 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001672 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001673
Geoff Langa15472a2015-08-11 11:48:03 -04001674 for (size_t drawbufferIdx = 0;
1675 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001676 {
Geoff Langa15472a2015-08-11 11:48:03 -04001677 const FramebufferAttachment *attachment =
1678 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1679 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001680 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001681 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001682
Geoff Langb2f3d052013-08-13 12:49:27 -04001683 // The GL ES 3.0.2 spec (pg 193) states that:
1684 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001685 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1686 // as well
1687 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1688 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001689 // Changes with EXT_color_buffer_float:
1690 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001691 GLenum readComponentType = readFormat.info->componentType;
1692 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001693 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001694 readComponentType == GL_SIGNED_NORMALIZED);
1695 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1696 drawComponentType == GL_SIGNED_NORMALIZED);
1697
1698 if (extensions.colorBufferFloat)
1699 {
1700 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1701 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1702
1703 if (readFixedOrFloat != drawFixedOrFloat)
1704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001705 context->handleError(InvalidOperation()
1706 << "If the read buffer contains fixed-point or "
1707 "floating-point values, the draw buffer must "
1708 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001709 return false;
1710 }
1711 }
1712 else if (readFixedPoint != drawFixedPoint)
1713 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001714 context->handleError(InvalidOperation()
1715 << "If the read buffer contains fixed-point values, "
1716 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001717 return false;
1718 }
1719
1720 if (readComponentType == GL_UNSIGNED_INT &&
1721 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001722 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001723 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001724 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001725 }
1726
Jamie Madill6163c752015-12-07 16:32:59 -05001727 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001728 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001729 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001730 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001731 }
1732
Jamie Madilla3944d42016-07-22 22:13:26 -04001733 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001734 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001735 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001736 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001737 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001738 }
Geoff Lange4915782017-04-12 15:19:07 -04001739
1740 if (context->getExtensions().webglCompatibility &&
1741 *readColorBuffer == *attachment)
1742 {
1743 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001744 InvalidOperation()
1745 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001746 return false;
1747 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001748 }
1749 }
1750
Jamie Madilla3944d42016-07-22 22:13:26 -04001751 if ((readFormat.info->componentType == GL_INT ||
1752 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1753 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001754 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001755 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001756 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001757 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001758 }
He Yunchao66a41a22016-12-15 16:45:05 +08001759 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1760 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1761 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1762 // situation is an application error that would lead to a crash in ANGLE.
1763 else if (drawFramebuffer->hasEnabledDrawBuffer())
1764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001765 context->handleError(
1766 InvalidOperation()
1767 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001768 return false;
1769 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001770 }
1771
He Yunchaoced53ae2016-11-29 15:00:51 +08001772 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001773 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1774 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001775 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001776 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001777 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001778 const gl::FramebufferAttachment *readBuffer =
1779 readFramebuffer->getAttachment(attachments[i]);
1780 const gl::FramebufferAttachment *drawBuffer =
1781 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001782
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001783 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001784 {
Kenneth Russell69382852017-07-21 16:38:44 -04001785 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001786 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001787 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001788 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001789 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001790
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001791 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001792 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001793 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001794 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001795 }
Geoff Lange4915782017-04-12 15:19:07 -04001796
1797 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1798 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001799 context->handleError(
1800 InvalidOperation()
1801 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001802 return false;
1803 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001804 }
He Yunchao66a41a22016-12-15 16:45:05 +08001805 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1806 else if (drawBuffer)
1807 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001808 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1809 "depth/stencil attachment of a "
1810 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001811 return false;
1812 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001813 }
1814 }
1815
Martin Radeva3ed4572017-07-27 18:29:37 +03001816 // ANGLE_multiview, Revision 1:
1817 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1818 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1819 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1820 {
1821 context->handleError(InvalidFramebufferOperation()
1822 << "Attempt to read from a multi-view framebuffer.");
1823 return false;
1824 }
1825 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1826 {
1827 context->handleError(InvalidFramebufferOperation()
1828 << "Attempt to write to a multi-view framebuffer.");
1829 return false;
1830 }
1831
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001832 return true;
1833}
1834
Jamie Madill4928b7c2017-06-20 12:57:39 -04001835bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001836 GLint x,
1837 GLint y,
1838 GLsizei width,
1839 GLsizei height,
1840 GLenum format,
1841 GLenum type,
1842 GLsizei bufSize,
1843 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001844 GLsizei *columns,
1845 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001846 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001847{
1848 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001849 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001850 return false;
1851 }
1852
Geoff Lang62fce5b2016-09-30 10:46:35 -04001853 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001854 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001855 {
Geoff Langb1196682014-07-23 13:47:29 -04001856 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001857 }
1858
Geoff Lang62fce5b2016-09-30 10:46:35 -04001859 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001860 {
Geoff Langb1196682014-07-23 13:47:29 -04001861 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001862 }
1863
Jamie Madillc29968b2016-01-20 11:17:23 -05001864 return true;
1865}
1866
1867bool ValidateReadnPixelsEXT(Context *context,
1868 GLint x,
1869 GLint y,
1870 GLsizei width,
1871 GLsizei height,
1872 GLenum format,
1873 GLenum type,
1874 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001875 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001876{
1877 if (bufSize < 0)
1878 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001879 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001880 return false;
1881 }
1882
Geoff Lang62fce5b2016-09-30 10:46:35 -04001883 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001884 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001885}
Jamie Madill26e91952014-03-05 15:01:27 -05001886
Jamie Madill4928b7c2017-06-20 12:57:39 -04001887bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001888 GLint x,
1889 GLint y,
1890 GLsizei width,
1891 GLsizei height,
1892 GLenum format,
1893 GLenum type,
1894 GLsizei bufSize,
1895 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001896 GLsizei *columns,
1897 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001898 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001899{
1900 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001901 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001902 return false;
1903 }
1904
Geoff Lange93daba2017-03-30 13:54:40 -04001905 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1906 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001907 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001908 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001909 }
1910
Geoff Lang62fce5b2016-09-30 10:46:35 -04001911 if (!ValidateRobustBufferSize(context, bufSize, *length))
1912 {
1913 return false;
1914 }
1915
1916 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001917}
1918
Olli Etuaho41997e72016-03-10 13:38:39 +02001919bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001920{
1921 if (!context->getExtensions().occlusionQueryBoolean &&
1922 !context->getExtensions().disjointTimerQuery)
1923 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001924 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001925 return false;
1926 }
1927
Olli Etuaho41997e72016-03-10 13:38:39 +02001928 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001929}
1930
Olli Etuaho41997e72016-03-10 13:38:39 +02001931bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001932{
1933 if (!context->getExtensions().occlusionQueryBoolean &&
1934 !context->getExtensions().disjointTimerQuery)
1935 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001936 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001937 return false;
1938 }
1939
Olli Etuaho41997e72016-03-10 13:38:39 +02001940 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001941}
1942
1943bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001944{
1945 if (!ValidQueryType(context, target))
1946 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001947 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001948 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001949 }
1950
1951 if (id == 0)
1952 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001953 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001954 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001955 }
1956
1957 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1958 // of zero, if the active query object name for <target> is non-zero (for the
1959 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1960 // the active query for either target is non-zero), if <id> is the name of an
1961 // existing query object whose type does not match <target>, or if <id> is the
1962 // active query object name for any query type, the error INVALID_OPERATION is
1963 // generated.
1964
1965 // Ensure no other queries are active
1966 // NOTE: If other queries than occlusion are supported, we will need to check
1967 // separately that:
1968 // a) The query ID passed is not the current active query for any target/type
1969 // b) There are no active queries for the requested target (and in the case
1970 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1971 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001972
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001973 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001974 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001975 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001976 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001977 }
1978
1979 Query *queryObject = context->getQuery(id, true, target);
1980
1981 // check that name was obtained with glGenQueries
1982 if (!queryObject)
1983 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001984 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001985 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001986 }
1987
1988 // check for type mismatch
1989 if (queryObject->getType() != target)
1990 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001991 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001992 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001993 }
1994
1995 return true;
1996}
1997
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001998bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1999{
2000 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002001 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002002 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002003 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002004 return false;
2005 }
2006
2007 return ValidateBeginQueryBase(context, target, id);
2008}
2009
2010bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002011{
2012 if (!ValidQueryType(context, target))
2013 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002014 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04002015 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002016 }
2017
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002018 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002019
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002020 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002021 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002022 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04002023 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002024 }
2025
Jamie Madill45c785d2014-05-13 14:09:34 -04002026 return true;
2027}
2028
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002029bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2030{
2031 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002032 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002033 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002034 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002035 return false;
2036 }
2037
2038 return ValidateEndQueryBase(context, target);
2039}
2040
2041bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2042{
2043 if (!context->getExtensions().disjointTimerQuery)
2044 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002045 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002046 return false;
2047 }
2048
2049 if (target != GL_TIMESTAMP_EXT)
2050 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002051 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002052 return false;
2053 }
2054
2055 Query *queryObject = context->getQuery(id, true, target);
2056 if (queryObject == nullptr)
2057 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002058 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002059 return false;
2060 }
2061
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002062 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002063 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002064 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002065 return false;
2066 }
2067
2068 return true;
2069}
2070
Geoff Lang2186c382016-10-14 10:54:54 -04002071bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002072{
Geoff Lang2186c382016-10-14 10:54:54 -04002073 if (numParams)
2074 {
2075 *numParams = 0;
2076 }
2077
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002078 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2079 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002080 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002081 return false;
2082 }
2083
2084 switch (pname)
2085 {
2086 case GL_CURRENT_QUERY_EXT:
2087 if (target == GL_TIMESTAMP_EXT)
2088 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002089 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002090 return false;
2091 }
2092 break;
2093 case GL_QUERY_COUNTER_BITS_EXT:
2094 if (!context->getExtensions().disjointTimerQuery ||
2095 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2096 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002097 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002098 return false;
2099 }
2100 break;
2101 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002102 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002103 return false;
2104 }
2105
Geoff Lang2186c382016-10-14 10:54:54 -04002106 if (numParams)
2107 {
2108 // All queries return only one value
2109 *numParams = 1;
2110 }
2111
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002112 return true;
2113}
2114
2115bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2116{
2117 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002118 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002119 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002120 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002121 return false;
2122 }
2123
Geoff Lang2186c382016-10-14 10:54:54 -04002124 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002125}
2126
Geoff Lang2186c382016-10-14 10:54:54 -04002127bool ValidateGetQueryivRobustANGLE(Context *context,
2128 GLenum target,
2129 GLenum pname,
2130 GLsizei bufSize,
2131 GLsizei *length,
2132 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002133{
Geoff Lang2186c382016-10-14 10:54:54 -04002134 if (!ValidateRobustEntryPoint(context, bufSize))
2135 {
2136 return false;
2137 }
2138
2139 if (!ValidateGetQueryivBase(context, target, pname, length))
2140 {
2141 return false;
2142 }
2143
2144 if (!ValidateRobustBufferSize(context, bufSize, *length))
2145 {
2146 return false;
2147 }
2148
2149 return true;
2150}
2151
2152bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2153{
2154 if (numParams)
2155 {
2156 *numParams = 0;
2157 }
2158
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002159 Query *queryObject = context->getQuery(id, false, GL_NONE);
2160
2161 if (!queryObject)
2162 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002163 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002164 return false;
2165 }
2166
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002167 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002168 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002169 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002170 return false;
2171 }
2172
2173 switch (pname)
2174 {
2175 case GL_QUERY_RESULT_EXT:
2176 case GL_QUERY_RESULT_AVAILABLE_EXT:
2177 break;
2178
2179 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002180 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002181 return false;
2182 }
2183
Geoff Lang2186c382016-10-14 10:54:54 -04002184 if (numParams)
2185 {
2186 *numParams = 1;
2187 }
2188
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002189 return true;
2190}
2191
2192bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2193{
2194 if (!context->getExtensions().disjointTimerQuery)
2195 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002196 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002197 return false;
2198 }
Geoff Lang2186c382016-10-14 10:54:54 -04002199 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2200}
2201
2202bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2203 GLuint id,
2204 GLenum pname,
2205 GLsizei bufSize,
2206 GLsizei *length,
2207 GLint *params)
2208{
2209 if (!context->getExtensions().disjointTimerQuery)
2210 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002211 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04002212 return false;
2213 }
2214
2215 if (!ValidateRobustEntryPoint(context, bufSize))
2216 {
2217 return false;
2218 }
2219
2220 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2221 {
2222 return false;
2223 }
2224
2225 if (!ValidateRobustBufferSize(context, bufSize, *length))
2226 {
2227 return false;
2228 }
2229
2230 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002231}
2232
2233bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2234{
2235 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002236 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002237 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002238 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002239 return false;
2240 }
Geoff Lang2186c382016-10-14 10:54:54 -04002241 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2242}
2243
2244bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2245 GLuint id,
2246 GLenum pname,
2247 GLsizei bufSize,
2248 GLsizei *length,
2249 GLuint *params)
2250{
2251 if (!context->getExtensions().disjointTimerQuery &&
2252 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2253 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002254 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002255 return false;
2256 }
2257
2258 if (!ValidateRobustEntryPoint(context, bufSize))
2259 {
2260 return false;
2261 }
2262
2263 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2264 {
2265 return false;
2266 }
2267
2268 if (!ValidateRobustBufferSize(context, bufSize, *length))
2269 {
2270 return false;
2271 }
2272
2273 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002274}
2275
2276bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2277{
2278 if (!context->getExtensions().disjointTimerQuery)
2279 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002280 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002281 return false;
2282 }
Geoff Lang2186c382016-10-14 10:54:54 -04002283 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2284}
2285
2286bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2287 GLuint id,
2288 GLenum pname,
2289 GLsizei bufSize,
2290 GLsizei *length,
2291 GLint64 *params)
2292{
2293 if (!context->getExtensions().disjointTimerQuery)
2294 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002295 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002296 return false;
2297 }
2298
2299 if (!ValidateRobustEntryPoint(context, bufSize))
2300 {
2301 return false;
2302 }
2303
2304 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2305 {
2306 return false;
2307 }
2308
2309 if (!ValidateRobustBufferSize(context, bufSize, *length))
2310 {
2311 return false;
2312 }
2313
2314 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002315}
2316
2317bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2318{
2319 if (!context->getExtensions().disjointTimerQuery)
2320 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002321 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002322 return false;
2323 }
Geoff Lang2186c382016-10-14 10:54:54 -04002324 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2325}
2326
2327bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2328 GLuint id,
2329 GLenum pname,
2330 GLsizei bufSize,
2331 GLsizei *length,
2332 GLuint64 *params)
2333{
2334 if (!context->getExtensions().disjointTimerQuery)
2335 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002336 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002337 return false;
2338 }
2339
2340 if (!ValidateRobustEntryPoint(context, bufSize))
2341 {
2342 return false;
2343 }
2344
2345 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2346 {
2347 return false;
2348 }
2349
2350 if (!ValidateRobustBufferSize(context, bufSize, *length))
2351 {
2352 return false;
2353 }
2354
2355 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002356}
2357
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002358bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002359 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002360 GLuint program,
2361 GLint location,
2362 GLsizei count)
2363{
2364 // Check for ES31 program uniform entry points
2365 if (context->getClientVersion() < Version(3, 1))
2366 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002367 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002368 return false;
2369 }
2370
2371 const LinkedUniform *uniform = nullptr;
2372 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002373 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2374 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002375}
2376
Frank Henigmana98a6472017-02-02 21:38:32 -05002377bool ValidateProgramUniform1iv(gl::Context *context,
2378 GLuint program,
2379 GLint location,
2380 GLsizei count,
2381 const GLint *value)
2382{
2383 // Check for ES31 program uniform entry points
2384 if (context->getClientVersion() < Version(3, 1))
2385 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002386 context->handleError(InvalidOperation());
Frank Henigmana98a6472017-02-02 21:38:32 -05002387 return false;
2388 }
2389
2390 const LinkedUniform *uniform = nullptr;
2391 gl::Program *programObject = GetValidProgram(context, program);
2392 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2393 ValidateUniform1ivValue(context, uniform->type, count, value);
2394}
2395
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002396bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002397 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002398 GLuint program,
2399 GLint location,
2400 GLsizei count,
2401 GLboolean transpose)
2402{
2403 // Check for ES31 program uniform entry points
2404 if (context->getClientVersion() < Version(3, 1))
2405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002406 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002407 return false;
2408 }
2409
2410 const LinkedUniform *uniform = nullptr;
2411 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002412 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2413 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002414}
2415
Jamie Madillc1d770e2017-04-13 17:31:24 -04002416bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002417{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002418 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002419 gl::Program *programObject = context->getGLState().getProgram();
2420 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2421 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002422}
2423
Jamie Madillbe849e42017-05-02 15:49:00 -04002424bool ValidateUniform1iv(ValidationContext *context,
2425 GLint location,
2426 GLsizei count,
2427 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002428{
2429 const LinkedUniform *uniform = nullptr;
2430 gl::Program *programObject = context->getGLState().getProgram();
2431 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2432 ValidateUniform1ivValue(context, uniform->type, count, value);
2433}
2434
Jamie Madillc1d770e2017-04-13 17:31:24 -04002435bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002436 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002437 GLint location,
2438 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002439 GLboolean transpose)
2440{
2441 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002442 int rows = VariableRowCount(valueType);
2443 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002444 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002445 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002446 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002447 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002448 }
2449
Martin Radev1be913c2016-07-11 17:59:16 +03002450 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002451 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002452 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002453 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002454 }
2455
Jamie Madill62d31cb2015-09-11 13:25:51 -04002456 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002457 gl::Program *programObject = context->getGLState().getProgram();
2458 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2459 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002460}
2461
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002462bool ValidateStateQuery(ValidationContext *context,
2463 GLenum pname,
2464 GLenum *nativeType,
2465 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002466{
2467 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2468 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002469 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002470 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002471 }
2472
Jamie Madill0af26e12015-03-05 19:54:33 -05002473 const Caps &caps = context->getCaps();
2474
Jamie Madill893ab082014-05-16 16:56:10 -04002475 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2476 {
2477 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2478
Jamie Madill0af26e12015-03-05 19:54:33 -05002479 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002480 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002481 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002482 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002483 }
2484 }
2485
2486 switch (pname)
2487 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002488 case GL_TEXTURE_BINDING_2D:
2489 case GL_TEXTURE_BINDING_CUBE_MAP:
2490 case GL_TEXTURE_BINDING_3D:
2491 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002492 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002493 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002494 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2495 if (!context->getExtensions().textureRectangle)
2496 {
2497 context->handleError(InvalidEnum()
2498 << "ANGLE_texture_rectangle extension not present");
2499 return false;
2500 }
2501 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002502 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2503 if (!context->getExtensions().eglStreamConsumerExternal &&
2504 !context->getExtensions().eglImageExternal)
2505 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002506 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2507 "nor GL_OES_EGL_image_external "
2508 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002509 return false;
2510 }
2511 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002512
He Yunchaoced53ae2016-11-29 15:00:51 +08002513 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2514 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002515 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002516 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2517 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002518 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002519 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002520 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002521 }
2522
Jamie Madill51f40ec2016-06-15 14:06:00 -04002523 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2524 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002525
2526 if (framebuffer->getReadBufferState() == GL_NONE)
2527 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002528 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002529 return false;
2530 }
2531
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002532 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002533 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002534 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002535 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002536 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002537 }
2538 }
2539 break;
2540
He Yunchaoced53ae2016-11-29 15:00:51 +08002541 default:
2542 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002543 }
2544
2545 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002546 if (*numParams == 0)
2547 {
2548 return false;
2549 }
2550
2551 return true;
2552}
2553
2554bool ValidateRobustStateQuery(ValidationContext *context,
2555 GLenum pname,
2556 GLsizei bufSize,
2557 GLenum *nativeType,
2558 unsigned int *numParams)
2559{
2560 if (!ValidateRobustEntryPoint(context, bufSize))
2561 {
2562 return false;
2563 }
2564
2565 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2566 {
2567 return false;
2568 }
2569
2570 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002571 {
2572 return false;
2573 }
2574
2575 return true;
2576}
2577
Jamie Madillc29968b2016-01-20 11:17:23 -05002578bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2579 GLenum target,
2580 GLint level,
2581 GLenum internalformat,
2582 bool isSubImage,
2583 GLint xoffset,
2584 GLint yoffset,
2585 GLint zoffset,
2586 GLint x,
2587 GLint y,
2588 GLsizei width,
2589 GLsizei height,
2590 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002591 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002592{
Brandon Jones6cad5662017-06-14 13:25:13 -07002593 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002594 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002595 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2596 return false;
2597 }
2598
2599 if (width < 0 || height < 0)
2600 {
2601 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002602 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002603 }
2604
He Yunchaoced53ae2016-11-29 15:00:51 +08002605 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2606 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002607 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002608 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002609 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002610 }
2611
2612 if (border != 0)
2613 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002614 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002615 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002616 }
2617
2618 if (!ValidMipLevel(context, target, level))
2619 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002620 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002621 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002622 }
2623
Jamie Madill51f40ec2016-06-15 14:06:00 -04002624 const auto &state = context->getGLState();
2625 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002626 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002627 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002628 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002629 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002630 }
2631
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002632 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002633 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002634 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002635 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002636 }
2637
Martin Radev138064f2016-07-15 12:03:41 +03002638 if (readFramebuffer->getReadBufferState() == GL_NONE)
2639 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002640 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002641 return false;
2642 }
2643
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002644 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2645 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002646 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002647 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002648 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2649 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002650 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002651 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002652 return false;
2653 }
2654
Martin Radev04e2c3b2017-07-27 16:54:35 +03002655 // ANGLE_multiview spec, Revision 1:
2656 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2657 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2658 // is not NONE.
2659 if (source->getMultiviewLayout() != GL_NONE)
2660 {
2661 context->handleError(InvalidFramebufferOperation()
2662 << "The active read framebuffer object has multiview attachments.");
2663 return false;
2664 }
2665
Geoff Langaae65a42014-05-26 12:43:44 -04002666 const gl::Caps &caps = context->getCaps();
2667
Geoff Langaae65a42014-05-26 12:43:44 -04002668 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002669 switch (target)
2670 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002671 case GL_TEXTURE_2D:
2672 maxDimension = caps.max2DTextureSize;
2673 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002674
He Yunchaoced53ae2016-11-29 15:00:51 +08002675 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2676 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2677 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2678 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2679 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2680 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2681 maxDimension = caps.maxCubeMapTextureSize;
2682 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002683
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002684 case GL_TEXTURE_RECTANGLE_ANGLE:
2685 maxDimension = caps.maxRectangleTextureSize;
2686 break;
2687
He Yunchaoced53ae2016-11-29 15:00:51 +08002688 case GL_TEXTURE_2D_ARRAY:
2689 maxDimension = caps.max2DTextureSize;
2690 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002691
He Yunchaoced53ae2016-11-29 15:00:51 +08002692 case GL_TEXTURE_3D:
2693 maxDimension = caps.max3DTextureSize;
2694 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002695
He Yunchaoced53ae2016-11-29 15:00:51 +08002696 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002697 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002698 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002699 }
2700
Jamie Madillc29968b2016-01-20 11:17:23 -05002701 gl::Texture *texture =
2702 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002703 if (!texture)
2704 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002705 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002706 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002707 }
2708
Geoff Lang69cce582015-09-17 13:20:36 -04002709 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002710 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002711 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002712 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002713 }
2714
Geoff Langca271392017-04-05 12:30:00 -04002715 const gl::InternalFormat &formatInfo =
2716 gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002717
Geoff Lang966c9402017-04-18 12:38:27 -04002718 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002719 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002720 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002721 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002722 }
2723
2724 if (isSubImage)
2725 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002726 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2727 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2728 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002729 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002730 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002731 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002732 }
2733 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002734 else
2735 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002736 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002737 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002738 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002739 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002740 }
2741
Geoff Langeb66a6e2016-10-31 13:06:12 -04002742 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002743 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002744 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002745 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002746 }
2747
2748 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002749 if (static_cast<int>(width) > maxLevelDimension ||
2750 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002751 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002752 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002753 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002754 }
2755 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002756
Jamie Madill0c8abca2016-07-22 20:21:26 -04002757 if (textureFormatOut)
2758 {
2759 *textureFormatOut = texture->getFormat(target, level);
2760 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002761
2762 // Detect texture copying feedback loops for WebGL.
2763 if (context->getExtensions().webglCompatibility)
2764 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002765 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002766 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002767 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002768 return false;
2769 }
2770 }
2771
Jamie Madill560a8d82014-05-21 13:06:20 -04002772 return true;
2773}
2774
Jiajia Qind9671222016-11-29 16:30:31 +08002775bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002776{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002777 switch (mode)
2778 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002779 case GL_POINTS:
2780 case GL_LINES:
2781 case GL_LINE_LOOP:
2782 case GL_LINE_STRIP:
2783 case GL_TRIANGLES:
2784 case GL_TRIANGLE_STRIP:
2785 case GL_TRIANGLE_FAN:
2786 break;
2787 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002788 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002789 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002790 }
2791
Jamie Madill250d33f2014-06-06 17:09:03 -04002792 if (count < 0)
2793 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002794 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002795 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002796 }
2797
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002798 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002799
Jamie Madill250d33f2014-06-06 17:09:03 -04002800 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002801 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002802 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002803 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002804 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002805 }
2806
Jamie Madillcbcde722017-01-06 14:50:00 -05002807 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2808 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002809 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002810 const Extensions &extensions = context->getExtensions();
2811 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002812 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002813 const FramebufferAttachment *dsAttachment =
2814 framebuffer->getStencilOrDepthStencilAttachment();
2815 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002816 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002817 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002818
2819 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2820 bool differentWritemasks =
2821 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2822 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2823 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2824 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2825
2826 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002827 {
Martin Radevffe754b2017-07-31 10:38:07 +03002828 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002829 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002830 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2831 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002832 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002833 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002834 return false;
2835 }
Jamie Madillac528012014-06-20 13:21:23 -04002836 }
2837
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002838 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002839 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002840 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002841 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002842 }
2843
Geoff Lang7dd2e102014-11-10 15:19:26 -05002844 gl::Program *program = state.getProgram();
2845 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002846 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002847 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002848 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002849 }
2850
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002851 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002852 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002853 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002854 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002855 }
2856
Martin Radevffe754b2017-07-31 10:38:07 +03002857 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002858 {
Martin Radev7e69f762017-07-27 14:54:13 +03002859 const int programNumViews = program->getNumViews();
2860 const int framebufferNumViews = framebuffer->getNumViews();
2861 if (programNumViews != -1 && framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002862 {
2863 context->handleError(InvalidOperation() << "The number of views in the active program "
2864 "and draw framebuffer does not match.");
2865 return false;
2866 }
Martin Radev7e69f762017-07-27 14:54:13 +03002867
2868 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2869 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2870 framebufferNumViews > 1)
2871 {
2872 context->handleError(InvalidOperation()
2873 << "There is an active transform feedback object "
2874 "when the number of views in the active draw "
2875 "framebuffer is greater than 1.");
2876 return false;
2877 }
Martin Radevffe754b2017-07-31 10:38:07 +03002878
2879 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2880 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2881 {
2882 context->handleError(InvalidOperation() << "There is an active query for target "
2883 "GL_TIME_ELAPSED_EXT when the number of "
2884 "views in the active draw framebuffer is "
2885 "greater than 1.");
2886 return false;
2887 }
Martin Radev7cf61662017-07-26 17:10:53 +03002888 }
2889
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002890 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002891 for (unsigned int uniformBlockIndex = 0;
2892 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002893 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002894 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002895 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002896 const OffsetBindingPointer<Buffer> &uniformBuffer =
2897 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002898
Geoff Lang5d124a62015-09-15 13:03:27 -04002899 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002900 {
2901 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002902 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002903 InvalidOperation()
2904 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002905 return false;
2906 }
2907
Geoff Lang5d124a62015-09-15 13:03:27 -04002908 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002909 if (uniformBufferSize == 0)
2910 {
2911 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002912 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002913 }
2914
Jamie Madill62d31cb2015-09-11 13:25:51 -04002915 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002916 {
2917 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002918 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002919 InvalidOperation()
2920 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002921 return false;
2922 }
2923 }
2924
Geoff Lange0cff192017-05-30 13:04:56 -04002925 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002926 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002927 {
Geoff Lange0cff192017-05-30 13:04:56 -04002928 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002929 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2930 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002931 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002932 return false;
2933 }
Geoff Lange0cff192017-05-30 13:04:56 -04002934
Geoff Lang9ab5b822017-05-30 16:19:23 -04002935 // Detect that the vertex shader input types match the attribute types
2936 if (!ValidateVertexShaderAttributeTypeMatch(context))
2937 {
2938 return false;
2939 }
2940
Geoff Lange0cff192017-05-30 13:04:56 -04002941 // Detect that the color buffer types match the fragment shader output types
2942 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2943 {
2944 return false;
2945 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002946 }
2947
Jamie Madill250d33f2014-06-06 17:09:03 -04002948 // No-op if zero count
2949 return (count > 0);
2950}
2951
Jamie Madillc1d770e2017-04-13 17:31:24 -04002952bool ValidateDrawArraysCommon(ValidationContext *context,
2953 GLenum mode,
2954 GLint first,
2955 GLsizei count,
2956 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002957{
Jamie Madillfd716582014-06-06 17:09:04 -04002958 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002959 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002960 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002961 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002962 }
2963
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002964 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002965 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002966 if (curTransformFeedback && curTransformFeedback->isActive() &&
2967 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002968 {
2969 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002970 // that does not match the current transform feedback object's draw mode (if transform
2971 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002972 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002973 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002974 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002975 }
2976
Jiajia Qind9671222016-11-29 16:30:31 +08002977 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002978 {
2979 return false;
2980 }
2981
Corentin Wallez71168a02016-12-19 15:11:18 -08002982 // Check the computation of maxVertex doesn't overflow.
2983 // - first < 0 or count < 0 have been checked as an error condition
2984 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2985 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2986 ASSERT(count > 0 && first >= 0);
2987 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2988 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002989 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002990 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002991 return false;
2992 }
2993
Corentin Wallez71168a02016-12-19 15:11:18 -08002994 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002995 {
2996 return false;
2997 }
2998
2999 return true;
3000}
3001
He Yunchaoced53ae2016-11-29 15:00:51 +08003002bool ValidateDrawArraysInstanced(Context *context,
3003 GLenum mode,
3004 GLint first,
3005 GLsizei count,
3006 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003007{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003008 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
Geoff Lang87a93302014-09-16 13:29:43 -04003009}
3010
He Yunchaoced53ae2016-11-29 15:00:51 +08003011bool ValidateDrawArraysInstancedANGLE(Context *context,
3012 GLenum mode,
3013 GLint first,
3014 GLsizei count,
3015 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003016{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003017 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003018 {
3019 return false;
3020 }
3021
Corentin Wallez0dc97812017-06-22 14:38:44 -04003022 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003023}
3024
Jiajia Qind9671222016-11-29 16:30:31 +08003025bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003026{
Jamie Madill250d33f2014-06-06 17:09:03 -04003027 switch (type)
3028 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003029 case GL_UNSIGNED_BYTE:
3030 case GL_UNSIGNED_SHORT:
3031 break;
3032 case GL_UNSIGNED_INT:
3033 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3034 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003035 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08003036 return false;
3037 }
3038 break;
3039 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003040 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08003041 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003042 }
3043
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003044 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003045
3046 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003047 if (curTransformFeedback && curTransformFeedback->isActive() &&
3048 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003049 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003050 // It is an invalid operation to call DrawElements, DrawRangeElements or
3051 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003052 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003053 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003054 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003055 }
3056
Jiajia Qind9671222016-11-29 16:30:31 +08003057 return true;
3058}
3059
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003060bool ValidateDrawElementsCommon(ValidationContext *context,
3061 GLenum mode,
3062 GLsizei count,
3063 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003064 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003065 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08003066{
3067 if (!ValidateDrawElementsBase(context, type))
3068 return false;
3069
3070 const State &state = context->getGLState();
3071
Corentin Wallez170efbf2017-05-02 13:45:01 -04003072 if (!ValidateDrawBase(context, mode, count))
3073 {
3074 return false;
3075 }
3076
Jamie Madill250d33f2014-06-06 17:09:03 -04003077 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003078 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003079 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003080 context->handleError(InvalidOperation() << "Index buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -04003081 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003082 }
3083
He Yunchaoced53ae2016-11-29 15:00:51 +08003084 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003085 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003086
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003087 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3088
3089 if (context->getExtensions().webglCompatibility)
3090 {
3091 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3092 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3093 {
3094 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3095 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3096 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003097 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003098 return false;
3099 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003100
3101 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3102 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3103 // error is generated.
3104 if (reinterpret_cast<intptr_t>(indices) < 0)
3105 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003106 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003107 return false;
3108 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003109 }
3110
3111 if (context->getExtensions().webglCompatibility ||
3112 !context->getGLState().areClientArraysEnabled())
3113 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003114 if (!elementArrayBuffer && count > 0)
3115 {
3116 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3117 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3118 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003119 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003120 return false;
3121 }
3122 }
3123
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003124 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003125 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003126 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003127 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003128 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3129 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3130 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3131 constexpr uint64_t kMaxTypeSize = 8;
3132 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3133 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3134 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003135
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003136 uint64_t typeSize = typeBytes;
3137 uint64_t elementCount = static_cast<uint64_t>(count);
3138 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3139
3140 // Doing the multiplication here is overflow-safe
3141 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3142
3143 // The offset can be any value, check for overflows
3144 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3145 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003146 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003147 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003148 return false;
3149 }
3150
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003151 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3152 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003153 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003154 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003155 return false;
3156 }
3157 }
3158 else if (!indices)
3159 {
3160 // This is an application error that would normally result in a crash,
3161 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003162 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04003163 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003164 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003165 }
3166
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003167 // Use the parameter buffer to retrieve and cache the index range.
3168 // TODO: offer fast path, with disabled index validation.
3169 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3170 const auto &params = context->getParams<HasIndexRange>();
3171 const auto &indexRangeOpt = params.getIndexRange();
3172 if (!indexRangeOpt.valid())
3173 {
3174 // Unexpected error.
3175 return false;
3176 }
3177
3178 // If we use an index greater than our maximum supported index range, return an error.
3179 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3180 // return an error if possible here.
3181 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
3182 {
3183 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3184 return false;
3185 }
3186
3187 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
3188 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003189 {
3190 return false;
3191 }
3192
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003193 // No op if there are no real indices in the index data (all are primitive restart).
3194 return (indexRangeOpt.value().vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003195}
3196
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003197bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
3198 GLenum mode,
3199 GLsizei count,
3200 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003201 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003202 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003203{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003204 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003205}
3206
Geoff Lang3edfe032015-09-04 16:38:24 -04003207bool ValidateDrawElementsInstancedANGLE(Context *context,
3208 GLenum mode,
3209 GLsizei count,
3210 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003211 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003212 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003213{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003214 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003215 {
3216 return false;
3217 }
3218
Corentin Wallez0dc97812017-06-22 14:38:44 -04003219 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003220}
3221
He Yunchaoced53ae2016-11-29 15:00:51 +08003222bool ValidateFramebufferTextureBase(Context *context,
3223 GLenum target,
3224 GLenum attachment,
3225 GLuint texture,
3226 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003227{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003228 if (!ValidFramebufferTarget(target))
3229 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003230 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003231 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003232 }
3233
3234 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003235 {
3236 return false;
3237 }
3238
Jamie Madill55ec3b12014-07-03 10:38:57 -04003239 if (texture != 0)
3240 {
3241 gl::Texture *tex = context->getTexture(texture);
3242
Jamie Madillbe849e42017-05-02 15:49:00 -04003243 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003244 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003245 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003246 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003247 }
3248
3249 if (level < 0)
3250 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003251 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003252 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003253 }
3254 }
3255
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003256 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003257 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003258
Jamie Madill84115c92015-04-23 15:00:07 -04003259 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003260 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003261 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003262 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003263 }
3264
3265 return true;
3266}
3267
Geoff Langb1196682014-07-23 13:47:29 -04003268bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003269{
3270 if (program == 0)
3271 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003272 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003273 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003274 }
3275
Dian Xiang769769a2015-09-09 15:20:08 -07003276 gl::Program *programObject = GetValidProgram(context, program);
3277 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003278 {
3279 return false;
3280 }
3281
Jamie Madill0063c512014-08-25 15:47:53 -04003282 if (!programObject || !programObject->isLinked())
3283 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003284 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003285 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003286 }
3287
Geoff Lang7dd2e102014-11-10 15:19:26 -05003288 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003289 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003290 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003291 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003292 }
3293
Jamie Madill0063c512014-08-25 15:47:53 -04003294 return true;
3295}
3296
Geoff Langf41d0ee2016-10-07 13:04:23 -04003297static bool ValidateSizedGetUniform(Context *context,
3298 GLuint program,
3299 GLint location,
3300 GLsizei bufSize,
3301 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003302{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003303 if (length)
3304 {
3305 *length = 0;
3306 }
3307
Jamie Madill78f41802014-08-25 15:47:55 -04003308 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003309 {
Jamie Madill78f41802014-08-25 15:47:55 -04003310 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003311 }
3312
Geoff Langf41d0ee2016-10-07 13:04:23 -04003313 if (bufSize < 0)
3314 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003315 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003316 return false;
3317 }
3318
Jamie Madilla502c742014-08-28 17:19:13 -04003319 gl::Program *programObject = context->getProgram(program);
3320 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003321
Jamie Madill78f41802014-08-25 15:47:55 -04003322 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003323 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003324 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003325 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003326 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003327 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003328 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003329 }
3330
Geoff Langf41d0ee2016-10-07 13:04:23 -04003331 if (length)
3332 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003333 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003334 }
3335
Jamie Madill0063c512014-08-25 15:47:53 -04003336 return true;
3337}
3338
He Yunchaoced53ae2016-11-29 15:00:51 +08003339bool ValidateGetnUniformfvEXT(Context *context,
3340 GLuint program,
3341 GLint location,
3342 GLsizei bufSize,
3343 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003344{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003345 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003346}
3347
He Yunchaoced53ae2016-11-29 15:00:51 +08003348bool ValidateGetnUniformivEXT(Context *context,
3349 GLuint program,
3350 GLint location,
3351 GLsizei bufSize,
3352 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003353{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003354 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3355}
3356
3357bool ValidateGetUniformfvRobustANGLE(Context *context,
3358 GLuint program,
3359 GLint location,
3360 GLsizei bufSize,
3361 GLsizei *length,
3362 GLfloat *params)
3363{
3364 if (!ValidateRobustEntryPoint(context, bufSize))
3365 {
3366 return false;
3367 }
3368
3369 // bufSize is validated in ValidateSizedGetUniform
3370 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3371}
3372
3373bool ValidateGetUniformivRobustANGLE(Context *context,
3374 GLuint program,
3375 GLint location,
3376 GLsizei bufSize,
3377 GLsizei *length,
3378 GLint *params)
3379{
3380 if (!ValidateRobustEntryPoint(context, bufSize))
3381 {
3382 return false;
3383 }
3384
3385 // bufSize is validated in ValidateSizedGetUniform
3386 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3387}
3388
3389bool ValidateGetUniformuivRobustANGLE(Context *context,
3390 GLuint program,
3391 GLint location,
3392 GLsizei bufSize,
3393 GLsizei *length,
3394 GLuint *params)
3395{
3396 if (!ValidateRobustEntryPoint(context, bufSize))
3397 {
3398 return false;
3399 }
3400
3401 if (context->getClientMajorVersion() < 3)
3402 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003403 context->handleError(InvalidOperation() << "Entry point requires at least OpenGL ES 3.0.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003404 return false;
3405 }
3406
3407 // bufSize is validated in ValidateSizedGetUniform
3408 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003409}
3410
He Yunchaoced53ae2016-11-29 15:00:51 +08003411bool ValidateDiscardFramebufferBase(Context *context,
3412 GLenum target,
3413 GLsizei numAttachments,
3414 const GLenum *attachments,
3415 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003416{
3417 if (numAttachments < 0)
3418 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003419 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003420 return false;
3421 }
3422
3423 for (GLsizei i = 0; i < numAttachments; ++i)
3424 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003425 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003426 {
3427 if (defaultFramebuffer)
3428 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003429 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003430 return false;
3431 }
3432
3433 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3434 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003435 context->handleError(InvalidOperation() << "Requested color attachment is "
3436 "greater than the maximum supported "
3437 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003438 return false;
3439 }
3440 }
3441 else
3442 {
3443 switch (attachments[i])
3444 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003445 case GL_DEPTH_ATTACHMENT:
3446 case GL_STENCIL_ATTACHMENT:
3447 case GL_DEPTH_STENCIL_ATTACHMENT:
3448 if (defaultFramebuffer)
3449 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003450 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3451 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003452 return false;
3453 }
3454 break;
3455 case GL_COLOR:
3456 case GL_DEPTH:
3457 case GL_STENCIL:
3458 if (!defaultFramebuffer)
3459 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003460 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3461 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003462 return false;
3463 }
3464 break;
3465 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003466 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003467 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003468 }
3469 }
3470 }
3471
3472 return true;
3473}
3474
Austin Kinross6ee1e782015-05-29 17:05:37 -07003475bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3476{
3477 // Note that debug marker calls must not set error state
3478
3479 if (length < 0)
3480 {
3481 return false;
3482 }
3483
3484 if (marker == nullptr)
3485 {
3486 return false;
3487 }
3488
3489 return true;
3490}
3491
3492bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3493{
3494 // Note that debug marker calls must not set error state
3495
3496 if (length < 0)
3497 {
3498 return false;
3499 }
3500
3501 if (length > 0 && marker == nullptr)
3502 {
3503 return false;
3504 }
3505
3506 return true;
3507}
3508
Geoff Langdcab33b2015-07-21 13:03:16 -04003509bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003510 GLenum target,
3511 egl::Image *image)
3512{
Geoff Langa8406172015-07-21 16:53:39 -04003513 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3514 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003515 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003516 return false;
3517 }
3518
3519 switch (target)
3520 {
3521 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003522 if (!context->getExtensions().eglImage)
3523 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003524 context->handleError(InvalidEnum()
3525 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003526 }
3527 break;
3528
3529 case GL_TEXTURE_EXTERNAL_OES:
3530 if (!context->getExtensions().eglImageExternal)
3531 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003532 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3533 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003534 }
Geoff Langa8406172015-07-21 16:53:39 -04003535 break;
3536
3537 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003538 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003539 return false;
3540 }
3541
Jamie Madill61e16b42017-06-19 11:13:23 -04003542 ASSERT(context->getCurrentDisplay());
3543 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003544 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003545 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003546 return false;
3547 }
3548
3549 if (image->getSamples() > 0)
3550 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003551 context->handleError(InvalidOperation()
3552 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003553 return false;
3554 }
3555
Geoff Langca271392017-04-05 12:30:00 -04003556 const TextureCaps &textureCaps =
3557 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003558 if (!textureCaps.texturable)
3559 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003560 context->handleError(InvalidOperation()
3561 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003562 return false;
3563 }
3564
Geoff Langdcab33b2015-07-21 13:03:16 -04003565 return true;
3566}
3567
3568bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003569 GLenum target,
3570 egl::Image *image)
3571{
Geoff Langa8406172015-07-21 16:53:39 -04003572 if (!context->getExtensions().eglImage)
3573 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003574 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003575 return false;
3576 }
3577
3578 switch (target)
3579 {
3580 case GL_RENDERBUFFER:
3581 break;
3582
3583 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003584 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003585 return false;
3586 }
3587
Jamie Madill61e16b42017-06-19 11:13:23 -04003588 ASSERT(context->getCurrentDisplay());
3589 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003590 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003591 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003592 return false;
3593 }
3594
Geoff Langca271392017-04-05 12:30:00 -04003595 const TextureCaps &textureCaps =
3596 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003597 if (!textureCaps.renderable)
3598 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003599 context->handleError(InvalidOperation()
3600 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003601 return false;
3602 }
3603
Geoff Langdcab33b2015-07-21 13:03:16 -04003604 return true;
3605}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003606
3607bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3608{
Geoff Lang36167ab2015-12-07 10:27:14 -05003609 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003610 {
3611 // The default VAO should always exist
3612 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003613 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003614 return false;
3615 }
3616
3617 return true;
3618}
3619
Geoff Langc5629752015-12-07 16:29:04 -05003620bool ValidateProgramBinaryBase(Context *context,
3621 GLuint program,
3622 GLenum binaryFormat,
3623 const void *binary,
3624 GLint length)
3625{
3626 Program *programObject = GetValidProgram(context, program);
3627 if (programObject == nullptr)
3628 {
3629 return false;
3630 }
3631
3632 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3633 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3634 programBinaryFormats.end())
3635 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003636 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003637 return false;
3638 }
3639
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003640 if (context->hasActiveTransformFeedback(program))
3641 {
3642 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003643 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3644 "is associated with an active transform "
3645 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003646 return false;
3647 }
3648
Geoff Langc5629752015-12-07 16:29:04 -05003649 return true;
3650}
3651
3652bool ValidateGetProgramBinaryBase(Context *context,
3653 GLuint program,
3654 GLsizei bufSize,
3655 GLsizei *length,
3656 GLenum *binaryFormat,
3657 void *binary)
3658{
3659 Program *programObject = GetValidProgram(context, program);
3660 if (programObject == nullptr)
3661 {
3662 return false;
3663 }
3664
3665 if (!programObject->isLinked())
3666 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003667 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003668 return false;
3669 }
3670
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003671 if (context->getCaps().programBinaryFormats.empty())
3672 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003673 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003674 return false;
3675 }
3676
Geoff Langc5629752015-12-07 16:29:04 -05003677 return true;
3678}
Jamie Madillc29968b2016-01-20 11:17:23 -05003679
Jamie Madillc29968b2016-01-20 11:17:23 -05003680bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3681{
3682 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003683 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003684 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003685 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3686 return false;
3687 }
3688 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3689 {
3690 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003691 return false;
3692 }
3693
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003694 ASSERT(context->getGLState().getDrawFramebuffer());
3695 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003696 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3697
3698 // This should come first before the check for the default frame buffer
3699 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3700 // rather than INVALID_OPERATION
3701 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3702 {
3703 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3704
3705 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003706 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3707 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003708 {
3709 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003710 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3711 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3712 // 3.1 is still a bit ambiguous about the error, but future specs are
3713 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003714 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003715 return false;
3716 }
3717 else if (bufs[colorAttachment] >= maxColorAttachment)
3718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003719 context->handleError(InvalidOperation()
3720 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003721 return false;
3722 }
3723 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3724 frameBufferId != 0)
3725 {
3726 // INVALID_OPERATION-GL is bound to buffer and ith argument
3727 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003728 context->handleError(InvalidOperation()
3729 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003730 return false;
3731 }
3732 }
3733
3734 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3735 // and n is not 1 or bufs is bound to value other than BACK and NONE
3736 if (frameBufferId == 0)
3737 {
3738 if (n != 1)
3739 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003740 context->handleError(InvalidOperation()
3741 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003742 return false;
3743 }
3744
3745 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3746 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003747 context->handleError(
3748 InvalidOperation()
3749 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003750 return false;
3751 }
3752 }
3753
3754 return true;
3755}
3756
Geoff Lang496c02d2016-10-20 11:38:11 -07003757bool ValidateGetBufferPointervBase(Context *context,
3758 GLenum target,
3759 GLenum pname,
3760 GLsizei *length,
3761 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003762{
Geoff Lang496c02d2016-10-20 11:38:11 -07003763 if (length)
3764 {
3765 *length = 0;
3766 }
3767
3768 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3769 {
3770 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003771 InvalidOperation()
3772 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003773 return false;
3774 }
3775
Olli Etuaho4f667482016-03-30 15:56:35 +03003776 if (!ValidBufferTarget(context, target))
3777 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003778 context->handleError(InvalidEnum() << "Buffer target not valid: 0x" << std::hex
3779 << std::uppercase << target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003780 return false;
3781 }
3782
Geoff Lang496c02d2016-10-20 11:38:11 -07003783 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003784 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003785 case GL_BUFFER_MAP_POINTER:
3786 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003787
Geoff Lang496c02d2016-10-20 11:38:11 -07003788 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003789 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003790 return false;
3791 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003792
3793 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3794 // target bound to zero generate an INVALID_OPERATION error."
3795 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003796 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003797 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003798 context->handleError(InvalidOperation()
3799 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003800 return false;
3801 }
3802
Geoff Lang496c02d2016-10-20 11:38:11 -07003803 if (length)
3804 {
3805 *length = 1;
3806 }
3807
Olli Etuaho4f667482016-03-30 15:56:35 +03003808 return true;
3809}
3810
3811bool ValidateUnmapBufferBase(Context *context, GLenum target)
3812{
3813 if (!ValidBufferTarget(context, target))
3814 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003815 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003816 return false;
3817 }
3818
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003819 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003820
3821 if (buffer == nullptr || !buffer->isMapped())
3822 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003823 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003824 return false;
3825 }
3826
3827 return true;
3828}
3829
3830bool ValidateMapBufferRangeBase(Context *context,
3831 GLenum target,
3832 GLintptr offset,
3833 GLsizeiptr length,
3834 GLbitfield access)
3835{
3836 if (!ValidBufferTarget(context, target))
3837 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003838 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003839 return false;
3840 }
3841
Brandon Jones6cad5662017-06-14 13:25:13 -07003842 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003843 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003844 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3845 return false;
3846 }
3847
3848 if (length < 0)
3849 {
3850 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003851 return false;
3852 }
3853
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003854 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003855
3856 if (!buffer)
3857 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003858 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003859 return false;
3860 }
3861
3862 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003863 CheckedNumeric<size_t> checkedOffset(offset);
3864 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003865
Jamie Madille2e406c2016-06-02 13:04:10 -04003866 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003867 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003868 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003869 return false;
3870 }
3871
3872 // Check for invalid bits in the mask
3873 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3874 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3875 GL_MAP_UNSYNCHRONIZED_BIT;
3876
3877 if (access & ~(allAccessBits))
3878 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003879 context->handleError(InvalidValue()
3880 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003881 return false;
3882 }
3883
3884 if (length == 0)
3885 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003886 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003887 return false;
3888 }
3889
3890 if (buffer->isMapped())
3891 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003892 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003893 return false;
3894 }
3895
3896 // Check for invalid bit combinations
3897 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3898 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003899 context->handleError(InvalidOperation()
3900 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003901 return false;
3902 }
3903
3904 GLbitfield writeOnlyBits =
3905 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3906
3907 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3908 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003909 context->handleError(InvalidOperation()
3910 << "Invalid access bits when mapping buffer for reading: 0x"
3911 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003912 return false;
3913 }
3914
3915 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3916 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003917 context->handleError(
3918 InvalidOperation()
3919 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003920 return false;
3921 }
Geoff Lang79f71042017-08-14 16:43:43 -04003922
3923 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003924}
3925
3926bool ValidateFlushMappedBufferRangeBase(Context *context,
3927 GLenum target,
3928 GLintptr offset,
3929 GLsizeiptr length)
3930{
Brandon Jones6cad5662017-06-14 13:25:13 -07003931 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003932 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003933 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3934 return false;
3935 }
3936
3937 if (length < 0)
3938 {
3939 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003940 return false;
3941 }
3942
3943 if (!ValidBufferTarget(context, target))
3944 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003945 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003946 return false;
3947 }
3948
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003949 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003950
3951 if (buffer == nullptr)
3952 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003953 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003954 return false;
3955 }
3956
3957 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3958 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003959 context->handleError(InvalidOperation()
3960 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003961 return false;
3962 }
3963
3964 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003965 CheckedNumeric<size_t> checkedOffset(offset);
3966 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003967
Jamie Madille2e406c2016-06-02 13:04:10 -04003968 if (!checkedSize.IsValid() ||
3969 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003970 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003971 context->handleError(InvalidValue()
3972 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003973 return false;
3974 }
3975
3976 return true;
3977}
3978
Olli Etuaho41997e72016-03-10 13:38:39 +02003979bool ValidateGenOrDelete(Context *context, GLint n)
3980{
3981 if (n < 0)
3982 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003983 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003984 return false;
3985 }
3986 return true;
3987}
3988
Geoff Langff5b2d52016-09-07 11:32:23 -04003989bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3990{
3991 if (!context->getExtensions().robustClientMemory)
3992 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003993 context->handleError(InvalidOperation()
3994 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003995 return false;
3996 }
3997
3998 if (bufSize < 0)
3999 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004000 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004001 return false;
4002 }
4003
4004 return true;
4005}
4006
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004007bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4008{
4009 if (bufSize < numParams)
4010 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004011 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4012 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004013 return false;
4014 }
4015
4016 return true;
4017}
4018
Jamie Madillbe849e42017-05-02 15:49:00 -04004019bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
4020 GLenum target,
4021 GLenum attachment,
4022 GLenum pname,
4023 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004024{
Geoff Langff5b2d52016-09-07 11:32:23 -04004025 if (!ValidFramebufferTarget(target))
4026 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004027 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004028 return false;
4029 }
4030
4031 int clientVersion = context->getClientMajorVersion();
4032
4033 switch (pname)
4034 {
4035 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4036 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4037 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4038 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4039 break;
4040
Martin Radeve5285d22017-07-14 16:23:53 +03004041 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4042 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4043 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4044 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4045 if (clientVersion < 3 || !context->getExtensions().multiview)
4046 {
4047 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4048 return false;
4049 }
4050 break;
4051
Geoff Langff5b2d52016-09-07 11:32:23 -04004052 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4053 if (clientVersion < 3 && !context->getExtensions().sRGB)
4054 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004055 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004056 return false;
4057 }
4058 break;
4059
4060 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4061 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4062 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4063 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4064 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4065 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4066 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4067 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4068 if (clientVersion < 3)
4069 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004070 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004071 return false;
4072 }
4073 break;
4074
4075 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004076 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004077 return false;
4078 }
4079
4080 // Determine if the attachment is a valid enum
4081 switch (attachment)
4082 {
4083 case GL_BACK:
4084 case GL_FRONT:
4085 case GL_DEPTH:
4086 case GL_STENCIL:
4087 case GL_DEPTH_STENCIL_ATTACHMENT:
4088 if (clientVersion < 3)
4089 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004090 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004091 return false;
4092 }
4093 break;
4094
4095 case GL_DEPTH_ATTACHMENT:
4096 case GL_STENCIL_ATTACHMENT:
4097 break;
4098
4099 default:
4100 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4101 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4102 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004103 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004104 return false;
4105 }
4106 break;
4107 }
4108
4109 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4110 ASSERT(framebuffer);
4111
4112 if (framebuffer->id() == 0)
4113 {
4114 if (clientVersion < 3)
4115 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004116 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004117 return false;
4118 }
4119
4120 switch (attachment)
4121 {
4122 case GL_BACK:
4123 case GL_DEPTH:
4124 case GL_STENCIL:
4125 break;
4126
4127 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004128 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004129 return false;
4130 }
4131 }
4132 else
4133 {
4134 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4135 {
4136 // Valid attachment query
4137 }
4138 else
4139 {
4140 switch (attachment)
4141 {
4142 case GL_DEPTH_ATTACHMENT:
4143 case GL_STENCIL_ATTACHMENT:
4144 break;
4145
4146 case GL_DEPTH_STENCIL_ATTACHMENT:
4147 if (!framebuffer->hasValidDepthStencil())
4148 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004149 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004150 return false;
4151 }
4152 break;
4153
4154 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004155 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004156 return false;
4157 }
4158 }
4159 }
4160
4161 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4162 if (attachmentObject)
4163 {
4164 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4165 attachmentObject->type() == GL_TEXTURE ||
4166 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4167
4168 switch (pname)
4169 {
4170 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4171 if (attachmentObject->type() != GL_RENDERBUFFER &&
4172 attachmentObject->type() != GL_TEXTURE)
4173 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004174 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004175 return false;
4176 }
4177 break;
4178
4179 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4180 if (attachmentObject->type() != GL_TEXTURE)
4181 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004182 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004183 return false;
4184 }
4185 break;
4186
4187 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4188 if (attachmentObject->type() != GL_TEXTURE)
4189 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004190 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004191 return false;
4192 }
4193 break;
4194
4195 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4196 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4197 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004198 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004199 return false;
4200 }
4201 break;
4202
4203 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4204 if (attachmentObject->type() != GL_TEXTURE)
4205 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004206 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004207 return false;
4208 }
4209 break;
4210
4211 default:
4212 break;
4213 }
4214 }
4215 else
4216 {
4217 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4218 // is NONE, then querying any other pname will generate INVALID_ENUM.
4219
4220 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4221 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4222 // INVALID_OPERATION for all other pnames
4223
4224 switch (pname)
4225 {
4226 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4227 break;
4228
4229 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4230 if (clientVersion < 3)
4231 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004232 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004233 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004234 return false;
4235 }
4236 break;
4237
4238 default:
4239 if (clientVersion < 3)
4240 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004241 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004242 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004243 return false;
4244 }
4245 else
4246 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004247 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004248 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004249 return false;
4250 }
4251 }
4252 }
4253
Martin Radeve5285d22017-07-14 16:23:53 +03004254 if (numParams)
4255 {
4256 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4257 {
4258 // Only when the viewport offsets are queried we can have a varying number of output
4259 // parameters.
4260 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4261 *numParams = numViews * 2;
4262 }
4263 else
4264 {
4265 // For all other queries we can have only one output parameter.
4266 *numParams = 1;
4267 }
4268 }
4269
Geoff Langff5b2d52016-09-07 11:32:23 -04004270 return true;
4271}
4272
4273bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4274 GLenum target,
4275 GLenum attachment,
4276 GLenum pname,
4277 GLsizei bufSize,
4278 GLsizei *numParams)
4279{
4280 if (!ValidateRobustEntryPoint(context, bufSize))
4281 {
4282 return false;
4283 }
4284
Jamie Madillbe849e42017-05-02 15:49:00 -04004285 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4286 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004287 {
4288 return false;
4289 }
4290
4291 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4292 {
4293 return false;
4294 }
4295
4296 return true;
4297}
4298
Geoff Langff5b2d52016-09-07 11:32:23 -04004299bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4300 GLenum target,
4301 GLenum pname,
4302 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004303 GLsizei *length,
4304 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004305{
4306 if (!ValidateRobustEntryPoint(context, bufSize))
4307 {
4308 return false;
4309 }
4310
Geoff Langebebe1c2016-10-14 12:01:31 -04004311 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004312 {
4313 return false;
4314 }
4315
Geoff Langebebe1c2016-10-14 12:01:31 -04004316 if (!ValidateRobustBufferSize(context, bufSize, *length))
4317 {
4318 return false;
4319 }
4320
4321 return true;
4322}
4323
4324bool ValidateGetBufferParameteri64v(ValidationContext *context,
4325 GLenum target,
4326 GLenum pname,
4327 GLint64 *params)
4328{
4329 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4330}
4331
4332bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4333 GLenum target,
4334 GLenum pname,
4335 GLsizei bufSize,
4336 GLsizei *length,
4337 GLint64 *params)
4338{
4339 if (!ValidateRobustEntryPoint(context, bufSize))
4340 {
4341 return false;
4342 }
4343
4344 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4345 {
4346 return false;
4347 }
4348
4349 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004350 {
4351 return false;
4352 }
4353
4354 return true;
4355}
4356
Jamie Madillbe849e42017-05-02 15:49:00 -04004357bool ValidateGetProgramivBase(ValidationContext *context,
4358 GLuint program,
4359 GLenum pname,
4360 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004361{
4362 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004363 if (numParams)
4364 {
4365 *numParams = 1;
4366 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004367
4368 Program *programObject = GetValidProgram(context, program);
4369 if (!programObject)
4370 {
4371 return false;
4372 }
4373
4374 switch (pname)
4375 {
4376 case GL_DELETE_STATUS:
4377 case GL_LINK_STATUS:
4378 case GL_VALIDATE_STATUS:
4379 case GL_INFO_LOG_LENGTH:
4380 case GL_ATTACHED_SHADERS:
4381 case GL_ACTIVE_ATTRIBUTES:
4382 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4383 case GL_ACTIVE_UNIFORMS:
4384 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4385 break;
4386
4387 case GL_PROGRAM_BINARY_LENGTH:
4388 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4389 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004390 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4391 "requires GL_OES_get_program_binary or "
4392 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004393 return false;
4394 }
4395 break;
4396
4397 case GL_ACTIVE_UNIFORM_BLOCKS:
4398 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4399 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4400 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4401 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4402 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4403 if (context->getClientMajorVersion() < 3)
4404 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004405 context->handleError(InvalidEnum() << "Querying requires at least ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004406 return false;
4407 }
4408 break;
4409
Yunchao He61afff12017-03-14 15:34:03 +08004410 case GL_PROGRAM_SEPARABLE:
4411 if (context->getClientVersion() < Version(3, 1))
4412 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004413 context->handleError(InvalidEnum() << "Querying requires at least ES 3.1.");
Yunchao He61afff12017-03-14 15:34:03 +08004414 return false;
4415 }
4416 break;
4417
Geoff Langff5b2d52016-09-07 11:32:23 -04004418 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004419 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004420 return false;
4421 }
4422
4423 return true;
4424}
4425
4426bool ValidateGetProgramivRobustANGLE(Context *context,
4427 GLuint program,
4428 GLenum pname,
4429 GLsizei bufSize,
4430 GLsizei *numParams)
4431{
4432 if (!ValidateRobustEntryPoint(context, bufSize))
4433 {
4434 return false;
4435 }
4436
Jamie Madillbe849e42017-05-02 15:49:00 -04004437 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004438 {
4439 return false;
4440 }
4441
4442 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4443 {
4444 return false;
4445 }
4446
4447 return true;
4448}
4449
Geoff Lang740d9022016-10-07 11:20:52 -04004450bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4451 GLenum target,
4452 GLenum pname,
4453 GLsizei bufSize,
4454 GLsizei *length,
4455 GLint *params)
4456{
4457 if (!ValidateRobustEntryPoint(context, bufSize))
4458 {
4459 return false;
4460 }
4461
4462 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4463 {
4464 return false;
4465 }
4466
4467 if (!ValidateRobustBufferSize(context, bufSize, *length))
4468 {
4469 return false;
4470 }
4471
4472 return true;
4473}
4474
Geoff Langd7d0ed32016-10-07 11:33:51 -04004475bool ValidateGetShaderivRobustANGLE(Context *context,
4476 GLuint shader,
4477 GLenum pname,
4478 GLsizei bufSize,
4479 GLsizei *length,
4480 GLint *params)
4481{
4482 if (!ValidateRobustEntryPoint(context, bufSize))
4483 {
4484 return false;
4485 }
4486
4487 if (!ValidateGetShaderivBase(context, shader, pname, length))
4488 {
4489 return false;
4490 }
4491
4492 if (!ValidateRobustBufferSize(context, bufSize, *length))
4493 {
4494 return false;
4495 }
4496
4497 return true;
4498}
4499
Geoff Langc1984ed2016-10-07 12:41:00 -04004500bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4501 GLenum target,
4502 GLenum pname,
4503 GLsizei bufSize,
4504 GLsizei *length,
4505 GLfloat *params)
4506{
4507 if (!ValidateRobustEntryPoint(context, bufSize))
4508 {
4509 return false;
4510 }
4511
4512 if (!ValidateGetTexParameterBase(context, target, pname, length))
4513 {
4514 return false;
4515 }
4516
4517 if (!ValidateRobustBufferSize(context, bufSize, *length))
4518 {
4519 return false;
4520 }
4521
4522 return true;
4523}
4524
Geoff Langc1984ed2016-10-07 12:41:00 -04004525bool ValidateGetTexParameterivRobustANGLE(Context *context,
4526 GLenum target,
4527 GLenum pname,
4528 GLsizei bufSize,
4529 GLsizei *length,
4530 GLint *params)
4531{
4532 if (!ValidateRobustEntryPoint(context, bufSize))
4533 {
4534 return false;
4535 }
4536
4537 if (!ValidateGetTexParameterBase(context, target, pname, length))
4538 {
4539 return false;
4540 }
4541
4542 if (!ValidateRobustBufferSize(context, bufSize, *length))
4543 {
4544 return false;
4545 }
4546
4547 return true;
4548}
4549
Geoff Langc1984ed2016-10-07 12:41:00 -04004550bool ValidateTexParameterfvRobustANGLE(Context *context,
4551 GLenum target,
4552 GLenum pname,
4553 GLsizei bufSize,
4554 const GLfloat *params)
4555{
4556 if (!ValidateRobustEntryPoint(context, bufSize))
4557 {
4558 return false;
4559 }
4560
4561 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4562}
4563
Geoff Langc1984ed2016-10-07 12:41:00 -04004564bool ValidateTexParameterivRobustANGLE(Context *context,
4565 GLenum target,
4566 GLenum pname,
4567 GLsizei bufSize,
4568 const GLint *params)
4569{
4570 if (!ValidateRobustEntryPoint(context, bufSize))
4571 {
4572 return false;
4573 }
4574
4575 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4576}
4577
4578bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4579{
4580 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4581}
4582
4583bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4584 GLuint sampler,
4585 GLenum pname,
4586 GLuint bufSize,
4587 GLsizei *length,
4588 GLfloat *params)
4589{
4590 if (!ValidateRobustEntryPoint(context, bufSize))
4591 {
4592 return false;
4593 }
4594
4595 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4596 {
4597 return false;
4598 }
4599
4600 if (!ValidateRobustBufferSize(context, bufSize, *length))
4601 {
4602 return false;
4603 }
4604
4605 return true;
4606}
4607
4608bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4609{
4610 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4611}
4612
4613bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4614 GLuint sampler,
4615 GLenum pname,
4616 GLuint bufSize,
4617 GLsizei *length,
4618 GLint *params)
4619{
4620 if (!ValidateRobustEntryPoint(context, bufSize))
4621 {
4622 return false;
4623 }
4624
4625 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4626 {
4627 return false;
4628 }
4629
4630 if (!ValidateRobustBufferSize(context, bufSize, *length))
4631 {
4632 return false;
4633 }
4634
4635 return true;
4636}
4637
4638bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4639{
4640 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4641}
4642
4643bool ValidateSamplerParameterfv(Context *context,
4644 GLuint sampler,
4645 GLenum pname,
4646 const GLfloat *params)
4647{
4648 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4649}
4650
4651bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4652 GLuint sampler,
4653 GLenum pname,
4654 GLsizei bufSize,
4655 const GLfloat *params)
4656{
4657 if (!ValidateRobustEntryPoint(context, bufSize))
4658 {
4659 return false;
4660 }
4661
4662 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4663}
4664
4665bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4666{
4667 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4668}
4669
4670bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4671{
4672 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4673}
4674
4675bool ValidateSamplerParameterivRobustANGLE(Context *context,
4676 GLuint sampler,
4677 GLenum pname,
4678 GLsizei bufSize,
4679 const GLint *params)
4680{
4681 if (!ValidateRobustEntryPoint(context, bufSize))
4682 {
4683 return false;
4684 }
4685
4686 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4687}
4688
Geoff Lang0b031062016-10-13 14:30:04 -04004689bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4690 GLuint index,
4691 GLenum pname,
4692 GLsizei bufSize,
4693 GLsizei *length,
4694 GLfloat *params)
4695{
4696 if (!ValidateRobustEntryPoint(context, bufSize))
4697 {
4698 return false;
4699 }
4700
4701 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4702 {
4703 return false;
4704 }
4705
4706 if (!ValidateRobustBufferSize(context, bufSize, *length))
4707 {
4708 return false;
4709 }
4710
4711 return true;
4712}
4713
Geoff Lang0b031062016-10-13 14:30:04 -04004714bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4715 GLuint index,
4716 GLenum pname,
4717 GLsizei bufSize,
4718 GLsizei *length,
4719 GLint *params)
4720{
4721 if (!ValidateRobustEntryPoint(context, bufSize))
4722 {
4723 return false;
4724 }
4725
4726 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4727 {
4728 return false;
4729 }
4730
4731 if (!ValidateRobustBufferSize(context, bufSize, *length))
4732 {
4733 return false;
4734 }
4735
4736 return true;
4737}
4738
Geoff Lang0b031062016-10-13 14:30:04 -04004739bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4740 GLuint index,
4741 GLenum pname,
4742 GLsizei bufSize,
4743 GLsizei *length,
4744 void **pointer)
4745{
4746 if (!ValidateRobustEntryPoint(context, bufSize))
4747 {
4748 return false;
4749 }
4750
4751 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4752 {
4753 return false;
4754 }
4755
4756 if (!ValidateRobustBufferSize(context, bufSize, *length))
4757 {
4758 return false;
4759 }
4760
4761 return true;
4762}
4763
4764bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
4765{
4766 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4767}
4768
4769bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4770 GLuint index,
4771 GLenum pname,
4772 GLsizei bufSize,
4773 GLsizei *length,
4774 GLint *params)
4775{
4776 if (!ValidateRobustEntryPoint(context, bufSize))
4777 {
4778 return false;
4779 }
4780
4781 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4782 {
4783 return false;
4784 }
4785
4786 if (!ValidateRobustBufferSize(context, bufSize, *length))
4787 {
4788 return false;
4789 }
4790
4791 return true;
4792}
4793
4794bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
4795{
4796 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4797}
4798
4799bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4800 GLuint index,
4801 GLenum pname,
4802 GLsizei bufSize,
4803 GLsizei *length,
4804 GLuint *params)
4805{
4806 if (!ValidateRobustEntryPoint(context, bufSize))
4807 {
4808 return false;
4809 }
4810
4811 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4812 {
4813 return false;
4814 }
4815
4816 if (!ValidateRobustBufferSize(context, bufSize, *length))
4817 {
4818 return false;
4819 }
4820
4821 return true;
4822}
4823
Geoff Lang6899b872016-10-14 11:30:13 -04004824bool ValidateGetActiveUniformBlockiv(Context *context,
4825 GLuint program,
4826 GLuint uniformBlockIndex,
4827 GLenum pname,
4828 GLint *params)
4829{
4830 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
4831}
4832
4833bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4834 GLuint program,
4835 GLuint uniformBlockIndex,
4836 GLenum pname,
4837 GLsizei bufSize,
4838 GLsizei *length,
4839 GLint *params)
4840{
4841 if (!ValidateRobustEntryPoint(context, bufSize))
4842 {
4843 return false;
4844 }
4845
4846 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4847 {
4848 return false;
4849 }
4850
4851 if (!ValidateRobustBufferSize(context, bufSize, *length))
4852 {
4853 return false;
4854 }
4855
4856 return true;
4857}
4858
Geoff Lang0a9661f2016-10-20 10:59:20 -07004859bool ValidateGetInternalFormativ(Context *context,
4860 GLenum target,
4861 GLenum internalformat,
4862 GLenum pname,
4863 GLsizei bufSize,
4864 GLint *params)
4865{
4866 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4867 nullptr);
4868}
4869
4870bool ValidateGetInternalFormativRobustANGLE(Context *context,
4871 GLenum target,
4872 GLenum internalformat,
4873 GLenum pname,
4874 GLsizei bufSize,
4875 GLsizei *length,
4876 GLint *params)
4877{
4878 if (!ValidateRobustEntryPoint(context, bufSize))
4879 {
4880 return false;
4881 }
4882
4883 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4884 {
4885 return false;
4886 }
4887
4888 if (!ValidateRobustBufferSize(context, bufSize, *length))
4889 {
4890 return false;
4891 }
4892
4893 return true;
4894}
4895
Shao80957d92017-02-20 21:25:59 +08004896bool ValidateVertexFormatBase(ValidationContext *context,
4897 GLuint attribIndex,
4898 GLint size,
4899 GLenum type,
4900 GLboolean pureInteger)
4901{
4902 const Caps &caps = context->getCaps();
4903 if (attribIndex >= caps.maxVertexAttributes)
4904 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004905 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004906 return false;
4907 }
4908
4909 if (size < 1 || size > 4)
4910 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004911 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004912 return false;
Shao80957d92017-02-20 21:25:59 +08004913 }
4914
4915 switch (type)
4916 {
4917 case GL_BYTE:
4918 case GL_UNSIGNED_BYTE:
4919 case GL_SHORT:
4920 case GL_UNSIGNED_SHORT:
4921 break;
4922
4923 case GL_INT:
4924 case GL_UNSIGNED_INT:
4925 if (context->getClientMajorVersion() < 3)
4926 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004927 context->handleError(InvalidEnum()
4928 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004929 return false;
4930 }
4931 break;
4932
4933 case GL_FIXED:
4934 case GL_FLOAT:
4935 if (pureInteger)
4936 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004937 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004938 return false;
4939 }
4940 break;
4941
4942 case GL_HALF_FLOAT:
4943 if (context->getClientMajorVersion() < 3)
4944 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004945 context->handleError(InvalidEnum()
4946 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004947 return false;
4948 }
4949 if (pureInteger)
4950 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004951 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004952 return false;
4953 }
4954 break;
4955
4956 case GL_INT_2_10_10_10_REV:
4957 case GL_UNSIGNED_INT_2_10_10_10_REV:
4958 if (context->getClientMajorVersion() < 3)
4959 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004960 context->handleError(InvalidEnum()
4961 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004962 return false;
4963 }
4964 if (pureInteger)
4965 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004966 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004967 return false;
4968 }
4969 if (size != 4)
4970 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004971 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4972 "UNSIGNED_INT_2_10_10_10_REV and "
4973 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004974 return false;
4975 }
4976 break;
4977
4978 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004979 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004980 return false;
4981 }
4982
4983 return true;
4984}
4985
Geoff Lang76e65652017-03-27 14:58:02 -04004986// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4987// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4988// specified clear value and the type of a buffer that is being cleared generates an
4989// INVALID_OPERATION error instead of producing undefined results
4990bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4991 GLint drawbuffer,
4992 const GLenum *validComponentTypes,
4993 size_t validComponentTypeCount)
4994{
4995 const FramebufferAttachment *attachment =
4996 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4997 if (attachment)
4998 {
4999 GLenum componentType = attachment->getFormat().info->componentType;
5000 const GLenum *end = validComponentTypes + validComponentTypeCount;
5001 if (std::find(validComponentTypes, end, componentType) == end)
5002 {
5003 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005004 InvalidOperation()
5005 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005006 return false;
5007 }
5008 }
5009
5010 return true;
5011}
5012
Corentin Wallezb2931602017-04-11 15:58:57 -04005013bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
5014 GLsizei imageSize,
5015 GLsizei dataSize)
5016{
5017 if (!ValidateRobustEntryPoint(context, dataSize))
5018 {
5019 return false;
5020 }
5021
5022 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
5023 if (pixelUnpackBuffer == nullptr)
5024 {
5025 if (dataSize < imageSize)
5026 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005027 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005028 }
5029 }
5030 return true;
5031}
5032
Jamie Madillbe849e42017-05-02 15:49:00 -04005033bool ValidateGetBufferParameterBase(ValidationContext *context,
5034 GLenum target,
5035 GLenum pname,
5036 bool pointerVersion,
5037 GLsizei *numParams)
5038{
5039 if (numParams)
5040 {
5041 *numParams = 0;
5042 }
5043
5044 if (!ValidBufferTarget(context, target))
5045 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005046 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005047 return false;
5048 }
5049
5050 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5051 if (!buffer)
5052 {
5053 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005054 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005055 return false;
5056 }
5057
5058 const Extensions &extensions = context->getExtensions();
5059
5060 switch (pname)
5061 {
5062 case GL_BUFFER_USAGE:
5063 case GL_BUFFER_SIZE:
5064 break;
5065
5066 case GL_BUFFER_ACCESS_OES:
5067 if (!extensions.mapBuffer)
5068 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005069 context->handleError(InvalidEnum()
5070 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005071 return false;
5072 }
5073 break;
5074
5075 case GL_BUFFER_MAPPED:
5076 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5077 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5078 !extensions.mapBufferRange)
5079 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005080 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5081 "GL_OES_mapbuffer or "
5082 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005083 return false;
5084 }
5085 break;
5086
5087 case GL_BUFFER_MAP_POINTER:
5088 if (!pointerVersion)
5089 {
5090 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005091 InvalidEnum()
5092 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005093 return false;
5094 }
5095 break;
5096
5097 case GL_BUFFER_ACCESS_FLAGS:
5098 case GL_BUFFER_MAP_OFFSET:
5099 case GL_BUFFER_MAP_LENGTH:
5100 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5101 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005102 context->handleError(InvalidEnum()
5103 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005104 return false;
5105 }
5106 break;
5107
5108 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005109 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005110 return false;
5111 }
5112
5113 // All buffer parameter queries return one value.
5114 if (numParams)
5115 {
5116 *numParams = 1;
5117 }
5118
5119 return true;
5120}
5121
5122bool ValidateGetRenderbufferParameterivBase(Context *context,
5123 GLenum target,
5124 GLenum pname,
5125 GLsizei *length)
5126{
5127 if (length)
5128 {
5129 *length = 0;
5130 }
5131
5132 if (target != GL_RENDERBUFFER)
5133 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005134 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005135 return false;
5136 }
5137
5138 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5139 if (renderbuffer == nullptr)
5140 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005141 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005142 return false;
5143 }
5144
5145 switch (pname)
5146 {
5147 case GL_RENDERBUFFER_WIDTH:
5148 case GL_RENDERBUFFER_HEIGHT:
5149 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5150 case GL_RENDERBUFFER_RED_SIZE:
5151 case GL_RENDERBUFFER_GREEN_SIZE:
5152 case GL_RENDERBUFFER_BLUE_SIZE:
5153 case GL_RENDERBUFFER_ALPHA_SIZE:
5154 case GL_RENDERBUFFER_DEPTH_SIZE:
5155 case GL_RENDERBUFFER_STENCIL_SIZE:
5156 break;
5157
5158 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5159 if (!context->getExtensions().framebufferMultisample)
5160 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005161 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005162 return false;
5163 }
5164 break;
5165
5166 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005167 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005168 return false;
5169 }
5170
5171 if (length)
5172 {
5173 *length = 1;
5174 }
5175 return true;
5176}
5177
5178bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5179{
5180 if (length)
5181 {
5182 *length = 0;
5183 }
5184
5185 if (GetValidShader(context, shader) == nullptr)
5186 {
5187 return false;
5188 }
5189
5190 switch (pname)
5191 {
5192 case GL_SHADER_TYPE:
5193 case GL_DELETE_STATUS:
5194 case GL_COMPILE_STATUS:
5195 case GL_INFO_LOG_LENGTH:
5196 case GL_SHADER_SOURCE_LENGTH:
5197 break;
5198
5199 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5200 if (!context->getExtensions().translatedShaderSource)
5201 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005202 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005203 return false;
5204 }
5205 break;
5206
5207 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005208 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005209 return false;
5210 }
5211
5212 if (length)
5213 {
5214 *length = 1;
5215 }
5216 return true;
5217}
5218
5219bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
5220{
5221 if (length)
5222 {
5223 *length = 0;
5224 }
5225
5226 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5227 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005228 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005229 return false;
5230 }
5231
5232 if (context->getTargetTexture(target) == nullptr)
5233 {
5234 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005235 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005236 return false;
5237 }
5238
5239 switch (pname)
5240 {
5241 case GL_TEXTURE_MAG_FILTER:
5242 case GL_TEXTURE_MIN_FILTER:
5243 case GL_TEXTURE_WRAP_S:
5244 case GL_TEXTURE_WRAP_T:
5245 break;
5246
5247 case GL_TEXTURE_USAGE_ANGLE:
5248 if (!context->getExtensions().textureUsage)
5249 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005250 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005251 return false;
5252 }
5253 break;
5254
5255 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5256 if (!context->getExtensions().textureFilterAnisotropic)
5257 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005258 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005259 return false;
5260 }
5261 break;
5262
5263 case GL_TEXTURE_IMMUTABLE_FORMAT:
5264 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5265 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005266 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005267 return false;
5268 }
5269 break;
5270
5271 case GL_TEXTURE_WRAP_R:
5272 case GL_TEXTURE_IMMUTABLE_LEVELS:
5273 case GL_TEXTURE_SWIZZLE_R:
5274 case GL_TEXTURE_SWIZZLE_G:
5275 case GL_TEXTURE_SWIZZLE_B:
5276 case GL_TEXTURE_SWIZZLE_A:
5277 case GL_TEXTURE_BASE_LEVEL:
5278 case GL_TEXTURE_MAX_LEVEL:
5279 case GL_TEXTURE_MIN_LOD:
5280 case GL_TEXTURE_MAX_LOD:
5281 case GL_TEXTURE_COMPARE_MODE:
5282 case GL_TEXTURE_COMPARE_FUNC:
5283 if (context->getClientMajorVersion() < 3)
5284 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005285 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005286 return false;
5287 }
5288 break;
5289
5290 case GL_TEXTURE_SRGB_DECODE_EXT:
5291 if (!context->getExtensions().textureSRGBDecode)
5292 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005293 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005294 return false;
5295 }
5296 break;
5297
5298 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005299 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005300 return false;
5301 }
5302
5303 if (length)
5304 {
5305 *length = 1;
5306 }
5307 return true;
5308}
5309
5310bool ValidateGetVertexAttribBase(Context *context,
5311 GLuint index,
5312 GLenum pname,
5313 GLsizei *length,
5314 bool pointer,
5315 bool pureIntegerEntryPoint)
5316{
5317 if (length)
5318 {
5319 *length = 0;
5320 }
5321
5322 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5323 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005324 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005325 return false;
5326 }
5327
5328 if (index >= context->getCaps().maxVertexAttributes)
5329 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005330 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005331 return false;
5332 }
5333
5334 if (pointer)
5335 {
5336 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5337 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005338 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005339 return false;
5340 }
5341 }
5342 else
5343 {
5344 switch (pname)
5345 {
5346 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5347 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5348 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5349 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5350 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5351 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5352 case GL_CURRENT_VERTEX_ATTRIB:
5353 break;
5354
5355 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5356 static_assert(
5357 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5358 "ANGLE extension enums not equal to GL enums.");
5359 if (context->getClientMajorVersion() < 3 &&
5360 !context->getExtensions().instancedArrays)
5361 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005362 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5363 "requires OpenGL ES 3.0 or "
5364 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005365 return false;
5366 }
5367 break;
5368
5369 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5370 if (context->getClientMajorVersion() < 3)
5371 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005372 context->handleError(
5373 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005374 return false;
5375 }
5376 break;
5377
5378 case GL_VERTEX_ATTRIB_BINDING:
5379 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5380 if (context->getClientVersion() < ES_3_1)
5381 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005382 context->handleError(InvalidEnum()
5383 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005384 return false;
5385 }
5386 break;
5387
5388 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005389 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005390 return false;
5391 }
5392 }
5393
5394 if (length)
5395 {
5396 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5397 {
5398 *length = 4;
5399 }
5400 else
5401 {
5402 *length = 1;
5403 }
5404 }
5405
5406 return true;
5407}
5408
Jamie Madill4928b7c2017-06-20 12:57:39 -04005409bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005410 GLint x,
5411 GLint y,
5412 GLsizei width,
5413 GLsizei height,
5414 GLenum format,
5415 GLenum type,
5416 GLsizei bufSize,
5417 GLsizei *length,
5418 GLsizei *columns,
5419 GLsizei *rows,
5420 void *pixels)
5421{
5422 if (length != nullptr)
5423 {
5424 *length = 0;
5425 }
5426 if (rows != nullptr)
5427 {
5428 *rows = 0;
5429 }
5430 if (columns != nullptr)
5431 {
5432 *columns = 0;
5433 }
5434
5435 if (width < 0 || height < 0)
5436 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005437 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005438 return false;
5439 }
5440
5441 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5442
5443 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5444 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005445 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005446 return false;
5447 }
5448
5449 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5450 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005451 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005452 return false;
5453 }
5454
5455 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5456 ASSERT(framebuffer);
5457
5458 if (framebuffer->getReadBufferState() == GL_NONE)
5459 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005460 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005461 return false;
5462 }
5463
5464 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5465 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5466 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5467 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5468 // situation is an application error that would lead to a crash in ANGLE.
5469 if (readBuffer == nullptr)
5470 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005471 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005472 return false;
5473 }
5474
Martin Radev28031682017-07-28 14:47:56 +03005475 // ANGLE_multiview, Revision 1:
5476 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5477 // current read framebuffer is not NONE.
5478 if (readBuffer->getMultiviewLayout() != GL_NONE)
5479 {
5480 context->handleError(InvalidFramebufferOperation()
5481 << "Attempting to read from a multi-view framebuffer.");
5482 return false;
5483 }
5484
Geoff Lang280ba992017-04-18 16:30:58 -04005485 if (context->getExtensions().webglCompatibility)
5486 {
5487 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5488 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5489 // and type before validating the combination of format and type. However, the
5490 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5491 // verifies that GL_INVALID_OPERATION is generated.
5492 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5493 // dEQP/WebGL.
5494 if (!ValidReadPixelsFormatEnum(context, format))
5495 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005496 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005497 return false;
5498 }
5499
5500 if (!ValidReadPixelsTypeEnum(context, type))
5501 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005502 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005503 return false;
5504 }
5505 }
5506
Jamie Madill4928b7c2017-06-20 12:57:39 -04005507 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5508 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005509 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5510
5511 bool validFormatTypeCombination =
5512 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5513
5514 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5515 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005516 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005517 return false;
5518 }
5519
5520 // Check for pixel pack buffer related API errors
5521 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5522 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5523 {
5524 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005525 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005526 return false;
5527 }
5528
5529 // .. the data would be packed to the buffer object such that the memory writes required
5530 // would exceed the data store size.
5531 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5532 const gl::Extents size(width, height, 1);
5533 const auto &pack = context->getGLState().getPackState();
5534
5535 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5536 if (endByteOrErr.isError())
5537 {
5538 context->handleError(endByteOrErr.getError());
5539 return false;
5540 }
5541
5542 size_t endByte = endByteOrErr.getResult();
5543 if (bufSize >= 0)
5544 {
5545 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5546 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005547 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005548 return false;
5549 }
5550 }
5551
5552 if (pixelPackBuffer != nullptr)
5553 {
5554 CheckedNumeric<size_t> checkedEndByte(endByte);
5555 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5556 checkedEndByte += checkedOffset;
5557
5558 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5559 {
5560 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005561 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005562 return false;
5563 }
5564 }
5565
5566 if (pixelPackBuffer == nullptr && length != nullptr)
5567 {
5568 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5569 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005570 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005571 return false;
5572 }
5573
5574 *length = static_cast<GLsizei>(endByte);
5575 }
5576
5577 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5578 angle::CheckedNumeric<int> clippedExtent(length);
5579 if (start < 0)
5580 {
5581 // "subtract" the area that is less than 0
5582 clippedExtent += start;
5583 }
5584
5585 const int readExtent = start + length;
5586 if (readExtent > bufferSize)
5587 {
5588 // Subtract the region to the right of the read buffer
5589 clippedExtent -= (readExtent - bufferSize);
5590 }
5591
5592 if (!clippedExtent.IsValid())
5593 {
5594 return 0;
5595 }
5596
5597 return std::max(clippedExtent.ValueOrDie(), 0);
5598 };
5599
5600 if (columns != nullptr)
5601 {
5602 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5603 }
5604
5605 if (rows != nullptr)
5606 {
5607 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5608 }
5609
5610 return true;
5611}
5612
5613template <typename ParamType>
5614bool ValidateTexParameterBase(Context *context,
5615 GLenum target,
5616 GLenum pname,
5617 GLsizei bufSize,
5618 const ParamType *params)
5619{
5620 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5621 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005622 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005623 return false;
5624 }
5625
5626 if (context->getTargetTexture(target) == nullptr)
5627 {
5628 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005629 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005630 return false;
5631 }
5632
5633 const GLsizei minBufSize = 1;
5634 if (bufSize >= 0 && bufSize < minBufSize)
5635 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005636 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005637 return false;
5638 }
5639
5640 switch (pname)
5641 {
5642 case GL_TEXTURE_WRAP_R:
5643 case GL_TEXTURE_SWIZZLE_R:
5644 case GL_TEXTURE_SWIZZLE_G:
5645 case GL_TEXTURE_SWIZZLE_B:
5646 case GL_TEXTURE_SWIZZLE_A:
5647 case GL_TEXTURE_BASE_LEVEL:
5648 case GL_TEXTURE_MAX_LEVEL:
5649 case GL_TEXTURE_COMPARE_MODE:
5650 case GL_TEXTURE_COMPARE_FUNC:
5651 case GL_TEXTURE_MIN_LOD:
5652 case GL_TEXTURE_MAX_LOD:
5653 if (context->getClientMajorVersion() < 3)
5654 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005655 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005656 return false;
5657 }
5658 if (target == GL_TEXTURE_EXTERNAL_OES &&
5659 !context->getExtensions().eglImageExternalEssl3)
5660 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005661 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5662 "available without "
5663 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005664 return false;
5665 }
5666 break;
5667
5668 default:
5669 break;
5670 }
5671
JiangYizhou4cff8d62017-07-06 14:54:09 +08005672 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5673 {
5674 switch (pname)
5675 {
5676 case GL_TEXTURE_MIN_FILTER:
5677 case GL_TEXTURE_MAG_FILTER:
5678 case GL_TEXTURE_WRAP_S:
5679 case GL_TEXTURE_WRAP_T:
5680 case GL_TEXTURE_WRAP_R:
5681 case GL_TEXTURE_MIN_LOD:
5682 case GL_TEXTURE_MAX_LOD:
5683 case GL_TEXTURE_COMPARE_MODE:
5684 case GL_TEXTURE_COMPARE_FUNC:
5685 context->handleError(InvalidEnum()
5686 << "Invalid parameter for 2D multisampled textures.");
5687 return false;
5688 }
5689 }
5690
Jamie Madillbe849e42017-05-02 15:49:00 -04005691 switch (pname)
5692 {
5693 case GL_TEXTURE_WRAP_S:
5694 case GL_TEXTURE_WRAP_T:
5695 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005696 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005697 bool restrictedWrapModes =
5698 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5699 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5700 {
5701 return false;
5702 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005703 }
5704 break;
5705
5706 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005707 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005708 bool restrictedMinFilter =
5709 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5710 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5711 {
5712 return false;
5713 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005714 }
5715 break;
5716
5717 case GL_TEXTURE_MAG_FILTER:
5718 if (!ValidateTextureMagFilterValue(context, params))
5719 {
5720 return false;
5721 }
5722 break;
5723
5724 case GL_TEXTURE_USAGE_ANGLE:
5725 switch (ConvertToGLenum(params[0]))
5726 {
5727 case GL_NONE:
5728 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5729 break;
5730
5731 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005732 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005733 return false;
5734 }
5735 break;
5736
5737 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5738 if (!context->getExtensions().textureFilterAnisotropic)
5739 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005740 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005741 return false;
5742 }
5743
5744 // we assume the parameter passed to this validation method is truncated, not rounded
5745 if (params[0] < 1)
5746 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005747 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005748 return false;
5749 }
5750 break;
5751
5752 case GL_TEXTURE_MIN_LOD:
5753 case GL_TEXTURE_MAX_LOD:
5754 // any value is permissible
5755 break;
5756
5757 case GL_TEXTURE_COMPARE_MODE:
5758 if (!ValidateTextureCompareModeValue(context, params))
5759 {
5760 return false;
5761 }
5762 break;
5763
5764 case GL_TEXTURE_COMPARE_FUNC:
5765 if (!ValidateTextureCompareFuncValue(context, params))
5766 {
5767 return false;
5768 }
5769 break;
5770
5771 case GL_TEXTURE_SWIZZLE_R:
5772 case GL_TEXTURE_SWIZZLE_G:
5773 case GL_TEXTURE_SWIZZLE_B:
5774 case GL_TEXTURE_SWIZZLE_A:
5775 switch (ConvertToGLenum(params[0]))
5776 {
5777 case GL_RED:
5778 case GL_GREEN:
5779 case GL_BLUE:
5780 case GL_ALPHA:
5781 case GL_ZERO:
5782 case GL_ONE:
5783 break;
5784
5785 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005786 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005787 return false;
5788 }
5789 break;
5790
5791 case GL_TEXTURE_BASE_LEVEL:
5792 if (params[0] < 0)
5793 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005794 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005795 return false;
5796 }
5797 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5798 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005799 context->handleError(InvalidOperation()
5800 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005801 return false;
5802 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005803 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5804 {
5805 context->handleError(InvalidOperation()
5806 << "Base level must be 0 for multisampled textures.");
5807 return false;
5808 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005809 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5810 {
5811 context->handleError(InvalidOperation()
5812 << "Base level must be 0 for rectangle textures.");
5813 return false;
5814 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005815 break;
5816
5817 case GL_TEXTURE_MAX_LEVEL:
5818 if (params[0] < 0)
5819 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005820 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005821 return false;
5822 }
5823 break;
5824
5825 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5826 if (context->getClientVersion() < Version(3, 1))
5827 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005828 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005829 return false;
5830 }
5831 switch (ConvertToGLenum(params[0]))
5832 {
5833 case GL_DEPTH_COMPONENT:
5834 case GL_STENCIL_INDEX:
5835 break;
5836
5837 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005838 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005839 return false;
5840 }
5841 break;
5842
5843 case GL_TEXTURE_SRGB_DECODE_EXT:
5844 if (!ValidateTextureSRGBDecodeValue(context, params))
5845 {
5846 return false;
5847 }
5848 break;
5849
5850 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005851 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005852 return false;
5853 }
5854
5855 return true;
5856}
5857
5858template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5859template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5860
Jamie Madillc29968b2016-01-20 11:17:23 -05005861} // namespace gl