blob: a878aed419e10bd692e57921d62563b6a789b6c1 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040012#include "libANGLE/Display.h"
Brandon Jones6cad5662017-06-14 13:25:13 -070013#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Framebuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
Geoff Langa8406172015-07-21 16:53:39 -040016#include "libANGLE/Image.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050017#include "libANGLE/Program.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Query.h"
19#include "libANGLE/Texture.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/TransformFeedback.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040021#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050022#include "libANGLE/VertexArray.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040023#include "libANGLE/formatutils.h"
24#include "libANGLE/validationES2.h"
25#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040026
27#include "common/mathutil.h"
28#include "common/utilities.h"
29
Jamie Madille2e406c2016-06-02 13:04:10 -040030using namespace angle;
31
Geoff Lange8ebe7f2013-08-05 15:03:13 -040032namespace gl
33{
Jamie Madill1ca74672015-07-21 15:14:11 -040034namespace
35{
Corentin Wallez92db6942016-12-09 13:10:36 -050036bool ValidateDrawAttribs(ValidationContext *context,
37 GLint primcount,
38 GLint maxVertex,
39 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040040{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070041 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040042 const gl::Program *program = state.getProgram();
43
Corentin Wallez327411e2016-12-09 11:09:17 -050044 bool webglCompatibility = context->getExtensions().webglCompatibility;
45
Jamie Madill231c7f52017-04-26 13:45:37 -040046 const VertexArray *vao = state.getVertexArray();
47 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080048 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madill231c7f52017-04-26 13:45:37 -040049 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040050 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
51 {
52 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallez672f7f32017-06-15 17:42:17 -040053
54 // No need to range check for disabled attribs.
55 if (!attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040056 {
Corentin Wallezfd456442016-12-21 17:57:00 -050057 continue;
58 }
Jamie Madill1ca74672015-07-21 15:14:11 -040059
Jamie Madill231c7f52017-04-26 13:45:37 -040060 // If we have no buffer, then we either get an error, or there are no more checks to be
61 // done.
Corentin Wallez672f7f32017-06-15 17:42:17 -040062 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
63 gl::Buffer *buffer = binding.getBuffer().get();
Corentin Wallezfd456442016-12-21 17:57:00 -050064 if (!buffer)
65 {
Geoff Langfeb8c682017-02-13 16:07:35 -050066 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -050067 {
68 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050069 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
70 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
71 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
72 // error.
Brandon Jonesafa75152017-07-21 13:11:29 -070073 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
Corentin Wallezfd456442016-12-21 17:57:00 -050074 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050075 }
Corentin Wallezfd456442016-12-21 17:57:00 -050076 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040077 {
78 // This is an application error that would normally result in a crash,
79 // but we catch it and return an error
Brandon Jonesafa75152017-07-21 13:11:29 -070080 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
Jamie Madill1ca74672015-07-21 15:14:11 -040081 return false;
82 }
Corentin Wallezfd456442016-12-21 17:57:00 -050083 continue;
84 }
85
Corentin Wallez672f7f32017-06-15 17:42:17 -040086 // This needs to come after the check for client arrays as even unused attributes cannot use
87 // client-side arrays
88 if (!program->isAttribLocationActive(attributeIndex))
89 {
90 continue;
91 }
92
Corentin Wallezfd456442016-12-21 17:57:00 -050093 // If we're drawing zero vertices, we have enough data.
94 if (vertexCount <= 0 || primcount <= 0)
95 {
96 continue;
97 }
98
99 GLint maxVertexElement = 0;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300100 GLuint divisor = binding.getDivisor();
101 if (divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500102 {
103 maxVertexElement = maxVertex;
104 }
105 else
106 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300107 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500108 }
109
110 // We do manual overflow checks here instead of using safe_math.h because it was
111 // a bottleneck. Thanks to some properties of GL we know inequalities that can
112 // help us make the overflow checks faster.
113
114 // The max possible attribSize is 16 for a vector of 4 32 bit values.
115 constexpr uint64_t kMaxAttribSize = 16;
116 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
117 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
118
119 // We know attribStride is given as a GLsizei which is typedefed to int.
120 // We also know an upper bound for attribSize.
121 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800122 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500123 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
124 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
125
126 // Computing the max offset using uint64_t without attrib.offset is overflow
127 // safe. Note: Last vertex element does not take the full stride!
128 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
129 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
130
131 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800132 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
133 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500134 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700135 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500136 return false;
137 }
138 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
139
140 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
141 // We can return INVALID_OPERATION if our vertex attribute does not have
142 // enough backing data.
143 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
144 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700145 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500146 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400147 }
148 }
149
150 return true;
151}
152
Geoff Lang280ba992017-04-18 16:30:58 -0400153bool ValidReadPixelsTypeEnum(ValidationContext *context, GLenum type)
154{
155 switch (type)
156 {
157 // Types referenced in Table 3.4 of the ES 2.0.25 spec
158 case GL_UNSIGNED_BYTE:
159 case GL_UNSIGNED_SHORT_4_4_4_4:
160 case GL_UNSIGNED_SHORT_5_5_5_1:
161 case GL_UNSIGNED_SHORT_5_6_5:
162 return context->getClientVersion() >= ES_2_0;
163
164 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
165 case GL_BYTE:
166 case GL_INT:
167 case GL_SHORT:
168 case GL_UNSIGNED_INT:
169 case GL_UNSIGNED_INT_10F_11F_11F_REV:
170 case GL_UNSIGNED_INT_24_8:
171 case GL_UNSIGNED_INT_2_10_10_10_REV:
172 case GL_UNSIGNED_INT_5_9_9_9_REV:
173 case GL_UNSIGNED_SHORT:
174 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
175 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
176 return context->getClientVersion() >= ES_3_0;
177
178 case GL_FLOAT:
179 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat;
180
181 case GL_HALF_FLOAT:
182 return context->getClientVersion() >= ES_3_0 ||
183 context->getExtensions().textureHalfFloat;
184
185 case GL_HALF_FLOAT_OES:
186 return context->getExtensions().colorBufferHalfFloat;
187
188 default:
189 return false;
190 }
191}
192
193bool ValidReadPixelsFormatEnum(ValidationContext *context, GLenum format)
194{
195 switch (format)
196 {
197 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
198 case GL_RGBA:
199 case GL_RGB:
200 case GL_ALPHA:
201 return context->getClientVersion() >= ES_2_0;
202
203 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
204 case GL_RG:
205 case GL_RED:
206 case GL_RGBA_INTEGER:
207 case GL_RGB_INTEGER:
208 case GL_RG_INTEGER:
209 case GL_RED_INTEGER:
210 return context->getClientVersion() >= ES_3_0;
211
212 case GL_SRGB_ALPHA_EXT:
213 case GL_SRGB_EXT:
214 return context->getExtensions().sRGB;
215
216 case GL_BGRA_EXT:
217 return context->getExtensions().readFormatBGRA;
218
219 default:
220 return false;
221 }
222}
223
Geoff Langf607c602016-09-21 11:46:48 -0400224bool ValidReadPixelsFormatType(ValidationContext *context,
225 GLenum framebufferComponentType,
226 GLenum format,
227 GLenum type)
228{
229 switch (framebufferComponentType)
230 {
231 case GL_UNSIGNED_NORMALIZED:
232 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
233 // ReadPixels with BGRA even if the extension is not present
234 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
235 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
236 type == GL_UNSIGNED_BYTE);
237
238 case GL_SIGNED_NORMALIZED:
239 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
240
241 case GL_INT:
242 return (format == GL_RGBA_INTEGER && type == GL_INT);
243
244 case GL_UNSIGNED_INT:
245 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
246
247 case GL_FLOAT:
248 return (format == GL_RGBA && type == GL_FLOAT);
249
250 default:
251 UNREACHABLE();
252 return false;
253 }
254}
255
Geoff Langc1984ed2016-10-07 12:41:00 -0400256template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400257bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400258{
259 switch (ConvertToGLenum(params[0]))
260 {
261 case GL_CLAMP_TO_EDGE:
262 break;
263
264 case GL_REPEAT:
265 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400266 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400267 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400268 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700269 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400270 return false;
271 }
272 break;
273
274 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700275 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400276 return false;
277 }
278
279 return true;
280}
281
282template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400283bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400284{
285 switch (ConvertToGLenum(params[0]))
286 {
287 case GL_NEAREST:
288 case GL_LINEAR:
289 break;
290
291 case GL_NEAREST_MIPMAP_NEAREST:
292 case GL_LINEAR_MIPMAP_NEAREST:
293 case GL_NEAREST_MIPMAP_LINEAR:
294 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400295 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400296 {
297 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700298 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400299 return false;
300 }
301 break;
302
303 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700304 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400305 return false;
306 }
307
308 return true;
309}
310
311template <typename ParamType>
312bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
313{
314 switch (ConvertToGLenum(params[0]))
315 {
316 case GL_NEAREST:
317 case GL_LINEAR:
318 break;
319
320 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700321 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400322 return false;
323 }
324
325 return true;
326}
327
328template <typename ParamType>
329bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
330{
331 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
332 switch (ConvertToGLenum(params[0]))
333 {
334 case GL_NONE:
335 case GL_COMPARE_REF_TO_TEXTURE:
336 break;
337
338 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700339 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400340 return false;
341 }
342
343 return true;
344}
345
346template <typename ParamType>
347bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
348{
349 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
350 switch (ConvertToGLenum(params[0]))
351 {
352 case GL_LEQUAL:
353 case GL_GEQUAL:
354 case GL_LESS:
355 case GL_GREATER:
356 case GL_EQUAL:
357 case GL_NOTEQUAL:
358 case GL_ALWAYS:
359 case GL_NEVER:
360 break;
361
362 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700363 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400364 return false;
365 }
366
367 return true;
368}
369
370template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700371bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
372{
373 if (!context->getExtensions().textureSRGBDecode)
374 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700375 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700376 return false;
377 }
378
379 switch (ConvertToGLenum(params[0]))
380 {
381 case GL_DECODE_EXT:
382 case GL_SKIP_DECODE_EXT:
383 break;
384
385 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700386 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700387 return false;
388 }
389
390 return true;
391}
392
393template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400394bool ValidateSamplerParameterBase(Context *context,
395 GLuint sampler,
396 GLenum pname,
397 GLsizei bufSize,
398 ParamType *params)
399{
400 if (context->getClientMajorVersion() < 3)
401 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700402 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc1984ed2016-10-07 12:41:00 -0400403 return false;
404 }
405
406 if (!context->isSampler(sampler))
407 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700408 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
Geoff Langc1984ed2016-10-07 12:41:00 -0400409 return false;
410 }
411
412 const GLsizei minBufSize = 1;
413 if (bufSize >= 0 && bufSize < minBufSize)
414 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700415 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langc1984ed2016-10-07 12:41:00 -0400416 return false;
417 }
418
419 switch (pname)
420 {
421 case GL_TEXTURE_WRAP_S:
422 case GL_TEXTURE_WRAP_T:
423 case GL_TEXTURE_WRAP_R:
424 if (!ValidateTextureWrapModeValue(context, params, false))
425 {
426 return false;
427 }
428 break;
429
430 case GL_TEXTURE_MIN_FILTER:
431 if (!ValidateTextureMinFilterValue(context, params, false))
432 {
433 return false;
434 }
435 break;
436
437 case GL_TEXTURE_MAG_FILTER:
438 if (!ValidateTextureMagFilterValue(context, params))
439 {
440 return false;
441 }
442 break;
443
444 case GL_TEXTURE_MIN_LOD:
445 case GL_TEXTURE_MAX_LOD:
446 // any value is permissible
447 break;
448
449 case GL_TEXTURE_COMPARE_MODE:
450 if (!ValidateTextureCompareModeValue(context, params))
451 {
452 return false;
453 }
454 break;
455
456 case GL_TEXTURE_COMPARE_FUNC:
457 if (!ValidateTextureCompareFuncValue(context, params))
458 {
459 return false;
460 }
461 break;
462
Geoff Lang81c6b572016-10-19 14:07:52 -0700463 case GL_TEXTURE_SRGB_DECODE_EXT:
464 if (!ValidateTextureSRGBDecodeValue(context, params))
465 {
466 return false;
467 }
468 break;
469
Geoff Langc1984ed2016-10-07 12:41:00 -0400470 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700471 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langc1984ed2016-10-07 12:41:00 -0400472 return false;
473 }
474
475 return true;
476}
477
478bool ValidateGetSamplerParameterBase(Context *context,
479 GLuint sampler,
480 GLenum pname,
481 GLsizei *length)
482{
483 if (length)
484 {
485 *length = 0;
486 }
487
488 if (context->getClientMajorVersion() < 3)
489 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700490 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc1984ed2016-10-07 12:41:00 -0400491 return false;
492 }
493
494 if (!context->isSampler(sampler))
495 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700496 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
Geoff Langc1984ed2016-10-07 12:41:00 -0400497 return false;
498 }
499
500 switch (pname)
501 {
502 case GL_TEXTURE_WRAP_S:
503 case GL_TEXTURE_WRAP_T:
504 case GL_TEXTURE_WRAP_R:
505 case GL_TEXTURE_MIN_FILTER:
506 case GL_TEXTURE_MAG_FILTER:
507 case GL_TEXTURE_MIN_LOD:
508 case GL_TEXTURE_MAX_LOD:
509 case GL_TEXTURE_COMPARE_MODE:
510 case GL_TEXTURE_COMPARE_FUNC:
511 break;
512
Geoff Lang81c6b572016-10-19 14:07:52 -0700513 case GL_TEXTURE_SRGB_DECODE_EXT:
514 if (!context->getExtensions().textureSRGBDecode)
515 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500516 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Geoff Lang81c6b572016-10-19 14:07:52 -0700517 return false;
518 }
519 break;
520
Geoff Langc1984ed2016-10-07 12:41:00 -0400521 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700522 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langc1984ed2016-10-07 12:41:00 -0400523 return false;
524 }
525
526 if (length)
527 {
528 *length = 1;
529 }
530 return true;
531}
532
Geoff Lang6899b872016-10-14 11:30:13 -0400533bool ValidateGetActiveUniformBlockivBase(Context *context,
534 GLuint program,
535 GLuint uniformBlockIndex,
536 GLenum pname,
537 GLsizei *length)
538{
539 if (length)
540 {
541 *length = 0;
542 }
543
544 if (context->getClientMajorVersion() < 3)
545 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500546 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Lang6899b872016-10-14 11:30:13 -0400547 return false;
548 }
549
550 Program *programObject = GetValidProgram(context, program);
551 if (!programObject)
552 {
553 return false;
554 }
555
556 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
557 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500558 context->handleError(InvalidValue()
559 << "uniformBlockIndex exceeds active uniform block count.");
Geoff Lang6899b872016-10-14 11:30:13 -0400560 return false;
561 }
562
563 switch (pname)
564 {
565 case GL_UNIFORM_BLOCK_BINDING:
566 case GL_UNIFORM_BLOCK_DATA_SIZE:
567 case GL_UNIFORM_BLOCK_NAME_LENGTH:
568 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
569 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
570 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
571 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
572 break;
573
574 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700575 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang6899b872016-10-14 11:30:13 -0400576 return false;
577 }
578
579 if (length)
580 {
581 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
582 {
583 const UniformBlock &uniformBlock =
584 programObject->getUniformBlockByIndex(uniformBlockIndex);
jchen10eaef1e52017-06-13 10:44:11 +0800585 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
Geoff Lang6899b872016-10-14 11:30:13 -0400586 }
587 else
588 {
589 *length = 1;
590 }
591 }
592
593 return true;
594}
595
Geoff Lang0a9661f2016-10-20 10:59:20 -0700596bool ValidateGetInternalFormativBase(Context *context,
597 GLenum target,
598 GLenum internalformat,
599 GLenum pname,
600 GLsizei bufSize,
601 GLsizei *numParams)
602{
603 if (numParams)
604 {
605 *numParams = 0;
606 }
607
608 if (context->getClientMajorVersion() < 3)
609 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500610 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700611 return false;
612 }
613
614 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
615 if (!formatCaps.renderable)
616 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500617 context->handleError(InvalidEnum() << "Internal format is not renderable.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700618 return false;
619 }
620
621 switch (target)
622 {
623 case GL_RENDERBUFFER:
624 break;
625
JiangYizhoubddc46b2016-12-09 09:50:51 +0800626 case GL_TEXTURE_2D_MULTISAMPLE:
627 if (context->getClientVersion() < ES_3_1)
628 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500629 context->handleError(InvalidOperation()
630 << "Texture target requires at least OpenGL ES 3.1.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800631 return false;
632 }
633 break;
634
Geoff Lang0a9661f2016-10-20 10:59:20 -0700635 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700636 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
Geoff Lang0a9661f2016-10-20 10:59:20 -0700637 return false;
638 }
639
640 if (bufSize < 0)
641 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700642 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
Geoff Lang0a9661f2016-10-20 10:59:20 -0700643 return false;
644 }
645
646 GLsizei maxWriteParams = 0;
647 switch (pname)
648 {
649 case GL_NUM_SAMPLE_COUNTS:
650 maxWriteParams = 1;
651 break;
652
653 case GL_SAMPLES:
654 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
655 break;
656
657 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700658 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang0a9661f2016-10-20 10:59:20 -0700659 return false;
660 }
661
662 if (numParams)
663 {
664 // glGetInternalFormativ will not overflow bufSize
665 *numParams = std::min(bufSize, maxWriteParams);
666 }
667
668 return true;
669}
670
Jamie Madillc1d770e2017-04-13 17:31:24 -0400671bool ValidateUniformCommonBase(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500672 gl::Program *program,
673 GLint location,
674 GLsizei count,
675 const LinkedUniform **uniformOut)
676{
677 // TODO(Jiajia): Add image uniform check in future.
678 if (count < 0)
679 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700680 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500681 return false;
682 }
683
Brandon Jones6cad5662017-06-14 13:25:13 -0700684 if (!program)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500685 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700686 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
687 return false;
688 }
689
690 if (!program->isLinked())
691 {
692 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500693 return false;
694 }
695
696 if (location == -1)
697 {
698 // Silently ignore the uniform command
699 return false;
700 }
701
702 const auto &uniformLocations = program->getUniformLocations();
Jamie Madillbe849e42017-05-02 15:49:00 -0400703 size_t castedLocation = static_cast<size_t>(location);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500704 if (castedLocation >= uniformLocations.size())
705 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500706 context->handleError(InvalidOperation() << "Invalid uniform location");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500707 return false;
708 }
709
710 const auto &uniformLocation = uniformLocations[castedLocation];
711 if (uniformLocation.ignored)
712 {
713 // Silently ignore the uniform command
714 return false;
715 }
716
717 if (!uniformLocation.used)
718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500719 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500720 return false;
721 }
722
723 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
724
725 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
726 if (!uniform.isArray() && count > 1)
727 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500728 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500729 return false;
730 }
731
732 *uniformOut = &uniform;
733 return true;
734}
735
Frank Henigman999b0fd2017-02-02 21:45:55 -0500736bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -0500737 GLenum uniformType,
738 GLsizei count,
739 const GLint *value)
740{
741 // Value type is GL_INT, because we only get here from glUniform1i{v}.
742 // It is compatible with INT or BOOL.
743 // Do these cheap tests first, for a little extra speed.
744 if (GL_INT == uniformType || GL_BOOL == uniformType)
745 {
746 return true;
747 }
748
749 if (IsSamplerType(uniformType))
750 {
Frank Henigman999b0fd2017-02-02 21:45:55 -0500751 // Check that the values are in range.
752 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
753 for (GLsizei i = 0; i < count; ++i)
754 {
755 if (value[i] < 0 || value[i] >= max)
756 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500757 context->handleError(InvalidValue() << "sampler uniform value out of range");
Frank Henigman999b0fd2017-02-02 21:45:55 -0500758 return false;
759 }
760 }
Frank Henigmana98a6472017-02-02 21:38:32 -0500761 return true;
762 }
763
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500764 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmana98a6472017-02-02 21:38:32 -0500765 return false;
766}
767
Jamie Madillc1d770e2017-04-13 17:31:24 -0400768bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500769{
770 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -0500771 // Do the cheaper test first, for a little extra speed.
772 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500773 {
774 return true;
775 }
776
Brandon Jonesafa75152017-07-21 13:11:29 -0700777 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500778 return false;
779}
780
Jamie Madillc1d770e2017-04-13 17:31:24 -0400781bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500782{
783 // Check that the value type is compatible with uniform type.
784 if (valueType == uniformType)
785 {
786 return true;
787 }
788
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500789 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500790 return false;
791}
792
Geoff Lange0cff192017-05-30 13:04:56 -0400793bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
794{
795 const Program *program = context->getGLState().getProgram();
796 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
797
798 const auto &programOutputTypes = program->getOutputVariableTypes();
799 for (size_t drawBufferIdx = 0; drawBufferIdx < programOutputTypes.size(); drawBufferIdx++)
800 {
801 GLenum outputType = programOutputTypes[drawBufferIdx];
802 GLenum inputType = framebuffer->getDrawbufferWriteType(drawBufferIdx);
803 if (outputType != GL_NONE && inputType != GL_NONE && inputType != outputType)
804 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500805 context->handleError(InvalidOperation() << "Fragment shader output type does not "
806 "match the bound framebuffer attachment "
807 "type.");
Geoff Lange0cff192017-05-30 13:04:56 -0400808 return false;
809 }
810 }
811
812 return true;
813}
814
Geoff Lang9ab5b822017-05-30 16:19:23 -0400815bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
816{
817 const Program *program = context->getGLState().getProgram();
818 const VertexArray *vao = context->getGLState().getVertexArray();
819
820 for (const auto &shaderAttribute : program->getAttributes())
821 {
Geoff Lang69df2422017-07-05 12:42:31 -0400822 // gl_VertexID and gl_InstanceID are active attributes but don't have a bound attribute.
823 if (shaderAttribute.isBuiltIn())
824 {
825 continue;
826 }
827
Geoff Lang9ab5b822017-05-30 16:19:23 -0400828 GLenum shaderInputType = VariableComponentType(shaderAttribute.type);
829
830 const auto &attrib = vao->getVertexAttribute(shaderAttribute.location);
831 const auto &currentValue =
832 context->getGLState().getVertexAttribCurrentValue(shaderAttribute.location);
833 GLenum vertexType = attrib.enabled ? GetVertexAttributeBaseType(attrib) : currentValue.Type;
834
835 if (shaderInputType != GL_NONE && vertexType != GL_NONE && shaderInputType != vertexType)
836 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500837 context->handleError(InvalidOperation() << "Vertex shader input type does not "
838 "match the type of the bound vertex "
839 "attribute.");
Geoff Lang9ab5b822017-05-30 16:19:23 -0400840 return false;
841 }
842 }
843
844 return true;
845}
846
Geoff Langf41a7152016-09-19 15:11:17 -0400847} // anonymous namespace
848
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500849bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400850{
Jamie Madilld7460c72014-01-21 16:38:14 -0500851 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400852 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800853 case GL_TEXTURE_2D:
854 case GL_TEXTURE_CUBE_MAP:
855 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400856
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400857 case GL_TEXTURE_RECTANGLE_ANGLE:
858 return context->getExtensions().textureRectangle;
859
He Yunchaoced53ae2016-11-29 15:00:51 +0800860 case GL_TEXTURE_3D:
861 case GL_TEXTURE_2D_ARRAY:
862 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500863
He Yunchaoced53ae2016-11-29 15:00:51 +0800864 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800865 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400866
He Yunchaoced53ae2016-11-29 15:00:51 +0800867 default:
868 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500869 }
Jamie Madill35d15012013-10-07 10:46:37 -0400870}
871
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500872bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
873{
874 switch (target)
875 {
876 case GL_TEXTURE_2D:
877 case GL_TEXTURE_CUBE_MAP:
878 return true;
879
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400880 case GL_TEXTURE_RECTANGLE_ANGLE:
881 return context->getExtensions().textureRectangle;
882
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500883 default:
884 return false;
885 }
886}
887
888bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
889{
890 switch (target)
891 {
892 case GL_TEXTURE_3D:
893 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300894 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500895
896 default:
897 return false;
898 }
899}
900
Ian Ewellbda75592016-04-18 17:25:54 -0400901// Most texture GL calls are not compatible with external textures, so we have a separate validation
902// function for use in the GL calls that do
903bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
904{
905 return (target == GL_TEXTURE_EXTERNAL_OES) &&
906 (context->getExtensions().eglImageExternal ||
907 context->getExtensions().eglStreamConsumerExternal);
908}
909
Shannon Woods4dfed832014-03-17 20:03:39 -0400910// This function differs from ValidTextureTarget in that the target must be
911// usable as the destination of a 2D operation-- so a cube face is valid, but
912// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400913// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500914bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400915{
916 switch (target)
917 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800918 case GL_TEXTURE_2D:
919 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
920 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
921 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
922 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
923 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
924 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
925 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400926 case GL_TEXTURE_RECTANGLE_ANGLE:
927 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800928 default:
929 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500930 }
931}
932
Jamie Madillbe849e42017-05-02 15:49:00 -0400933bool ValidateDrawElementsInstancedBase(ValidationContext *context,
934 GLenum mode,
935 GLsizei count,
936 GLenum type,
937 const GLvoid *indices,
938 GLsizei primcount)
939{
940 if (primcount < 0)
941 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700942 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400943 return false;
944 }
945
946 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
947 {
948 return false;
949 }
950
951 // No-op zero primitive count
952 return (primcount > 0);
953}
954
955bool ValidateDrawArraysInstancedBase(Context *context,
956 GLenum mode,
957 GLint first,
958 GLsizei count,
959 GLsizei primcount)
960{
961 if (primcount < 0)
962 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700963 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400964 return false;
965 }
966
967 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
968 {
969 return false;
970 }
971
972 // No-op if zero primitive count
973 return (primcount > 0);
974}
975
Corentin Wallez0dc97812017-06-22 14:38:44 -0400976bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400977{
978 // Verify there is at least one active attribute with a divisor of zero
979 const State &state = context->getGLState();
980
981 Program *program = state.getProgram();
982
983 const auto &attribs = state.getVertexArray()->getVertexAttributes();
984 const auto &bindings = state.getVertexArray()->getVertexBindings();
985 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
986 {
987 const VertexAttribute &attrib = attribs[attributeIndex];
988 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300989 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400990 {
991 return true;
992 }
993 }
994
Brandon Jonesafa75152017-07-21 13:11:29 -0700995 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400996 return false;
997}
998
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500999bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1000{
1001 switch (target)
1002 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001003 case GL_TEXTURE_3D:
1004 case GL_TEXTURE_2D_ARRAY:
1005 return true;
1006 default:
1007 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001008 }
1009}
1010
He Yunchao11b038b2016-11-22 21:24:04 +08001011bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
1012{
1013 switch (target)
1014 {
1015 case GL_TEXTURE_2D:
1016 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1017 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1018 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1019 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1020 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1021 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1022 case GL_TEXTURE_3D:
1023 case GL_TEXTURE_2D_ARRAY:
1024 case GL_TEXTURE_2D_MULTISAMPLE:
1025 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001026 case GL_TEXTURE_RECTANGLE_ANGLE:
1027 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +08001028 default:
1029 return false;
1030 }
1031}
1032
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001033bool ValidFramebufferTarget(GLenum target)
1034{
He Yunchaoced53ae2016-11-29 15:00:51 +08001035 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1036 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001037 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001038
1039 switch (target)
1040 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001041 case GL_FRAMEBUFFER:
1042 return true;
1043 case GL_READ_FRAMEBUFFER:
1044 return true;
1045 case GL_DRAW_FRAMEBUFFER:
1046 return true;
1047 default:
1048 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001049 }
1050}
1051
Jamie Madill29639852016-09-02 15:00:09 -04001052bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001053{
1054 switch (target)
1055 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001056 case GL_ARRAY_BUFFER:
1057 case GL_ELEMENT_ARRAY_BUFFER:
1058 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001059
He Yunchaoced53ae2016-11-29 15:00:51 +08001060 case GL_PIXEL_PACK_BUFFER:
1061 case GL_PIXEL_UNPACK_BUFFER:
1062 return (context->getExtensions().pixelBufferObject ||
1063 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001064
He Yunchaoced53ae2016-11-29 15:00:51 +08001065 case GL_COPY_READ_BUFFER:
1066 case GL_COPY_WRITE_BUFFER:
1067 case GL_TRANSFORM_FEEDBACK_BUFFER:
1068 case GL_UNIFORM_BUFFER:
1069 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001070
He Yunchaoced53ae2016-11-29 15:00:51 +08001071 case GL_ATOMIC_COUNTER_BUFFER:
1072 case GL_SHADER_STORAGE_BUFFER:
1073 case GL_DRAW_INDIRECT_BUFFER:
1074 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001075 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001076
He Yunchaoced53ae2016-11-29 15:00:51 +08001077 default:
1078 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001079 }
1080}
1081
Jamie Madillc29968b2016-01-20 11:17:23 -05001082bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001083{
Jamie Madillc29968b2016-01-20 11:17:23 -05001084 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001085 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001086 switch (target)
1087 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001088 case GL_TEXTURE_2D:
1089 maxDimension = caps.max2DTextureSize;
1090 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001091 case GL_TEXTURE_CUBE_MAP:
1092 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1093 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1094 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1095 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1096 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1097 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1098 maxDimension = caps.maxCubeMapTextureSize;
1099 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001100 case GL_TEXTURE_RECTANGLE_ANGLE:
1101 return level == 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08001102 case GL_TEXTURE_3D:
1103 maxDimension = caps.max3DTextureSize;
1104 break;
1105 case GL_TEXTURE_2D_ARRAY:
1106 maxDimension = caps.max2DTextureSize;
1107 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001108 case GL_TEXTURE_2D_MULTISAMPLE:
1109 maxDimension = caps.max2DTextureSize;
1110 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001111 default:
1112 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001113 }
1114
Brandon Jones6cad5662017-06-14 13:25:13 -07001115 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -04001116}
1117
Brandon Jones6cad5662017-06-14 13:25:13 -07001118bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001119 GLenum target,
1120 GLint level,
1121 GLsizei width,
1122 GLsizei height,
1123 GLsizei depth,
1124 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001125{
Brandon Jones6cad5662017-06-14 13:25:13 -07001126 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -04001127 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001128 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -04001129 return false;
1130 }
Austin Kinross08528e12015-10-07 16:24:40 -07001131 // TexSubImage parameters can be NPOT without textureNPOT extension,
1132 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001133 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001134 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001135 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001136 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001137 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001138 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -04001139 return false;
1140 }
1141
1142 if (!ValidMipLevel(context, target, level))
1143 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001144 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -04001145 return false;
1146 }
1147
1148 return true;
1149}
1150
Geoff Lang0d8b7242015-09-09 14:56:53 -04001151bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1152{
1153 // List of compressed format that require that the texture size is smaller than or a multiple of
1154 // the compressed block size.
1155 switch (internalFormat)
1156 {
1157 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1158 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1159 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1160 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langfff7a7d2017-06-02 10:39:17 -04001161 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
1162 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
1163 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
1164 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
Minmin Gonge3939b92015-12-01 15:36:51 -08001165 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001166 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1167 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1168 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1169 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1170 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
1171 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001172 return true;
1173
1174 default:
1175 return false;
1176 }
1177}
1178
Geoff Lang966c9402017-04-18 12:38:27 -04001179bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
1180{
1181 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
1182 (size % blockSize == 0);
1183}
1184
Jamie Madillc29968b2016-01-20 11:17:23 -05001185bool ValidCompressedImageSize(const ValidationContext *context,
1186 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -04001187 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -05001188 GLsizei width,
1189 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001190{
Geoff Langca271392017-04-05 12:30:00 -04001191 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -04001192 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001193 {
1194 return false;
1195 }
1196
Geoff Lang966c9402017-04-18 12:38:27 -04001197 if (width < 0 || height < 0)
1198 {
1199 return false;
1200 }
1201
1202 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1203 {
1204 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
1205 // block size for level 0 but WebGL disallows this.
1206 bool smallerThanBlockSizeAllowed =
1207 level > 0 || !context->getExtensions().webglCompatibility;
1208
1209 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
1210 smallerThanBlockSizeAllowed) ||
1211 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
1212 smallerThanBlockSizeAllowed))
1213 {
1214 return false;
1215 }
1216 }
1217
1218 return true;
1219}
1220
1221bool ValidCompressedSubImageSize(const ValidationContext *context,
1222 GLenum internalFormat,
1223 GLint xoffset,
1224 GLint yoffset,
1225 GLsizei width,
1226 GLsizei height,
1227 size_t textureWidth,
1228 size_t textureHeight)
1229{
1230 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
1231 if (!formatInfo.compressed)
1232 {
1233 return false;
1234 }
1235
Geoff Lang44ff5a72017-02-03 15:15:43 -05001236 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001237 {
1238 return false;
1239 }
1240
Geoff Lang0d8b7242015-09-09 14:56:53 -04001241 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1242 {
Geoff Lang44ff5a72017-02-03 15:15:43 -05001243 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -04001244 yoffset % formatInfo.compressedBlockHeight != 0)
1245 {
1246 return false;
1247 }
1248
1249 // Allowed to either have data that is a multiple of block size or is smaller than the block
1250 // size but fills the entire mip
1251 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
1252 static_cast<size_t>(width) == textureWidth &&
1253 static_cast<size_t>(height) == textureHeight;
1254 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
1255 (height % formatInfo.compressedBlockHeight) == 0;
1256 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -04001257 {
1258 return false;
1259 }
1260 }
1261
Geoff Langd4f180b2013-09-24 13:57:44 -04001262 return true;
1263}
1264
Geoff Langff5b2d52016-09-07 11:32:23 -04001265bool ValidImageDataSize(ValidationContext *context,
1266 GLenum textureTarget,
1267 GLsizei width,
1268 GLsizei height,
1269 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -04001270 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -04001271 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001272 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001273 GLsizei imageSize)
1274{
1275 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1276 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1277 {
1278 // Checks are not required
1279 return true;
1280 }
1281
1282 // ...the data would be unpacked from the buffer object such that the memory reads required
1283 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -04001284 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
1285 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -04001286 const gl::Extents size(width, height, depth);
1287 const auto &unpack = context->getGLState().getUnpackState();
1288
1289 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1290 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1291 if (endByteOrErr.isError())
1292 {
1293 context->handleError(endByteOrErr.getError());
1294 return false;
1295 }
1296
1297 GLuint endByte = endByteOrErr.getResult();
1298
1299 if (pixelUnpackBuffer)
1300 {
1301 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1302 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1303 checkedEndByte += checkedOffset;
1304
1305 if (!checkedEndByte.IsValid() ||
1306 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1307 {
1308 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001309 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04001310 return false;
1311 }
1312 }
1313 else
1314 {
1315 ASSERT(imageSize >= 0);
1316 if (pixels == nullptr && imageSize != 0)
1317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001318 context->handleError(InvalidOperation()
1319 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001320 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001321 }
1322
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001323 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001324 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001325 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001326 return false;
1327 }
1328 }
1329
1330 return true;
1331}
1332
Geoff Lang37dde692014-01-31 16:34:54 -05001333bool ValidQueryType(const Context *context, GLenum queryType)
1334{
He Yunchaoced53ae2016-11-29 15:00:51 +08001335 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1336 "GL extension enums not equal.");
1337 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1338 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001339
1340 switch (queryType)
1341 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001342 case GL_ANY_SAMPLES_PASSED:
1343 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1344 return true;
1345 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1346 return (context->getClientMajorVersion() >= 3);
1347 case GL_TIME_ELAPSED_EXT:
1348 return context->getExtensions().disjointTimerQuery;
1349 case GL_COMMANDS_COMPLETED_CHROMIUM:
1350 return context->getExtensions().syncQuery;
1351 default:
1352 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001353 }
1354}
1355
Geoff Lang2d62ab72017-03-23 16:54:40 -04001356bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
1357 GLenum type,
1358 GLboolean normalized,
1359 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001360 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001361 bool pureInteger)
1362{
1363 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001364 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1365 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1366 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1367 // parameter exceeds 255.
1368 constexpr GLsizei kMaxWebGLStride = 255;
1369 if (stride > kMaxWebGLStride)
1370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001371 context->handleError(InvalidValue()
1372 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001373 return false;
1374 }
1375
1376 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1377 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1378 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1379 // or an INVALID_OPERATION error is generated.
1380 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1381 size_t typeSize = GetVertexFormatTypeSize(internalType);
1382
1383 ASSERT(isPow2(typeSize) && typeSize > 0);
1384 size_t sizeMask = (typeSize - 1);
1385 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1386 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001387 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001388 return false;
1389 }
1390
1391 if ((stride & sizeMask) != 0)
1392 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001393 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001394 return false;
1395 }
1396
1397 return true;
1398}
1399
Jamie Madillef300b12016-10-07 15:12:09 -04001400Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001401{
He Yunchaoced53ae2016-11-29 15:00:51 +08001402 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1403 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1404 // or program object and INVALID_OPERATION if the provided name identifies an object
1405 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001406
Dian Xiang769769a2015-09-09 15:20:08 -07001407 Program *validProgram = context->getProgram(id);
1408
1409 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001410 {
Dian Xiang769769a2015-09-09 15:20:08 -07001411 if (context->getShader(id))
1412 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001413 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001414 }
1415 else
1416 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001417 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001418 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001419 }
Dian Xiang769769a2015-09-09 15:20:08 -07001420
1421 return validProgram;
1422}
1423
Jamie Madillef300b12016-10-07 15:12:09 -04001424Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001425{
1426 // See ValidProgram for spec details.
1427
1428 Shader *validShader = context->getShader(id);
1429
1430 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001431 {
Dian Xiang769769a2015-09-09 15:20:08 -07001432 if (context->getProgram(id))
1433 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001434 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001435 }
1436 else
1437 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001438 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001439 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001440 }
Dian Xiang769769a2015-09-09 15:20:08 -07001441
1442 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001443}
1444
Geoff Langb1196682014-07-23 13:47:29 -04001445bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001446{
1447 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1448 {
1449 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1450
Geoff Langaae65a42014-05-26 12:43:44 -04001451 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001452 {
Martin Radevd178aa42017-07-13 14:03:22 +03001453 context->handleError(
1454 InvalidOperation()
1455 << "attachment index cannot be greater or equal to MAX_COLOR_ATTACHMENTS.");
Geoff Langb1196682014-07-23 13:47:29 -04001456 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001457 }
1458 }
1459 else
1460 {
1461 switch (attachment)
1462 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001463 case GL_DEPTH_ATTACHMENT:
1464 case GL_STENCIL_ATTACHMENT:
1465 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001466
He Yunchaoced53ae2016-11-29 15:00:51 +08001467 case GL_DEPTH_STENCIL_ATTACHMENT:
1468 if (!context->getExtensions().webglCompatibility &&
1469 context->getClientMajorVersion() < 3)
1470 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001471 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001472 return false;
1473 }
1474 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001475
He Yunchaoced53ae2016-11-29 15:00:51 +08001476 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001477 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001478 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001479 }
1480 }
1481
1482 return true;
1483}
1484
Jamie Madille8fb6402017-02-14 17:56:40 -05001485bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001486 GLenum target,
1487 GLsizei samples,
1488 GLenum internalformat,
1489 GLsizei width,
1490 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001491{
1492 switch (target)
1493 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001494 case GL_RENDERBUFFER:
1495 break;
1496 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001497 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001498 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001499 }
1500
1501 if (width < 0 || height < 0 || samples < 0)
1502 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001503 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001504 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001505 }
1506
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001507 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1508 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1509
1510 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001511 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001513 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001514 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001515 }
1516
1517 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1518 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
Corentin Walleze0902642014-11-04 12:32:15 -08001519 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001520 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1521 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001522 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001523 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001524 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001525 }
1526
Geoff Langaae65a42014-05-26 12:43:44 -04001527 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001528 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001529 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001530 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001531 }
1532
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001533 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001534 if (handle == 0)
1535 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001536 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001537 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001538 }
1539
1540 return true;
1541}
1542
He Yunchaoced53ae2016-11-29 15:00:51 +08001543bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1544 GLenum target,
1545 GLenum attachment,
1546 GLenum renderbuffertarget,
1547 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001548{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001549 if (!ValidFramebufferTarget(target))
1550 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001551 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001552 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001553 }
1554
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001555 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001556
Jamie Madill84115c92015-04-23 15:00:07 -04001557 ASSERT(framebuffer);
1558 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001559 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001560 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001561 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001562 }
1563
Jamie Madillb4472272014-07-03 10:38:55 -04001564 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001565 {
Jamie Madillb4472272014-07-03 10:38:55 -04001566 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001567 }
1568
Jamie Madillab9d82c2014-01-21 16:38:14 -05001569 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1570 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1571 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1572 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1573 if (renderbuffer != 0)
1574 {
1575 if (!context->getRenderbuffer(renderbuffer))
1576 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001577 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001578 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001579 }
1580 }
1581
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001582 return true;
1583}
1584
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001585bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001586 GLint srcX0,
1587 GLint srcY0,
1588 GLint srcX1,
1589 GLint srcY1,
1590 GLint dstX0,
1591 GLint dstY0,
1592 GLint dstX1,
1593 GLint dstY1,
1594 GLbitfield mask,
1595 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001596{
1597 switch (filter)
1598 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001599 case GL_NEAREST:
1600 break;
1601 case GL_LINEAR:
1602 break;
1603 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001604 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001605 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001606 }
1607
1608 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1609 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001610 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001611 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001612 }
1613
1614 if (mask == 0)
1615 {
1616 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1617 // buffers are copied.
1618 return false;
1619 }
1620
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001621 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1622 // color buffer, leaving only nearest being unfiltered from above
1623 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001625 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001626 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001627 }
1628
Jamie Madill51f40ec2016-06-15 14:06:00 -04001629 const auto &glState = context->getGLState();
1630 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1631 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001632
1633 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001634 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001635 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001636 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001637 }
1638
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001639 if (readFramebuffer->id() == drawFramebuffer->id())
1640 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001641 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001642 return false;
1643 }
1644
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001645 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001647 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001648 return false;
1649 }
1650
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001651 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001652 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001653 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001654 return false;
1655 }
1656
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001657 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001659 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001660 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001661 }
1662
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001663 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1664
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001665 if (mask & GL_COLOR_BUFFER_BIT)
1666 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001667 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001668 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001669
He Yunchao66a41a22016-12-15 16:45:05 +08001670 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001671 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001672 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001673
Geoff Langa15472a2015-08-11 11:48:03 -04001674 for (size_t drawbufferIdx = 0;
1675 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001676 {
Geoff Langa15472a2015-08-11 11:48:03 -04001677 const FramebufferAttachment *attachment =
1678 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1679 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001680 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001681 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001682
Geoff Langb2f3d052013-08-13 12:49:27 -04001683 // The GL ES 3.0.2 spec (pg 193) states that:
1684 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001685 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1686 // as well
1687 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1688 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001689 // Changes with EXT_color_buffer_float:
1690 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001691 GLenum readComponentType = readFormat.info->componentType;
1692 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001693 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001694 readComponentType == GL_SIGNED_NORMALIZED);
1695 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1696 drawComponentType == GL_SIGNED_NORMALIZED);
1697
1698 if (extensions.colorBufferFloat)
1699 {
1700 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1701 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1702
1703 if (readFixedOrFloat != drawFixedOrFloat)
1704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001705 context->handleError(InvalidOperation()
1706 << "If the read buffer contains fixed-point or "
1707 "floating-point values, the draw buffer must "
1708 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001709 return false;
1710 }
1711 }
1712 else if (readFixedPoint != drawFixedPoint)
1713 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001714 context->handleError(InvalidOperation()
1715 << "If the read buffer contains fixed-point values, "
1716 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001717 return false;
1718 }
1719
1720 if (readComponentType == GL_UNSIGNED_INT &&
1721 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001722 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001723 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001724 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001725 }
1726
Jamie Madill6163c752015-12-07 16:32:59 -05001727 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001728 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001729 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001730 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001731 }
1732
Jamie Madilla3944d42016-07-22 22:13:26 -04001733 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001734 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001735 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001736 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001737 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001738 }
Geoff Lange4915782017-04-12 15:19:07 -04001739
1740 if (context->getExtensions().webglCompatibility &&
1741 *readColorBuffer == *attachment)
1742 {
1743 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001744 InvalidOperation()
1745 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001746 return false;
1747 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001748 }
1749 }
1750
Jamie Madilla3944d42016-07-22 22:13:26 -04001751 if ((readFormat.info->componentType == GL_INT ||
1752 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1753 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001754 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001755 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001756 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001757 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001758 }
He Yunchao66a41a22016-12-15 16:45:05 +08001759 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1760 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1761 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1762 // situation is an application error that would lead to a crash in ANGLE.
1763 else if (drawFramebuffer->hasEnabledDrawBuffer())
1764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001765 context->handleError(
1766 InvalidOperation()
1767 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001768 return false;
1769 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001770 }
1771
He Yunchaoced53ae2016-11-29 15:00:51 +08001772 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001773 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1774 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001775 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001776 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001777 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001778 const gl::FramebufferAttachment *readBuffer =
1779 readFramebuffer->getAttachment(attachments[i]);
1780 const gl::FramebufferAttachment *drawBuffer =
1781 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001782
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001783 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001784 {
Kenneth Russell69382852017-07-21 16:38:44 -04001785 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001786 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001787 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001788 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001789 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001790
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001791 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001792 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001793 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001794 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001795 }
Geoff Lange4915782017-04-12 15:19:07 -04001796
1797 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1798 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001799 context->handleError(
1800 InvalidOperation()
1801 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001802 return false;
1803 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001804 }
He Yunchao66a41a22016-12-15 16:45:05 +08001805 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1806 else if (drawBuffer)
1807 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001808 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1809 "depth/stencil attachment of a "
1810 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001811 return false;
1812 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001813 }
1814 }
1815
Martin Radeva3ed4572017-07-27 18:29:37 +03001816 // ANGLE_multiview, Revision 1:
1817 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1818 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1819 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1820 {
1821 context->handleError(InvalidFramebufferOperation()
1822 << "Attempt to read from a multi-view framebuffer.");
1823 return false;
1824 }
1825 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1826 {
1827 context->handleError(InvalidFramebufferOperation()
1828 << "Attempt to write to a multi-view framebuffer.");
1829 return false;
1830 }
1831
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001832 return true;
1833}
1834
Jamie Madill4928b7c2017-06-20 12:57:39 -04001835bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001836 GLint x,
1837 GLint y,
1838 GLsizei width,
1839 GLsizei height,
1840 GLenum format,
1841 GLenum type,
1842 GLsizei bufSize,
1843 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001844 GLsizei *columns,
1845 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001846 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001847{
1848 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001849 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001850 return false;
1851 }
1852
Geoff Lang62fce5b2016-09-30 10:46:35 -04001853 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001854 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001855 {
Geoff Langb1196682014-07-23 13:47:29 -04001856 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001857 }
1858
Geoff Lang62fce5b2016-09-30 10:46:35 -04001859 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001860 {
Geoff Langb1196682014-07-23 13:47:29 -04001861 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001862 }
1863
Jamie Madillc29968b2016-01-20 11:17:23 -05001864 return true;
1865}
1866
1867bool ValidateReadnPixelsEXT(Context *context,
1868 GLint x,
1869 GLint y,
1870 GLsizei width,
1871 GLsizei height,
1872 GLenum format,
1873 GLenum type,
1874 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001875 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001876{
1877 if (bufSize < 0)
1878 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001879 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001880 return false;
1881 }
1882
Geoff Lang62fce5b2016-09-30 10:46:35 -04001883 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001884 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001885}
Jamie Madill26e91952014-03-05 15:01:27 -05001886
Jamie Madill4928b7c2017-06-20 12:57:39 -04001887bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001888 GLint x,
1889 GLint y,
1890 GLsizei width,
1891 GLsizei height,
1892 GLenum format,
1893 GLenum type,
1894 GLsizei bufSize,
1895 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001896 GLsizei *columns,
1897 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001898 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001899{
1900 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001901 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001902 return false;
1903 }
1904
Geoff Lange93daba2017-03-30 13:54:40 -04001905 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1906 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001907 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001908 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001909 }
1910
Geoff Lang62fce5b2016-09-30 10:46:35 -04001911 if (!ValidateRobustBufferSize(context, bufSize, *length))
1912 {
1913 return false;
1914 }
1915
1916 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001917}
1918
Olli Etuaho41997e72016-03-10 13:38:39 +02001919bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001920{
1921 if (!context->getExtensions().occlusionQueryBoolean &&
1922 !context->getExtensions().disjointTimerQuery)
1923 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001924 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001925 return false;
1926 }
1927
Olli Etuaho41997e72016-03-10 13:38:39 +02001928 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001929}
1930
Olli Etuaho41997e72016-03-10 13:38:39 +02001931bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001932{
1933 if (!context->getExtensions().occlusionQueryBoolean &&
1934 !context->getExtensions().disjointTimerQuery)
1935 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001936 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001937 return false;
1938 }
1939
Olli Etuaho41997e72016-03-10 13:38:39 +02001940 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001941}
1942
1943bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001944{
1945 if (!ValidQueryType(context, target))
1946 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001947 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001948 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001949 }
1950
1951 if (id == 0)
1952 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001953 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001954 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001955 }
1956
1957 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1958 // of zero, if the active query object name for <target> is non-zero (for the
1959 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1960 // the active query for either target is non-zero), if <id> is the name of an
1961 // existing query object whose type does not match <target>, or if <id> is the
1962 // active query object name for any query type, the error INVALID_OPERATION is
1963 // generated.
1964
1965 // Ensure no other queries are active
1966 // NOTE: If other queries than occlusion are supported, we will need to check
1967 // separately that:
1968 // a) The query ID passed is not the current active query for any target/type
1969 // b) There are no active queries for the requested target (and in the case
1970 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1971 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001972
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001973 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001974 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001975 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001976 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001977 }
1978
1979 Query *queryObject = context->getQuery(id, true, target);
1980
1981 // check that name was obtained with glGenQueries
1982 if (!queryObject)
1983 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001984 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001985 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001986 }
1987
1988 // check for type mismatch
1989 if (queryObject->getType() != target)
1990 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001991 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001992 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001993 }
1994
1995 return true;
1996}
1997
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001998bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1999{
2000 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002001 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002002 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002003 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002004 return false;
2005 }
2006
2007 return ValidateBeginQueryBase(context, target, id);
2008}
2009
2010bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002011{
2012 if (!ValidQueryType(context, target))
2013 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002014 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04002015 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002016 }
2017
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002018 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002019
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002020 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002021 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002022 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04002023 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002024 }
2025
Jamie Madill45c785d2014-05-13 14:09:34 -04002026 return true;
2027}
2028
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002029bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2030{
2031 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002032 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002033 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002034 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002035 return false;
2036 }
2037
2038 return ValidateEndQueryBase(context, target);
2039}
2040
2041bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2042{
2043 if (!context->getExtensions().disjointTimerQuery)
2044 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002045 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002046 return false;
2047 }
2048
2049 if (target != GL_TIMESTAMP_EXT)
2050 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002051 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002052 return false;
2053 }
2054
2055 Query *queryObject = context->getQuery(id, true, target);
2056 if (queryObject == nullptr)
2057 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002058 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002059 return false;
2060 }
2061
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002062 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002063 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002064 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002065 return false;
2066 }
2067
2068 return true;
2069}
2070
Geoff Lang2186c382016-10-14 10:54:54 -04002071bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002072{
Geoff Lang2186c382016-10-14 10:54:54 -04002073 if (numParams)
2074 {
2075 *numParams = 0;
2076 }
2077
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002078 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2079 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002080 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002081 return false;
2082 }
2083
2084 switch (pname)
2085 {
2086 case GL_CURRENT_QUERY_EXT:
2087 if (target == GL_TIMESTAMP_EXT)
2088 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002089 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002090 return false;
2091 }
2092 break;
2093 case GL_QUERY_COUNTER_BITS_EXT:
2094 if (!context->getExtensions().disjointTimerQuery ||
2095 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2096 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002097 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002098 return false;
2099 }
2100 break;
2101 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002102 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002103 return false;
2104 }
2105
Geoff Lang2186c382016-10-14 10:54:54 -04002106 if (numParams)
2107 {
2108 // All queries return only one value
2109 *numParams = 1;
2110 }
2111
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002112 return true;
2113}
2114
2115bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2116{
2117 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002118 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002119 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002120 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002121 return false;
2122 }
2123
Geoff Lang2186c382016-10-14 10:54:54 -04002124 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002125}
2126
Geoff Lang2186c382016-10-14 10:54:54 -04002127bool ValidateGetQueryivRobustANGLE(Context *context,
2128 GLenum target,
2129 GLenum pname,
2130 GLsizei bufSize,
2131 GLsizei *length,
2132 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002133{
Geoff Lang2186c382016-10-14 10:54:54 -04002134 if (!ValidateRobustEntryPoint(context, bufSize))
2135 {
2136 return false;
2137 }
2138
2139 if (!ValidateGetQueryivBase(context, target, pname, length))
2140 {
2141 return false;
2142 }
2143
2144 if (!ValidateRobustBufferSize(context, bufSize, *length))
2145 {
2146 return false;
2147 }
2148
2149 return true;
2150}
2151
2152bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2153{
2154 if (numParams)
2155 {
2156 *numParams = 0;
2157 }
2158
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002159 Query *queryObject = context->getQuery(id, false, GL_NONE);
2160
2161 if (!queryObject)
2162 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002163 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002164 return false;
2165 }
2166
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002167 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002168 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002169 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002170 return false;
2171 }
2172
2173 switch (pname)
2174 {
2175 case GL_QUERY_RESULT_EXT:
2176 case GL_QUERY_RESULT_AVAILABLE_EXT:
2177 break;
2178
2179 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002180 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002181 return false;
2182 }
2183
Geoff Lang2186c382016-10-14 10:54:54 -04002184 if (numParams)
2185 {
2186 *numParams = 1;
2187 }
2188
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002189 return true;
2190}
2191
2192bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2193{
2194 if (!context->getExtensions().disjointTimerQuery)
2195 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002196 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002197 return false;
2198 }
Geoff Lang2186c382016-10-14 10:54:54 -04002199 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2200}
2201
2202bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2203 GLuint id,
2204 GLenum pname,
2205 GLsizei bufSize,
2206 GLsizei *length,
2207 GLint *params)
2208{
2209 if (!context->getExtensions().disjointTimerQuery)
2210 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002211 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04002212 return false;
2213 }
2214
2215 if (!ValidateRobustEntryPoint(context, bufSize))
2216 {
2217 return false;
2218 }
2219
2220 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2221 {
2222 return false;
2223 }
2224
2225 if (!ValidateRobustBufferSize(context, bufSize, *length))
2226 {
2227 return false;
2228 }
2229
2230 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002231}
2232
2233bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2234{
2235 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002236 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002237 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002238 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002239 return false;
2240 }
Geoff Lang2186c382016-10-14 10:54:54 -04002241 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2242}
2243
2244bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2245 GLuint id,
2246 GLenum pname,
2247 GLsizei bufSize,
2248 GLsizei *length,
2249 GLuint *params)
2250{
2251 if (!context->getExtensions().disjointTimerQuery &&
2252 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2253 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002254 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002255 return false;
2256 }
2257
2258 if (!ValidateRobustEntryPoint(context, bufSize))
2259 {
2260 return false;
2261 }
2262
2263 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2264 {
2265 return false;
2266 }
2267
2268 if (!ValidateRobustBufferSize(context, bufSize, *length))
2269 {
2270 return false;
2271 }
2272
2273 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002274}
2275
2276bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2277{
2278 if (!context->getExtensions().disjointTimerQuery)
2279 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002280 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002281 return false;
2282 }
Geoff Lang2186c382016-10-14 10:54:54 -04002283 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2284}
2285
2286bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2287 GLuint id,
2288 GLenum pname,
2289 GLsizei bufSize,
2290 GLsizei *length,
2291 GLint64 *params)
2292{
2293 if (!context->getExtensions().disjointTimerQuery)
2294 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002295 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002296 return false;
2297 }
2298
2299 if (!ValidateRobustEntryPoint(context, bufSize))
2300 {
2301 return false;
2302 }
2303
2304 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2305 {
2306 return false;
2307 }
2308
2309 if (!ValidateRobustBufferSize(context, bufSize, *length))
2310 {
2311 return false;
2312 }
2313
2314 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002315}
2316
2317bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2318{
2319 if (!context->getExtensions().disjointTimerQuery)
2320 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002321 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002322 return false;
2323 }
Geoff Lang2186c382016-10-14 10:54:54 -04002324 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2325}
2326
2327bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2328 GLuint id,
2329 GLenum pname,
2330 GLsizei bufSize,
2331 GLsizei *length,
2332 GLuint64 *params)
2333{
2334 if (!context->getExtensions().disjointTimerQuery)
2335 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002336 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002337 return false;
2338 }
2339
2340 if (!ValidateRobustEntryPoint(context, bufSize))
2341 {
2342 return false;
2343 }
2344
2345 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2346 {
2347 return false;
2348 }
2349
2350 if (!ValidateRobustBufferSize(context, bufSize, *length))
2351 {
2352 return false;
2353 }
2354
2355 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002356}
2357
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002358bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002359 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002360 GLuint program,
2361 GLint location,
2362 GLsizei count)
2363{
2364 // Check for ES31 program uniform entry points
2365 if (context->getClientVersion() < Version(3, 1))
2366 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002367 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002368 return false;
2369 }
2370
2371 const LinkedUniform *uniform = nullptr;
2372 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002373 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2374 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002375}
2376
Frank Henigmana98a6472017-02-02 21:38:32 -05002377bool ValidateProgramUniform1iv(gl::Context *context,
2378 GLuint program,
2379 GLint location,
2380 GLsizei count,
2381 const GLint *value)
2382{
2383 // Check for ES31 program uniform entry points
2384 if (context->getClientVersion() < Version(3, 1))
2385 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002386 context->handleError(InvalidOperation());
Frank Henigmana98a6472017-02-02 21:38:32 -05002387 return false;
2388 }
2389
2390 const LinkedUniform *uniform = nullptr;
2391 gl::Program *programObject = GetValidProgram(context, program);
2392 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2393 ValidateUniform1ivValue(context, uniform->type, count, value);
2394}
2395
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002396bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002397 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002398 GLuint program,
2399 GLint location,
2400 GLsizei count,
2401 GLboolean transpose)
2402{
2403 // Check for ES31 program uniform entry points
2404 if (context->getClientVersion() < Version(3, 1))
2405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002406 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002407 return false;
2408 }
2409
2410 const LinkedUniform *uniform = nullptr;
2411 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002412 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2413 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002414}
2415
Jamie Madillc1d770e2017-04-13 17:31:24 -04002416bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002417{
2418 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002419 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002420 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002421 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002422 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002423 }
2424
Jamie Madill62d31cb2015-09-11 13:25:51 -04002425 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002426 gl::Program *programObject = context->getGLState().getProgram();
2427 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2428 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002429}
2430
Jamie Madillbe849e42017-05-02 15:49:00 -04002431bool ValidateUniform1iv(ValidationContext *context,
2432 GLint location,
2433 GLsizei count,
2434 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002435{
2436 const LinkedUniform *uniform = nullptr;
2437 gl::Program *programObject = context->getGLState().getProgram();
2438 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2439 ValidateUniform1ivValue(context, uniform->type, count, value);
2440}
2441
Jamie Madillc1d770e2017-04-13 17:31:24 -04002442bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002443 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002444 GLint location,
2445 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002446 GLboolean transpose)
2447{
2448 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002449 int rows = VariableRowCount(valueType);
2450 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002451 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002452 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002453 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002454 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002455 }
2456
Martin Radev1be913c2016-07-11 17:59:16 +03002457 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002458 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002459 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002460 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002461 }
2462
Jamie Madill62d31cb2015-09-11 13:25:51 -04002463 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002464 gl::Program *programObject = context->getGLState().getProgram();
2465 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2466 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002467}
2468
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002469bool ValidateStateQuery(ValidationContext *context,
2470 GLenum pname,
2471 GLenum *nativeType,
2472 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002473{
2474 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2475 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002476 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002477 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002478 }
2479
Jamie Madill0af26e12015-03-05 19:54:33 -05002480 const Caps &caps = context->getCaps();
2481
Jamie Madill893ab082014-05-16 16:56:10 -04002482 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2483 {
2484 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2485
Jamie Madill0af26e12015-03-05 19:54:33 -05002486 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002488 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002489 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002490 }
2491 }
2492
2493 switch (pname)
2494 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002495 case GL_TEXTURE_BINDING_2D:
2496 case GL_TEXTURE_BINDING_CUBE_MAP:
2497 case GL_TEXTURE_BINDING_3D:
2498 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002499 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002500 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002501 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2502 if (!context->getExtensions().textureRectangle)
2503 {
2504 context->handleError(InvalidEnum()
2505 << "ANGLE_texture_rectangle extension not present");
2506 return false;
2507 }
2508 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002509 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2510 if (!context->getExtensions().eglStreamConsumerExternal &&
2511 !context->getExtensions().eglImageExternal)
2512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002513 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2514 "nor GL_OES_EGL_image_external "
2515 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002516 return false;
2517 }
2518 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002519
He Yunchaoced53ae2016-11-29 15:00:51 +08002520 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2521 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002522 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002523 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2524 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002525 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002526 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002527 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002528 }
2529
Jamie Madill51f40ec2016-06-15 14:06:00 -04002530 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2531 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002532
2533 if (framebuffer->getReadBufferState() == GL_NONE)
2534 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002535 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002536 return false;
2537 }
2538
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002539 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002540 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002541 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002542 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002543 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002544 }
2545 }
2546 break;
2547
He Yunchaoced53ae2016-11-29 15:00:51 +08002548 default:
2549 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002550 }
2551
2552 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002553 if (*numParams == 0)
2554 {
2555 return false;
2556 }
2557
2558 return true;
2559}
2560
2561bool ValidateRobustStateQuery(ValidationContext *context,
2562 GLenum pname,
2563 GLsizei bufSize,
2564 GLenum *nativeType,
2565 unsigned int *numParams)
2566{
2567 if (!ValidateRobustEntryPoint(context, bufSize))
2568 {
2569 return false;
2570 }
2571
2572 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2573 {
2574 return false;
2575 }
2576
2577 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002578 {
2579 return false;
2580 }
2581
2582 return true;
2583}
2584
Jamie Madillc29968b2016-01-20 11:17:23 -05002585bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2586 GLenum target,
2587 GLint level,
2588 GLenum internalformat,
2589 bool isSubImage,
2590 GLint xoffset,
2591 GLint yoffset,
2592 GLint zoffset,
2593 GLint x,
2594 GLint y,
2595 GLsizei width,
2596 GLsizei height,
2597 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002598 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002599{
Brandon Jones6cad5662017-06-14 13:25:13 -07002600 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002601 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002602 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2603 return false;
2604 }
2605
2606 if (width < 0 || height < 0)
2607 {
2608 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002609 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002610 }
2611
He Yunchaoced53ae2016-11-29 15:00:51 +08002612 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2613 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002614 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002615 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002616 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002617 }
2618
2619 if (border != 0)
2620 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002621 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002622 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002623 }
2624
2625 if (!ValidMipLevel(context, target, level))
2626 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002627 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002628 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002629 }
2630
Jamie Madill51f40ec2016-06-15 14:06:00 -04002631 const auto &state = context->getGLState();
2632 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002633 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002634 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002635 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002636 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002637 }
2638
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002639 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002640 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002641 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002642 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002643 }
2644
Martin Radev138064f2016-07-15 12:03:41 +03002645 if (readFramebuffer->getReadBufferState() == GL_NONE)
2646 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002647 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002648 return false;
2649 }
2650
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002651 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2652 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002653 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002654 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002655 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2656 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002657 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002658 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002659 return false;
2660 }
2661
Martin Radev04e2c3b2017-07-27 16:54:35 +03002662 // ANGLE_multiview spec, Revision 1:
2663 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2664 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2665 // is not NONE.
2666 if (source->getMultiviewLayout() != GL_NONE)
2667 {
2668 context->handleError(InvalidFramebufferOperation()
2669 << "The active read framebuffer object has multiview attachments.");
2670 return false;
2671 }
2672
Geoff Langaae65a42014-05-26 12:43:44 -04002673 const gl::Caps &caps = context->getCaps();
2674
Geoff Langaae65a42014-05-26 12:43:44 -04002675 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002676 switch (target)
2677 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002678 case GL_TEXTURE_2D:
2679 maxDimension = caps.max2DTextureSize;
2680 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002681
He Yunchaoced53ae2016-11-29 15:00:51 +08002682 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2683 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2684 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2685 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2686 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2687 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2688 maxDimension = caps.maxCubeMapTextureSize;
2689 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002690
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002691 case GL_TEXTURE_RECTANGLE_ANGLE:
2692 maxDimension = caps.maxRectangleTextureSize;
2693 break;
2694
He Yunchaoced53ae2016-11-29 15:00:51 +08002695 case GL_TEXTURE_2D_ARRAY:
2696 maxDimension = caps.max2DTextureSize;
2697 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002698
He Yunchaoced53ae2016-11-29 15:00:51 +08002699 case GL_TEXTURE_3D:
2700 maxDimension = caps.max3DTextureSize;
2701 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002702
He Yunchaoced53ae2016-11-29 15:00:51 +08002703 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002704 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002705 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002706 }
2707
Jamie Madillc29968b2016-01-20 11:17:23 -05002708 gl::Texture *texture =
2709 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002710 if (!texture)
2711 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002712 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002713 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002714 }
2715
Geoff Lang69cce582015-09-17 13:20:36 -04002716 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002717 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002718 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002719 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002720 }
2721
Geoff Langca271392017-04-05 12:30:00 -04002722 const gl::InternalFormat &formatInfo =
2723 gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002724
Geoff Lang966c9402017-04-18 12:38:27 -04002725 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002726 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002727 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002728 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002729 }
2730
2731 if (isSubImage)
2732 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002733 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2734 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2735 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002736 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002737 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002738 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002739 }
2740 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002741 else
2742 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002743 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002744 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002745 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002746 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002747 }
2748
Geoff Langeb66a6e2016-10-31 13:06:12 -04002749 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002750 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002751 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002752 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002753 }
2754
2755 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002756 if (static_cast<int>(width) > maxLevelDimension ||
2757 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002758 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002759 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002760 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002761 }
2762 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002763
Jamie Madill0c8abca2016-07-22 20:21:26 -04002764 if (textureFormatOut)
2765 {
2766 *textureFormatOut = texture->getFormat(target, level);
2767 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002768
2769 // Detect texture copying feedback loops for WebGL.
2770 if (context->getExtensions().webglCompatibility)
2771 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002772 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002773 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002774 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002775 return false;
2776 }
2777 }
2778
Jamie Madill560a8d82014-05-21 13:06:20 -04002779 return true;
2780}
2781
Jiajia Qind9671222016-11-29 16:30:31 +08002782bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002783{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002784 switch (mode)
2785 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002786 case GL_POINTS:
2787 case GL_LINES:
2788 case GL_LINE_LOOP:
2789 case GL_LINE_STRIP:
2790 case GL_TRIANGLES:
2791 case GL_TRIANGLE_STRIP:
2792 case GL_TRIANGLE_FAN:
2793 break;
2794 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002795 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002796 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002797 }
2798
Jamie Madill250d33f2014-06-06 17:09:03 -04002799 if (count < 0)
2800 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002801 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002802 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002803 }
2804
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002805 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002806
Jamie Madill250d33f2014-06-06 17:09:03 -04002807 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002808 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002809 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002810 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002811 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002812 }
2813
Jamie Madillcbcde722017-01-06 14:50:00 -05002814 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2815 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002816 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002817 const Extensions &extensions = context->getExtensions();
2818 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002819 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002820 const FramebufferAttachment *dsAttachment =
2821 framebuffer->getStencilOrDepthStencilAttachment();
2822 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002823 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002824 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002825
2826 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2827 bool differentWritemasks =
2828 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2829 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2830 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2831 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2832
2833 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002834 {
Martin Radevffe754b2017-07-31 10:38:07 +03002835 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002836 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002837 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2838 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002839 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002840 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002841 return false;
2842 }
Jamie Madillac528012014-06-20 13:21:23 -04002843 }
2844
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002845 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002846 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002847 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002848 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002849 }
2850
Geoff Lang7dd2e102014-11-10 15:19:26 -05002851 gl::Program *program = state.getProgram();
2852 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002853 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002854 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002855 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002856 }
2857
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002858 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002859 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002860 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002861 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002862 }
2863
Martin Radevffe754b2017-07-31 10:38:07 +03002864 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002865 {
Martin Radev7e69f762017-07-27 14:54:13 +03002866 const int programNumViews = program->getNumViews();
2867 const int framebufferNumViews = framebuffer->getNumViews();
2868 if (programNumViews != -1 && framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002869 {
2870 context->handleError(InvalidOperation() << "The number of views in the active program "
2871 "and draw framebuffer does not match.");
2872 return false;
2873 }
Martin Radev7e69f762017-07-27 14:54:13 +03002874
2875 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2876 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2877 framebufferNumViews > 1)
2878 {
2879 context->handleError(InvalidOperation()
2880 << "There is an active transform feedback object "
2881 "when the number of views in the active draw "
2882 "framebuffer is greater than 1.");
2883 return false;
2884 }
Martin Radevffe754b2017-07-31 10:38:07 +03002885
2886 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2887 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2888 {
2889 context->handleError(InvalidOperation() << "There is an active query for target "
2890 "GL_TIME_ELAPSED_EXT when the number of "
2891 "views in the active draw framebuffer is "
2892 "greater than 1.");
2893 return false;
2894 }
Martin Radev7cf61662017-07-26 17:10:53 +03002895 }
2896
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002897 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002898 for (unsigned int uniformBlockIndex = 0;
2899 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002900 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002901 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002902 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002903 const OffsetBindingPointer<Buffer> &uniformBuffer =
2904 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002905
Geoff Lang5d124a62015-09-15 13:03:27 -04002906 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002907 {
2908 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002909 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002910 InvalidOperation()
2911 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002912 return false;
2913 }
2914
Geoff Lang5d124a62015-09-15 13:03:27 -04002915 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002916 if (uniformBufferSize == 0)
2917 {
2918 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002919 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002920 }
2921
Jamie Madill62d31cb2015-09-11 13:25:51 -04002922 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002923 {
2924 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002925 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002926 InvalidOperation()
2927 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002928 return false;
2929 }
2930 }
2931
Geoff Lange0cff192017-05-30 13:04:56 -04002932 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002933 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002934 {
Geoff Lange0cff192017-05-30 13:04:56 -04002935 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002936 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2937 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002938 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002939 return false;
2940 }
Geoff Lange0cff192017-05-30 13:04:56 -04002941
Geoff Lang9ab5b822017-05-30 16:19:23 -04002942 // Detect that the vertex shader input types match the attribute types
2943 if (!ValidateVertexShaderAttributeTypeMatch(context))
2944 {
2945 return false;
2946 }
2947
Geoff Lange0cff192017-05-30 13:04:56 -04002948 // Detect that the color buffer types match the fragment shader output types
2949 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2950 {
2951 return false;
2952 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002953 }
2954
Jamie Madill250d33f2014-06-06 17:09:03 -04002955 // No-op if zero count
2956 return (count > 0);
2957}
2958
Jamie Madillc1d770e2017-04-13 17:31:24 -04002959bool ValidateDrawArraysCommon(ValidationContext *context,
2960 GLenum mode,
2961 GLint first,
2962 GLsizei count,
2963 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002964{
Jamie Madillfd716582014-06-06 17:09:04 -04002965 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002966 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002967 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002968 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002969 }
2970
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002971 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002972 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002973 if (curTransformFeedback && curTransformFeedback->isActive() &&
2974 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002975 {
2976 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002977 // that does not match the current transform feedback object's draw mode (if transform
2978 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002979 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002980 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002981 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002982 }
2983
Jiajia Qind9671222016-11-29 16:30:31 +08002984 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002985 {
2986 return false;
2987 }
2988
Corentin Wallez71168a02016-12-19 15:11:18 -08002989 // Check the computation of maxVertex doesn't overflow.
2990 // - first < 0 or count < 0 have been checked as an error condition
2991 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2992 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2993 ASSERT(count > 0 && first >= 0);
2994 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2995 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002996 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002997 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002998 return false;
2999 }
3000
Corentin Wallez71168a02016-12-19 15:11:18 -08003001 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003002 {
3003 return false;
3004 }
3005
3006 return true;
3007}
3008
He Yunchaoced53ae2016-11-29 15:00:51 +08003009bool ValidateDrawArraysInstanced(Context *context,
3010 GLenum mode,
3011 GLint first,
3012 GLsizei count,
3013 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003014{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003015 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
Geoff Lang87a93302014-09-16 13:29:43 -04003016}
3017
He Yunchaoced53ae2016-11-29 15:00:51 +08003018bool ValidateDrawArraysInstancedANGLE(Context *context,
3019 GLenum mode,
3020 GLint first,
3021 GLsizei count,
3022 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003023{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003024 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003025 {
3026 return false;
3027 }
3028
Corentin Wallez0dc97812017-06-22 14:38:44 -04003029 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003030}
3031
Jiajia Qind9671222016-11-29 16:30:31 +08003032bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003033{
Jamie Madill250d33f2014-06-06 17:09:03 -04003034 switch (type)
3035 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003036 case GL_UNSIGNED_BYTE:
3037 case GL_UNSIGNED_SHORT:
3038 break;
3039 case GL_UNSIGNED_INT:
3040 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3041 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003042 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08003043 return false;
3044 }
3045 break;
3046 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003047 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08003048 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003049 }
3050
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003051 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003052
3053 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003054 if (curTransformFeedback && curTransformFeedback->isActive() &&
3055 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003056 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003057 // It is an invalid operation to call DrawElements, DrawRangeElements or
3058 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003059 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003060 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003061 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003062 }
3063
Jiajia Qind9671222016-11-29 16:30:31 +08003064 return true;
3065}
3066
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003067bool ValidateDrawElementsCommon(ValidationContext *context,
3068 GLenum mode,
3069 GLsizei count,
3070 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003071 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003072 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08003073{
3074 if (!ValidateDrawElementsBase(context, type))
3075 return false;
3076
3077 const State &state = context->getGLState();
3078
Corentin Wallez170efbf2017-05-02 13:45:01 -04003079 if (!ValidateDrawBase(context, mode, count))
3080 {
3081 return false;
3082 }
3083
Jamie Madill250d33f2014-06-06 17:09:03 -04003084 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003085 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003086 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003087 context->handleError(InvalidOperation() << "Index buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -04003088 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003089 }
3090
He Yunchaoced53ae2016-11-29 15:00:51 +08003091 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003092 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003093
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003094 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3095
3096 if (context->getExtensions().webglCompatibility)
3097 {
3098 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3099 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3100 {
3101 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3102 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3103 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003104 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003105 return false;
3106 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003107
3108 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3109 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3110 // error is generated.
3111 if (reinterpret_cast<intptr_t>(indices) < 0)
3112 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003113 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003114 return false;
3115 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003116 }
3117
3118 if (context->getExtensions().webglCompatibility ||
3119 !context->getGLState().areClientArraysEnabled())
3120 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003121 if (!elementArrayBuffer && count > 0)
3122 {
3123 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3124 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3125 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003126 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003127 return false;
3128 }
3129 }
3130
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003131 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003132 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003133 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003134 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003135 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3136 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3137 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3138 constexpr uint64_t kMaxTypeSize = 8;
3139 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3140 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3141 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003142
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003143 uint64_t typeSize = typeBytes;
3144 uint64_t elementCount = static_cast<uint64_t>(count);
3145 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3146
3147 // Doing the multiplication here is overflow-safe
3148 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3149
3150 // The offset can be any value, check for overflows
3151 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3152 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003153 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003154 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003155 return false;
3156 }
3157
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003158 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3159 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003160 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003161 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003162 return false;
3163 }
3164 }
3165 else if (!indices)
3166 {
3167 // This is an application error that would normally result in a crash,
3168 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003169 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04003170 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003171 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003172 }
3173
Qin Jiajia59d9da02017-08-09 16:59:17 +08003174 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange.
3175 if (!ValidateDrawAttribs(context, primcount, 0, 1))
Jamie Madillfd716582014-06-06 17:09:04 -04003176 {
3177 return false;
3178 }
3179
Qin Jiajia59d9da02017-08-09 16:59:17 +08003180 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04003181}
3182
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003183bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
3184 GLenum mode,
3185 GLsizei count,
3186 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003187 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003188 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003189{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003190 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003191}
3192
Geoff Lang3edfe032015-09-04 16:38:24 -04003193bool ValidateDrawElementsInstancedANGLE(Context *context,
3194 GLenum mode,
3195 GLsizei count,
3196 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003197 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003198 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003199{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003200 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003201 {
3202 return false;
3203 }
3204
Corentin Wallez0dc97812017-06-22 14:38:44 -04003205 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003206}
3207
He Yunchaoced53ae2016-11-29 15:00:51 +08003208bool ValidateFramebufferTextureBase(Context *context,
3209 GLenum target,
3210 GLenum attachment,
3211 GLuint texture,
3212 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003213{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003214 if (!ValidFramebufferTarget(target))
3215 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003216 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003217 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003218 }
3219
3220 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003221 {
3222 return false;
3223 }
3224
Jamie Madill55ec3b12014-07-03 10:38:57 -04003225 if (texture != 0)
3226 {
3227 gl::Texture *tex = context->getTexture(texture);
3228
Jamie Madillbe849e42017-05-02 15:49:00 -04003229 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003230 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003231 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003232 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003233 }
3234
3235 if (level < 0)
3236 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003237 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003238 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003239 }
3240 }
3241
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003242 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003243 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003244
Jamie Madill84115c92015-04-23 15:00:07 -04003245 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003246 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003247 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003248 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003249 }
3250
3251 return true;
3252}
3253
Geoff Langb1196682014-07-23 13:47:29 -04003254bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003255{
3256 if (program == 0)
3257 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003258 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003259 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003260 }
3261
Dian Xiang769769a2015-09-09 15:20:08 -07003262 gl::Program *programObject = GetValidProgram(context, program);
3263 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003264 {
3265 return false;
3266 }
3267
Jamie Madill0063c512014-08-25 15:47:53 -04003268 if (!programObject || !programObject->isLinked())
3269 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003270 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003271 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003272 }
3273
Geoff Lang7dd2e102014-11-10 15:19:26 -05003274 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003275 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003276 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003277 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003278 }
3279
Jamie Madill0063c512014-08-25 15:47:53 -04003280 return true;
3281}
3282
Geoff Langf41d0ee2016-10-07 13:04:23 -04003283static bool ValidateSizedGetUniform(Context *context,
3284 GLuint program,
3285 GLint location,
3286 GLsizei bufSize,
3287 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003288{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003289 if (length)
3290 {
3291 *length = 0;
3292 }
3293
Jamie Madill78f41802014-08-25 15:47:55 -04003294 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003295 {
Jamie Madill78f41802014-08-25 15:47:55 -04003296 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003297 }
3298
Geoff Langf41d0ee2016-10-07 13:04:23 -04003299 if (bufSize < 0)
3300 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003301 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003302 return false;
3303 }
3304
Jamie Madilla502c742014-08-28 17:19:13 -04003305 gl::Program *programObject = context->getProgram(program);
3306 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003307
Jamie Madill78f41802014-08-25 15:47:55 -04003308 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003309 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003310 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003311 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003312 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003313 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003314 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003315 }
3316
Geoff Langf41d0ee2016-10-07 13:04:23 -04003317 if (length)
3318 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003319 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003320 }
3321
Jamie Madill0063c512014-08-25 15:47:53 -04003322 return true;
3323}
3324
He Yunchaoced53ae2016-11-29 15:00:51 +08003325bool ValidateGetnUniformfvEXT(Context *context,
3326 GLuint program,
3327 GLint location,
3328 GLsizei bufSize,
3329 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003330{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003331 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003332}
3333
He Yunchaoced53ae2016-11-29 15:00:51 +08003334bool ValidateGetnUniformivEXT(Context *context,
3335 GLuint program,
3336 GLint location,
3337 GLsizei bufSize,
3338 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003339{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003340 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3341}
3342
3343bool ValidateGetUniformfvRobustANGLE(Context *context,
3344 GLuint program,
3345 GLint location,
3346 GLsizei bufSize,
3347 GLsizei *length,
3348 GLfloat *params)
3349{
3350 if (!ValidateRobustEntryPoint(context, bufSize))
3351 {
3352 return false;
3353 }
3354
3355 // bufSize is validated in ValidateSizedGetUniform
3356 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3357}
3358
3359bool ValidateGetUniformivRobustANGLE(Context *context,
3360 GLuint program,
3361 GLint location,
3362 GLsizei bufSize,
3363 GLsizei *length,
3364 GLint *params)
3365{
3366 if (!ValidateRobustEntryPoint(context, bufSize))
3367 {
3368 return false;
3369 }
3370
3371 // bufSize is validated in ValidateSizedGetUniform
3372 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3373}
3374
3375bool ValidateGetUniformuivRobustANGLE(Context *context,
3376 GLuint program,
3377 GLint location,
3378 GLsizei bufSize,
3379 GLsizei *length,
3380 GLuint *params)
3381{
3382 if (!ValidateRobustEntryPoint(context, bufSize))
3383 {
3384 return false;
3385 }
3386
3387 if (context->getClientMajorVersion() < 3)
3388 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003389 context->handleError(InvalidOperation() << "Entry point requires at least OpenGL ES 3.0.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003390 return false;
3391 }
3392
3393 // bufSize is validated in ValidateSizedGetUniform
3394 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003395}
3396
He Yunchaoced53ae2016-11-29 15:00:51 +08003397bool ValidateDiscardFramebufferBase(Context *context,
3398 GLenum target,
3399 GLsizei numAttachments,
3400 const GLenum *attachments,
3401 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003402{
3403 if (numAttachments < 0)
3404 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003405 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003406 return false;
3407 }
3408
3409 for (GLsizei i = 0; i < numAttachments; ++i)
3410 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003411 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003412 {
3413 if (defaultFramebuffer)
3414 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003415 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003416 return false;
3417 }
3418
3419 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3420 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003421 context->handleError(InvalidOperation() << "Requested color attachment is "
3422 "greater than the maximum supported "
3423 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003424 return false;
3425 }
3426 }
3427 else
3428 {
3429 switch (attachments[i])
3430 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003431 case GL_DEPTH_ATTACHMENT:
3432 case GL_STENCIL_ATTACHMENT:
3433 case GL_DEPTH_STENCIL_ATTACHMENT:
3434 if (defaultFramebuffer)
3435 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003436 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3437 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003438 return false;
3439 }
3440 break;
3441 case GL_COLOR:
3442 case GL_DEPTH:
3443 case GL_STENCIL:
3444 if (!defaultFramebuffer)
3445 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003446 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3447 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003448 return false;
3449 }
3450 break;
3451 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003452 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003453 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003454 }
3455 }
3456 }
3457
3458 return true;
3459}
3460
Austin Kinross6ee1e782015-05-29 17:05:37 -07003461bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3462{
3463 // Note that debug marker calls must not set error state
3464
3465 if (length < 0)
3466 {
3467 return false;
3468 }
3469
3470 if (marker == nullptr)
3471 {
3472 return false;
3473 }
3474
3475 return true;
3476}
3477
3478bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3479{
3480 // Note that debug marker calls must not set error state
3481
3482 if (length < 0)
3483 {
3484 return false;
3485 }
3486
3487 if (length > 0 && marker == nullptr)
3488 {
3489 return false;
3490 }
3491
3492 return true;
3493}
3494
Geoff Langdcab33b2015-07-21 13:03:16 -04003495bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003496 GLenum target,
3497 egl::Image *image)
3498{
Geoff Langa8406172015-07-21 16:53:39 -04003499 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3500 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003501 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003502 return false;
3503 }
3504
3505 switch (target)
3506 {
3507 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003508 if (!context->getExtensions().eglImage)
3509 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003510 context->handleError(InvalidEnum()
3511 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003512 }
3513 break;
3514
3515 case GL_TEXTURE_EXTERNAL_OES:
3516 if (!context->getExtensions().eglImageExternal)
3517 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003518 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3519 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003520 }
Geoff Langa8406172015-07-21 16:53:39 -04003521 break;
3522
3523 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003524 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003525 return false;
3526 }
3527
Jamie Madill61e16b42017-06-19 11:13:23 -04003528 ASSERT(context->getCurrentDisplay());
3529 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003530 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003531 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003532 return false;
3533 }
3534
3535 if (image->getSamples() > 0)
3536 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003537 context->handleError(InvalidOperation()
3538 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003539 return false;
3540 }
3541
Geoff Langca271392017-04-05 12:30:00 -04003542 const TextureCaps &textureCaps =
3543 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003544 if (!textureCaps.texturable)
3545 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003546 context->handleError(InvalidOperation()
3547 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003548 return false;
3549 }
3550
Geoff Langdcab33b2015-07-21 13:03:16 -04003551 return true;
3552}
3553
3554bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003555 GLenum target,
3556 egl::Image *image)
3557{
Geoff Langa8406172015-07-21 16:53:39 -04003558 if (!context->getExtensions().eglImage)
3559 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003560 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003561 return false;
3562 }
3563
3564 switch (target)
3565 {
3566 case GL_RENDERBUFFER:
3567 break;
3568
3569 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003570 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003571 return false;
3572 }
3573
Jamie Madill61e16b42017-06-19 11:13:23 -04003574 ASSERT(context->getCurrentDisplay());
3575 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003576 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003577 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003578 return false;
3579 }
3580
Geoff Langca271392017-04-05 12:30:00 -04003581 const TextureCaps &textureCaps =
3582 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003583 if (!textureCaps.renderable)
3584 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003585 context->handleError(InvalidOperation()
3586 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003587 return false;
3588 }
3589
Geoff Langdcab33b2015-07-21 13:03:16 -04003590 return true;
3591}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003592
3593bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3594{
Geoff Lang36167ab2015-12-07 10:27:14 -05003595 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003596 {
3597 // The default VAO should always exist
3598 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003599 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003600 return false;
3601 }
3602
3603 return true;
3604}
3605
Geoff Langc5629752015-12-07 16:29:04 -05003606bool ValidateProgramBinaryBase(Context *context,
3607 GLuint program,
3608 GLenum binaryFormat,
3609 const void *binary,
3610 GLint length)
3611{
3612 Program *programObject = GetValidProgram(context, program);
3613 if (programObject == nullptr)
3614 {
3615 return false;
3616 }
3617
3618 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3619 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3620 programBinaryFormats.end())
3621 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003622 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003623 return false;
3624 }
3625
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003626 if (context->hasActiveTransformFeedback(program))
3627 {
3628 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003629 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3630 "is associated with an active transform "
3631 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003632 return false;
3633 }
3634
Geoff Langc5629752015-12-07 16:29:04 -05003635 return true;
3636}
3637
3638bool ValidateGetProgramBinaryBase(Context *context,
3639 GLuint program,
3640 GLsizei bufSize,
3641 GLsizei *length,
3642 GLenum *binaryFormat,
3643 void *binary)
3644{
3645 Program *programObject = GetValidProgram(context, program);
3646 if (programObject == nullptr)
3647 {
3648 return false;
3649 }
3650
3651 if (!programObject->isLinked())
3652 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003653 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003654 return false;
3655 }
3656
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003657 if (context->getCaps().programBinaryFormats.empty())
3658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003659 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003660 return false;
3661 }
3662
Geoff Langc5629752015-12-07 16:29:04 -05003663 return true;
3664}
Jamie Madillc29968b2016-01-20 11:17:23 -05003665
Jamie Madillc29968b2016-01-20 11:17:23 -05003666bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3667{
3668 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003669 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003670 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003671 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3672 return false;
3673 }
3674 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3675 {
3676 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003677 return false;
3678 }
3679
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003680 ASSERT(context->getGLState().getDrawFramebuffer());
3681 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003682 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3683
3684 // This should come first before the check for the default frame buffer
3685 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3686 // rather than INVALID_OPERATION
3687 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3688 {
3689 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3690
3691 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003692 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3693 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003694 {
3695 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003696 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3697 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3698 // 3.1 is still a bit ambiguous about the error, but future specs are
3699 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003700 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003701 return false;
3702 }
3703 else if (bufs[colorAttachment] >= maxColorAttachment)
3704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003705 context->handleError(InvalidOperation()
3706 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003707 return false;
3708 }
3709 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3710 frameBufferId != 0)
3711 {
3712 // INVALID_OPERATION-GL is bound to buffer and ith argument
3713 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003714 context->handleError(InvalidOperation()
3715 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003716 return false;
3717 }
3718 }
3719
3720 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3721 // and n is not 1 or bufs is bound to value other than BACK and NONE
3722 if (frameBufferId == 0)
3723 {
3724 if (n != 1)
3725 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003726 context->handleError(InvalidOperation()
3727 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003728 return false;
3729 }
3730
3731 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3732 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003733 context->handleError(
3734 InvalidOperation()
3735 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003736 return false;
3737 }
3738 }
3739
3740 return true;
3741}
3742
Geoff Lang496c02d2016-10-20 11:38:11 -07003743bool ValidateGetBufferPointervBase(Context *context,
3744 GLenum target,
3745 GLenum pname,
3746 GLsizei *length,
3747 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003748{
Geoff Lang496c02d2016-10-20 11:38:11 -07003749 if (length)
3750 {
3751 *length = 0;
3752 }
3753
3754 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3755 {
3756 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003757 InvalidOperation()
3758 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003759 return false;
3760 }
3761
Olli Etuaho4f667482016-03-30 15:56:35 +03003762 if (!ValidBufferTarget(context, target))
3763 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003764 context->handleError(InvalidEnum() << "Buffer target not valid: 0x" << std::hex
3765 << std::uppercase << target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003766 return false;
3767 }
3768
Geoff Lang496c02d2016-10-20 11:38:11 -07003769 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003770 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003771 case GL_BUFFER_MAP_POINTER:
3772 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003773
Geoff Lang496c02d2016-10-20 11:38:11 -07003774 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003775 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003776 return false;
3777 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003778
3779 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3780 // target bound to zero generate an INVALID_OPERATION error."
3781 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003782 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003783 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003784 context->handleError(InvalidOperation()
3785 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003786 return false;
3787 }
3788
Geoff Lang496c02d2016-10-20 11:38:11 -07003789 if (length)
3790 {
3791 *length = 1;
3792 }
3793
Olli Etuaho4f667482016-03-30 15:56:35 +03003794 return true;
3795}
3796
3797bool ValidateUnmapBufferBase(Context *context, GLenum target)
3798{
3799 if (!ValidBufferTarget(context, target))
3800 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003801 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003802 return false;
3803 }
3804
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003805 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003806
3807 if (buffer == nullptr || !buffer->isMapped())
3808 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003809 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003810 return false;
3811 }
3812
3813 return true;
3814}
3815
3816bool ValidateMapBufferRangeBase(Context *context,
3817 GLenum target,
3818 GLintptr offset,
3819 GLsizeiptr length,
3820 GLbitfield access)
3821{
3822 if (!ValidBufferTarget(context, target))
3823 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003824 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003825 return false;
3826 }
3827
Brandon Jones6cad5662017-06-14 13:25:13 -07003828 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003829 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003830 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3831 return false;
3832 }
3833
3834 if (length < 0)
3835 {
3836 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003837 return false;
3838 }
3839
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003840 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003841
3842 if (!buffer)
3843 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003844 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003845 return false;
3846 }
3847
3848 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003849 CheckedNumeric<size_t> checkedOffset(offset);
3850 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003851
Jamie Madille2e406c2016-06-02 13:04:10 -04003852 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003853 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003854 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003855 return false;
3856 }
3857
3858 // Check for invalid bits in the mask
3859 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3860 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3861 GL_MAP_UNSYNCHRONIZED_BIT;
3862
3863 if (access & ~(allAccessBits))
3864 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003865 context->handleError(InvalidValue()
3866 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003867 return false;
3868 }
3869
3870 if (length == 0)
3871 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003872 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003873 return false;
3874 }
3875
3876 if (buffer->isMapped())
3877 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003878 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003879 return false;
3880 }
3881
3882 // Check for invalid bit combinations
3883 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3884 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003885 context->handleError(InvalidOperation()
3886 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003887 return false;
3888 }
3889
3890 GLbitfield writeOnlyBits =
3891 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3892
3893 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3894 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003895 context->handleError(InvalidOperation()
3896 << "Invalid access bits when mapping buffer for reading: 0x"
3897 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003898 return false;
3899 }
3900
3901 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3902 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003903 context->handleError(
3904 InvalidOperation()
3905 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003906 return false;
3907 }
Geoff Lang79f71042017-08-14 16:43:43 -04003908
3909 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003910}
3911
3912bool ValidateFlushMappedBufferRangeBase(Context *context,
3913 GLenum target,
3914 GLintptr offset,
3915 GLsizeiptr length)
3916{
Brandon Jones6cad5662017-06-14 13:25:13 -07003917 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003918 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003919 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3920 return false;
3921 }
3922
3923 if (length < 0)
3924 {
3925 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003926 return false;
3927 }
3928
3929 if (!ValidBufferTarget(context, target))
3930 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003931 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003932 return false;
3933 }
3934
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003935 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003936
3937 if (buffer == nullptr)
3938 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003939 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003940 return false;
3941 }
3942
3943 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3944 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003945 context->handleError(InvalidOperation()
3946 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003947 return false;
3948 }
3949
3950 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003951 CheckedNumeric<size_t> checkedOffset(offset);
3952 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003953
Jamie Madille2e406c2016-06-02 13:04:10 -04003954 if (!checkedSize.IsValid() ||
3955 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003956 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003957 context->handleError(InvalidValue()
3958 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003959 return false;
3960 }
3961
3962 return true;
3963}
3964
Olli Etuaho41997e72016-03-10 13:38:39 +02003965bool ValidateGenOrDelete(Context *context, GLint n)
3966{
3967 if (n < 0)
3968 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003969 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003970 return false;
3971 }
3972 return true;
3973}
3974
Geoff Langff5b2d52016-09-07 11:32:23 -04003975bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3976{
3977 if (!context->getExtensions().robustClientMemory)
3978 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003979 context->handleError(InvalidOperation()
3980 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003981 return false;
3982 }
3983
3984 if (bufSize < 0)
3985 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003986 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003987 return false;
3988 }
3989
3990 return true;
3991}
3992
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003993bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3994{
3995 if (bufSize < numParams)
3996 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003997 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3998 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003999 return false;
4000 }
4001
4002 return true;
4003}
4004
Jamie Madillbe849e42017-05-02 15:49:00 -04004005bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
4006 GLenum target,
4007 GLenum attachment,
4008 GLenum pname,
4009 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004010{
Geoff Langff5b2d52016-09-07 11:32:23 -04004011 if (!ValidFramebufferTarget(target))
4012 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004013 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004014 return false;
4015 }
4016
4017 int clientVersion = context->getClientMajorVersion();
4018
4019 switch (pname)
4020 {
4021 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4022 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4023 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4024 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4025 break;
4026
Martin Radeve5285d22017-07-14 16:23:53 +03004027 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4028 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4029 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4030 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4031 if (clientVersion < 3 || !context->getExtensions().multiview)
4032 {
4033 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4034 return false;
4035 }
4036 break;
4037
Geoff Langff5b2d52016-09-07 11:32:23 -04004038 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4039 if (clientVersion < 3 && !context->getExtensions().sRGB)
4040 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004041 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004042 return false;
4043 }
4044 break;
4045
4046 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4047 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4048 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4049 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4050 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4051 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4052 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4053 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4054 if (clientVersion < 3)
4055 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004056 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004057 return false;
4058 }
4059 break;
4060
4061 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004062 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004063 return false;
4064 }
4065
4066 // Determine if the attachment is a valid enum
4067 switch (attachment)
4068 {
4069 case GL_BACK:
4070 case GL_FRONT:
4071 case GL_DEPTH:
4072 case GL_STENCIL:
4073 case GL_DEPTH_STENCIL_ATTACHMENT:
4074 if (clientVersion < 3)
4075 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004076 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004077 return false;
4078 }
4079 break;
4080
4081 case GL_DEPTH_ATTACHMENT:
4082 case GL_STENCIL_ATTACHMENT:
4083 break;
4084
4085 default:
4086 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4087 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4088 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004089 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004090 return false;
4091 }
4092 break;
4093 }
4094
4095 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4096 ASSERT(framebuffer);
4097
4098 if (framebuffer->id() == 0)
4099 {
4100 if (clientVersion < 3)
4101 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004102 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004103 return false;
4104 }
4105
4106 switch (attachment)
4107 {
4108 case GL_BACK:
4109 case GL_DEPTH:
4110 case GL_STENCIL:
4111 break;
4112
4113 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004114 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004115 return false;
4116 }
4117 }
4118 else
4119 {
4120 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4121 {
4122 // Valid attachment query
4123 }
4124 else
4125 {
4126 switch (attachment)
4127 {
4128 case GL_DEPTH_ATTACHMENT:
4129 case GL_STENCIL_ATTACHMENT:
4130 break;
4131
4132 case GL_DEPTH_STENCIL_ATTACHMENT:
4133 if (!framebuffer->hasValidDepthStencil())
4134 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004135 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004136 return false;
4137 }
4138 break;
4139
4140 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004141 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004142 return false;
4143 }
4144 }
4145 }
4146
4147 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4148 if (attachmentObject)
4149 {
4150 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4151 attachmentObject->type() == GL_TEXTURE ||
4152 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4153
4154 switch (pname)
4155 {
4156 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4157 if (attachmentObject->type() != GL_RENDERBUFFER &&
4158 attachmentObject->type() != GL_TEXTURE)
4159 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004160 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004161 return false;
4162 }
4163 break;
4164
4165 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4166 if (attachmentObject->type() != GL_TEXTURE)
4167 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004168 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004169 return false;
4170 }
4171 break;
4172
4173 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4174 if (attachmentObject->type() != GL_TEXTURE)
4175 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004176 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004177 return false;
4178 }
4179 break;
4180
4181 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4182 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4183 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004184 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004185 return false;
4186 }
4187 break;
4188
4189 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4190 if (attachmentObject->type() != GL_TEXTURE)
4191 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004192 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004193 return false;
4194 }
4195 break;
4196
4197 default:
4198 break;
4199 }
4200 }
4201 else
4202 {
4203 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4204 // is NONE, then querying any other pname will generate INVALID_ENUM.
4205
4206 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4207 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4208 // INVALID_OPERATION for all other pnames
4209
4210 switch (pname)
4211 {
4212 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4213 break;
4214
4215 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4216 if (clientVersion < 3)
4217 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004218 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004219 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004220 return false;
4221 }
4222 break;
4223
4224 default:
4225 if (clientVersion < 3)
4226 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004227 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004228 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004229 return false;
4230 }
4231 else
4232 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004233 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004234 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004235 return false;
4236 }
4237 }
4238 }
4239
Martin Radeve5285d22017-07-14 16:23:53 +03004240 if (numParams)
4241 {
4242 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4243 {
4244 // Only when the viewport offsets are queried we can have a varying number of output
4245 // parameters.
4246 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4247 *numParams = numViews * 2;
4248 }
4249 else
4250 {
4251 // For all other queries we can have only one output parameter.
4252 *numParams = 1;
4253 }
4254 }
4255
Geoff Langff5b2d52016-09-07 11:32:23 -04004256 return true;
4257}
4258
4259bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4260 GLenum target,
4261 GLenum attachment,
4262 GLenum pname,
4263 GLsizei bufSize,
4264 GLsizei *numParams)
4265{
4266 if (!ValidateRobustEntryPoint(context, bufSize))
4267 {
4268 return false;
4269 }
4270
Jamie Madillbe849e42017-05-02 15:49:00 -04004271 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4272 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004273 {
4274 return false;
4275 }
4276
4277 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4278 {
4279 return false;
4280 }
4281
4282 return true;
4283}
4284
Geoff Langff5b2d52016-09-07 11:32:23 -04004285bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4286 GLenum target,
4287 GLenum pname,
4288 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004289 GLsizei *length,
4290 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004291{
4292 if (!ValidateRobustEntryPoint(context, bufSize))
4293 {
4294 return false;
4295 }
4296
Geoff Langebebe1c2016-10-14 12:01:31 -04004297 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004298 {
4299 return false;
4300 }
4301
Geoff Langebebe1c2016-10-14 12:01:31 -04004302 if (!ValidateRobustBufferSize(context, bufSize, *length))
4303 {
4304 return false;
4305 }
4306
4307 return true;
4308}
4309
4310bool ValidateGetBufferParameteri64v(ValidationContext *context,
4311 GLenum target,
4312 GLenum pname,
4313 GLint64 *params)
4314{
4315 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4316}
4317
4318bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4319 GLenum target,
4320 GLenum pname,
4321 GLsizei bufSize,
4322 GLsizei *length,
4323 GLint64 *params)
4324{
4325 if (!ValidateRobustEntryPoint(context, bufSize))
4326 {
4327 return false;
4328 }
4329
4330 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4331 {
4332 return false;
4333 }
4334
4335 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004336 {
4337 return false;
4338 }
4339
4340 return true;
4341}
4342
Jamie Madillbe849e42017-05-02 15:49:00 -04004343bool ValidateGetProgramivBase(ValidationContext *context,
4344 GLuint program,
4345 GLenum pname,
4346 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004347{
4348 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004349 if (numParams)
4350 {
4351 *numParams = 1;
4352 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004353
4354 Program *programObject = GetValidProgram(context, program);
4355 if (!programObject)
4356 {
4357 return false;
4358 }
4359
4360 switch (pname)
4361 {
4362 case GL_DELETE_STATUS:
4363 case GL_LINK_STATUS:
4364 case GL_VALIDATE_STATUS:
4365 case GL_INFO_LOG_LENGTH:
4366 case GL_ATTACHED_SHADERS:
4367 case GL_ACTIVE_ATTRIBUTES:
4368 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4369 case GL_ACTIVE_UNIFORMS:
4370 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4371 break;
4372
4373 case GL_PROGRAM_BINARY_LENGTH:
4374 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4375 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004376 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4377 "requires GL_OES_get_program_binary or "
4378 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004379 return false;
4380 }
4381 break;
4382
4383 case GL_ACTIVE_UNIFORM_BLOCKS:
4384 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4385 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4386 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4387 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4388 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4389 if (context->getClientMajorVersion() < 3)
4390 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004391 context->handleError(InvalidEnum() << "Querying requires at least ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004392 return false;
4393 }
4394 break;
4395
Yunchao He61afff12017-03-14 15:34:03 +08004396 case GL_PROGRAM_SEPARABLE:
4397 if (context->getClientVersion() < Version(3, 1))
4398 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004399 context->handleError(InvalidEnum() << "Querying requires at least ES 3.1.");
Yunchao He61afff12017-03-14 15:34:03 +08004400 return false;
4401 }
4402 break;
4403
Geoff Langff5b2d52016-09-07 11:32:23 -04004404 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004405 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004406 return false;
4407 }
4408
4409 return true;
4410}
4411
4412bool ValidateGetProgramivRobustANGLE(Context *context,
4413 GLuint program,
4414 GLenum pname,
4415 GLsizei bufSize,
4416 GLsizei *numParams)
4417{
4418 if (!ValidateRobustEntryPoint(context, bufSize))
4419 {
4420 return false;
4421 }
4422
Jamie Madillbe849e42017-05-02 15:49:00 -04004423 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004424 {
4425 return false;
4426 }
4427
4428 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4429 {
4430 return false;
4431 }
4432
4433 return true;
4434}
4435
Geoff Lang740d9022016-10-07 11:20:52 -04004436bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4437 GLenum target,
4438 GLenum pname,
4439 GLsizei bufSize,
4440 GLsizei *length,
4441 GLint *params)
4442{
4443 if (!ValidateRobustEntryPoint(context, bufSize))
4444 {
4445 return false;
4446 }
4447
4448 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4449 {
4450 return false;
4451 }
4452
4453 if (!ValidateRobustBufferSize(context, bufSize, *length))
4454 {
4455 return false;
4456 }
4457
4458 return true;
4459}
4460
Geoff Langd7d0ed32016-10-07 11:33:51 -04004461bool ValidateGetShaderivRobustANGLE(Context *context,
4462 GLuint shader,
4463 GLenum pname,
4464 GLsizei bufSize,
4465 GLsizei *length,
4466 GLint *params)
4467{
4468 if (!ValidateRobustEntryPoint(context, bufSize))
4469 {
4470 return false;
4471 }
4472
4473 if (!ValidateGetShaderivBase(context, shader, pname, length))
4474 {
4475 return false;
4476 }
4477
4478 if (!ValidateRobustBufferSize(context, bufSize, *length))
4479 {
4480 return false;
4481 }
4482
4483 return true;
4484}
4485
Geoff Langc1984ed2016-10-07 12:41:00 -04004486bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4487 GLenum target,
4488 GLenum pname,
4489 GLsizei bufSize,
4490 GLsizei *length,
4491 GLfloat *params)
4492{
4493 if (!ValidateRobustEntryPoint(context, bufSize))
4494 {
4495 return false;
4496 }
4497
4498 if (!ValidateGetTexParameterBase(context, target, pname, length))
4499 {
4500 return false;
4501 }
4502
4503 if (!ValidateRobustBufferSize(context, bufSize, *length))
4504 {
4505 return false;
4506 }
4507
4508 return true;
4509}
4510
Geoff Langc1984ed2016-10-07 12:41:00 -04004511bool ValidateGetTexParameterivRobustANGLE(Context *context,
4512 GLenum target,
4513 GLenum pname,
4514 GLsizei bufSize,
4515 GLsizei *length,
4516 GLint *params)
4517{
4518 if (!ValidateRobustEntryPoint(context, bufSize))
4519 {
4520 return false;
4521 }
4522
4523 if (!ValidateGetTexParameterBase(context, target, pname, length))
4524 {
4525 return false;
4526 }
4527
4528 if (!ValidateRobustBufferSize(context, bufSize, *length))
4529 {
4530 return false;
4531 }
4532
4533 return true;
4534}
4535
Geoff Langc1984ed2016-10-07 12:41:00 -04004536bool ValidateTexParameterfvRobustANGLE(Context *context,
4537 GLenum target,
4538 GLenum pname,
4539 GLsizei bufSize,
4540 const GLfloat *params)
4541{
4542 if (!ValidateRobustEntryPoint(context, bufSize))
4543 {
4544 return false;
4545 }
4546
4547 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4548}
4549
Geoff Langc1984ed2016-10-07 12:41:00 -04004550bool ValidateTexParameterivRobustANGLE(Context *context,
4551 GLenum target,
4552 GLenum pname,
4553 GLsizei bufSize,
4554 const GLint *params)
4555{
4556 if (!ValidateRobustEntryPoint(context, bufSize))
4557 {
4558 return false;
4559 }
4560
4561 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4562}
4563
4564bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4565{
4566 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4567}
4568
4569bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4570 GLuint sampler,
4571 GLenum pname,
4572 GLuint bufSize,
4573 GLsizei *length,
4574 GLfloat *params)
4575{
4576 if (!ValidateRobustEntryPoint(context, bufSize))
4577 {
4578 return false;
4579 }
4580
4581 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4582 {
4583 return false;
4584 }
4585
4586 if (!ValidateRobustBufferSize(context, bufSize, *length))
4587 {
4588 return false;
4589 }
4590
4591 return true;
4592}
4593
4594bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4595{
4596 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4597}
4598
4599bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4600 GLuint sampler,
4601 GLenum pname,
4602 GLuint bufSize,
4603 GLsizei *length,
4604 GLint *params)
4605{
4606 if (!ValidateRobustEntryPoint(context, bufSize))
4607 {
4608 return false;
4609 }
4610
4611 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4612 {
4613 return false;
4614 }
4615
4616 if (!ValidateRobustBufferSize(context, bufSize, *length))
4617 {
4618 return false;
4619 }
4620
4621 return true;
4622}
4623
4624bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4625{
4626 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4627}
4628
4629bool ValidateSamplerParameterfv(Context *context,
4630 GLuint sampler,
4631 GLenum pname,
4632 const GLfloat *params)
4633{
4634 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4635}
4636
4637bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4638 GLuint sampler,
4639 GLenum pname,
4640 GLsizei bufSize,
4641 const GLfloat *params)
4642{
4643 if (!ValidateRobustEntryPoint(context, bufSize))
4644 {
4645 return false;
4646 }
4647
4648 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4649}
4650
4651bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4652{
4653 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4654}
4655
4656bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4657{
4658 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4659}
4660
4661bool ValidateSamplerParameterivRobustANGLE(Context *context,
4662 GLuint sampler,
4663 GLenum pname,
4664 GLsizei bufSize,
4665 const GLint *params)
4666{
4667 if (!ValidateRobustEntryPoint(context, bufSize))
4668 {
4669 return false;
4670 }
4671
4672 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4673}
4674
Geoff Lang0b031062016-10-13 14:30:04 -04004675bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4676 GLuint index,
4677 GLenum pname,
4678 GLsizei bufSize,
4679 GLsizei *length,
4680 GLfloat *params)
4681{
4682 if (!ValidateRobustEntryPoint(context, bufSize))
4683 {
4684 return false;
4685 }
4686
4687 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4688 {
4689 return false;
4690 }
4691
4692 if (!ValidateRobustBufferSize(context, bufSize, *length))
4693 {
4694 return false;
4695 }
4696
4697 return true;
4698}
4699
Geoff Lang0b031062016-10-13 14:30:04 -04004700bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4701 GLuint index,
4702 GLenum pname,
4703 GLsizei bufSize,
4704 GLsizei *length,
4705 GLint *params)
4706{
4707 if (!ValidateRobustEntryPoint(context, bufSize))
4708 {
4709 return false;
4710 }
4711
4712 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4713 {
4714 return false;
4715 }
4716
4717 if (!ValidateRobustBufferSize(context, bufSize, *length))
4718 {
4719 return false;
4720 }
4721
4722 return true;
4723}
4724
Geoff Lang0b031062016-10-13 14:30:04 -04004725bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4726 GLuint index,
4727 GLenum pname,
4728 GLsizei bufSize,
4729 GLsizei *length,
4730 void **pointer)
4731{
4732 if (!ValidateRobustEntryPoint(context, bufSize))
4733 {
4734 return false;
4735 }
4736
4737 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4738 {
4739 return false;
4740 }
4741
4742 if (!ValidateRobustBufferSize(context, bufSize, *length))
4743 {
4744 return false;
4745 }
4746
4747 return true;
4748}
4749
4750bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
4751{
4752 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4753}
4754
4755bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4756 GLuint index,
4757 GLenum pname,
4758 GLsizei bufSize,
4759 GLsizei *length,
4760 GLint *params)
4761{
4762 if (!ValidateRobustEntryPoint(context, bufSize))
4763 {
4764 return false;
4765 }
4766
4767 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4768 {
4769 return false;
4770 }
4771
4772 if (!ValidateRobustBufferSize(context, bufSize, *length))
4773 {
4774 return false;
4775 }
4776
4777 return true;
4778}
4779
4780bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
4781{
4782 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4783}
4784
4785bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4786 GLuint index,
4787 GLenum pname,
4788 GLsizei bufSize,
4789 GLsizei *length,
4790 GLuint *params)
4791{
4792 if (!ValidateRobustEntryPoint(context, bufSize))
4793 {
4794 return false;
4795 }
4796
4797 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4798 {
4799 return false;
4800 }
4801
4802 if (!ValidateRobustBufferSize(context, bufSize, *length))
4803 {
4804 return false;
4805 }
4806
4807 return true;
4808}
4809
Geoff Lang6899b872016-10-14 11:30:13 -04004810bool ValidateGetActiveUniformBlockiv(Context *context,
4811 GLuint program,
4812 GLuint uniformBlockIndex,
4813 GLenum pname,
4814 GLint *params)
4815{
4816 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
4817}
4818
4819bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4820 GLuint program,
4821 GLuint uniformBlockIndex,
4822 GLenum pname,
4823 GLsizei bufSize,
4824 GLsizei *length,
4825 GLint *params)
4826{
4827 if (!ValidateRobustEntryPoint(context, bufSize))
4828 {
4829 return false;
4830 }
4831
4832 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4833 {
4834 return false;
4835 }
4836
4837 if (!ValidateRobustBufferSize(context, bufSize, *length))
4838 {
4839 return false;
4840 }
4841
4842 return true;
4843}
4844
Geoff Lang0a9661f2016-10-20 10:59:20 -07004845bool ValidateGetInternalFormativ(Context *context,
4846 GLenum target,
4847 GLenum internalformat,
4848 GLenum pname,
4849 GLsizei bufSize,
4850 GLint *params)
4851{
4852 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4853 nullptr);
4854}
4855
4856bool ValidateGetInternalFormativRobustANGLE(Context *context,
4857 GLenum target,
4858 GLenum internalformat,
4859 GLenum pname,
4860 GLsizei bufSize,
4861 GLsizei *length,
4862 GLint *params)
4863{
4864 if (!ValidateRobustEntryPoint(context, bufSize))
4865 {
4866 return false;
4867 }
4868
4869 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4870 {
4871 return false;
4872 }
4873
4874 if (!ValidateRobustBufferSize(context, bufSize, *length))
4875 {
4876 return false;
4877 }
4878
4879 return true;
4880}
4881
Shao80957d92017-02-20 21:25:59 +08004882bool ValidateVertexFormatBase(ValidationContext *context,
4883 GLuint attribIndex,
4884 GLint size,
4885 GLenum type,
4886 GLboolean pureInteger)
4887{
4888 const Caps &caps = context->getCaps();
4889 if (attribIndex >= caps.maxVertexAttributes)
4890 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004891 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004892 return false;
4893 }
4894
4895 if (size < 1 || size > 4)
4896 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004897 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004898 return false;
Shao80957d92017-02-20 21:25:59 +08004899 }
4900
4901 switch (type)
4902 {
4903 case GL_BYTE:
4904 case GL_UNSIGNED_BYTE:
4905 case GL_SHORT:
4906 case GL_UNSIGNED_SHORT:
4907 break;
4908
4909 case GL_INT:
4910 case GL_UNSIGNED_INT:
4911 if (context->getClientMajorVersion() < 3)
4912 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004913 context->handleError(InvalidEnum()
4914 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004915 return false;
4916 }
4917 break;
4918
4919 case GL_FIXED:
4920 case GL_FLOAT:
4921 if (pureInteger)
4922 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004923 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004924 return false;
4925 }
4926 break;
4927
4928 case GL_HALF_FLOAT:
4929 if (context->getClientMajorVersion() < 3)
4930 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004931 context->handleError(InvalidEnum()
4932 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004933 return false;
4934 }
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_INT_2_10_10_10_REV:
4943 case GL_UNSIGNED_INT_2_10_10_10_REV:
4944 if (context->getClientMajorVersion() < 3)
4945 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004946 context->handleError(InvalidEnum()
4947 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004948 return false;
4949 }
4950 if (pureInteger)
4951 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004952 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004953 return false;
4954 }
4955 if (size != 4)
4956 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004957 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4958 "UNSIGNED_INT_2_10_10_10_REV and "
4959 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004960 return false;
4961 }
4962 break;
4963
4964 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004965 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004966 return false;
4967 }
4968
4969 return true;
4970}
4971
Geoff Lang76e65652017-03-27 14:58:02 -04004972// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4973// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4974// specified clear value and the type of a buffer that is being cleared generates an
4975// INVALID_OPERATION error instead of producing undefined results
4976bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4977 GLint drawbuffer,
4978 const GLenum *validComponentTypes,
4979 size_t validComponentTypeCount)
4980{
4981 const FramebufferAttachment *attachment =
4982 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4983 if (attachment)
4984 {
4985 GLenum componentType = attachment->getFormat().info->componentType;
4986 const GLenum *end = validComponentTypes + validComponentTypeCount;
4987 if (std::find(validComponentTypes, end, componentType) == end)
4988 {
4989 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004990 InvalidOperation()
4991 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004992 return false;
4993 }
4994 }
4995
4996 return true;
4997}
4998
Corentin Wallezb2931602017-04-11 15:58:57 -04004999bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
5000 GLsizei imageSize,
5001 GLsizei dataSize)
5002{
5003 if (!ValidateRobustEntryPoint(context, dataSize))
5004 {
5005 return false;
5006 }
5007
5008 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
5009 if (pixelUnpackBuffer == nullptr)
5010 {
5011 if (dataSize < imageSize)
5012 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005013 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005014 }
5015 }
5016 return true;
5017}
5018
Jamie Madillbe849e42017-05-02 15:49:00 -04005019bool ValidateGetBufferParameterBase(ValidationContext *context,
5020 GLenum target,
5021 GLenum pname,
5022 bool pointerVersion,
5023 GLsizei *numParams)
5024{
5025 if (numParams)
5026 {
5027 *numParams = 0;
5028 }
5029
5030 if (!ValidBufferTarget(context, target))
5031 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005032 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005033 return false;
5034 }
5035
5036 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5037 if (!buffer)
5038 {
5039 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005040 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005041 return false;
5042 }
5043
5044 const Extensions &extensions = context->getExtensions();
5045
5046 switch (pname)
5047 {
5048 case GL_BUFFER_USAGE:
5049 case GL_BUFFER_SIZE:
5050 break;
5051
5052 case GL_BUFFER_ACCESS_OES:
5053 if (!extensions.mapBuffer)
5054 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005055 context->handleError(InvalidEnum()
5056 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005057 return false;
5058 }
5059 break;
5060
5061 case GL_BUFFER_MAPPED:
5062 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5063 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5064 !extensions.mapBufferRange)
5065 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005066 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5067 "GL_OES_mapbuffer or "
5068 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005069 return false;
5070 }
5071 break;
5072
5073 case GL_BUFFER_MAP_POINTER:
5074 if (!pointerVersion)
5075 {
5076 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005077 InvalidEnum()
5078 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005079 return false;
5080 }
5081 break;
5082
5083 case GL_BUFFER_ACCESS_FLAGS:
5084 case GL_BUFFER_MAP_OFFSET:
5085 case GL_BUFFER_MAP_LENGTH:
5086 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5087 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005088 context->handleError(InvalidEnum()
5089 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005090 return false;
5091 }
5092 break;
5093
5094 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005095 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005096 return false;
5097 }
5098
5099 // All buffer parameter queries return one value.
5100 if (numParams)
5101 {
5102 *numParams = 1;
5103 }
5104
5105 return true;
5106}
5107
5108bool ValidateGetRenderbufferParameterivBase(Context *context,
5109 GLenum target,
5110 GLenum pname,
5111 GLsizei *length)
5112{
5113 if (length)
5114 {
5115 *length = 0;
5116 }
5117
5118 if (target != GL_RENDERBUFFER)
5119 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005120 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005121 return false;
5122 }
5123
5124 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5125 if (renderbuffer == nullptr)
5126 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005127 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005128 return false;
5129 }
5130
5131 switch (pname)
5132 {
5133 case GL_RENDERBUFFER_WIDTH:
5134 case GL_RENDERBUFFER_HEIGHT:
5135 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5136 case GL_RENDERBUFFER_RED_SIZE:
5137 case GL_RENDERBUFFER_GREEN_SIZE:
5138 case GL_RENDERBUFFER_BLUE_SIZE:
5139 case GL_RENDERBUFFER_ALPHA_SIZE:
5140 case GL_RENDERBUFFER_DEPTH_SIZE:
5141 case GL_RENDERBUFFER_STENCIL_SIZE:
5142 break;
5143
5144 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5145 if (!context->getExtensions().framebufferMultisample)
5146 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005147 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005148 return false;
5149 }
5150 break;
5151
5152 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005153 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005154 return false;
5155 }
5156
5157 if (length)
5158 {
5159 *length = 1;
5160 }
5161 return true;
5162}
5163
5164bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5165{
5166 if (length)
5167 {
5168 *length = 0;
5169 }
5170
5171 if (GetValidShader(context, shader) == nullptr)
5172 {
5173 return false;
5174 }
5175
5176 switch (pname)
5177 {
5178 case GL_SHADER_TYPE:
5179 case GL_DELETE_STATUS:
5180 case GL_COMPILE_STATUS:
5181 case GL_INFO_LOG_LENGTH:
5182 case GL_SHADER_SOURCE_LENGTH:
5183 break;
5184
5185 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5186 if (!context->getExtensions().translatedShaderSource)
5187 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005188 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005189 return false;
5190 }
5191 break;
5192
5193 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005194 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005195 return false;
5196 }
5197
5198 if (length)
5199 {
5200 *length = 1;
5201 }
5202 return true;
5203}
5204
5205bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
5206{
5207 if (length)
5208 {
5209 *length = 0;
5210 }
5211
5212 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5213 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005214 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005215 return false;
5216 }
5217
5218 if (context->getTargetTexture(target) == nullptr)
5219 {
5220 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005221 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005222 return false;
5223 }
5224
5225 switch (pname)
5226 {
5227 case GL_TEXTURE_MAG_FILTER:
5228 case GL_TEXTURE_MIN_FILTER:
5229 case GL_TEXTURE_WRAP_S:
5230 case GL_TEXTURE_WRAP_T:
5231 break;
5232
5233 case GL_TEXTURE_USAGE_ANGLE:
5234 if (!context->getExtensions().textureUsage)
5235 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005236 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005237 return false;
5238 }
5239 break;
5240
5241 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5242 if (!context->getExtensions().textureFilterAnisotropic)
5243 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005244 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005245 return false;
5246 }
5247 break;
5248
5249 case GL_TEXTURE_IMMUTABLE_FORMAT:
5250 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5251 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005252 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005253 return false;
5254 }
5255 break;
5256
5257 case GL_TEXTURE_WRAP_R:
5258 case GL_TEXTURE_IMMUTABLE_LEVELS:
5259 case GL_TEXTURE_SWIZZLE_R:
5260 case GL_TEXTURE_SWIZZLE_G:
5261 case GL_TEXTURE_SWIZZLE_B:
5262 case GL_TEXTURE_SWIZZLE_A:
5263 case GL_TEXTURE_BASE_LEVEL:
5264 case GL_TEXTURE_MAX_LEVEL:
5265 case GL_TEXTURE_MIN_LOD:
5266 case GL_TEXTURE_MAX_LOD:
5267 case GL_TEXTURE_COMPARE_MODE:
5268 case GL_TEXTURE_COMPARE_FUNC:
5269 if (context->getClientMajorVersion() < 3)
5270 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005271 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005272 return false;
5273 }
5274 break;
5275
5276 case GL_TEXTURE_SRGB_DECODE_EXT:
5277 if (!context->getExtensions().textureSRGBDecode)
5278 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005279 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005280 return false;
5281 }
5282 break;
5283
5284 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005285 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005286 return false;
5287 }
5288
5289 if (length)
5290 {
5291 *length = 1;
5292 }
5293 return true;
5294}
5295
5296bool ValidateGetVertexAttribBase(Context *context,
5297 GLuint index,
5298 GLenum pname,
5299 GLsizei *length,
5300 bool pointer,
5301 bool pureIntegerEntryPoint)
5302{
5303 if (length)
5304 {
5305 *length = 0;
5306 }
5307
5308 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5309 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005310 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005311 return false;
5312 }
5313
5314 if (index >= context->getCaps().maxVertexAttributes)
5315 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005316 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005317 return false;
5318 }
5319
5320 if (pointer)
5321 {
5322 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5323 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005324 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005325 return false;
5326 }
5327 }
5328 else
5329 {
5330 switch (pname)
5331 {
5332 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5333 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5334 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5335 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5336 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5337 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5338 case GL_CURRENT_VERTEX_ATTRIB:
5339 break;
5340
5341 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5342 static_assert(
5343 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5344 "ANGLE extension enums not equal to GL enums.");
5345 if (context->getClientMajorVersion() < 3 &&
5346 !context->getExtensions().instancedArrays)
5347 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005348 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5349 "requires OpenGL ES 3.0 or "
5350 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005351 return false;
5352 }
5353 break;
5354
5355 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5356 if (context->getClientMajorVersion() < 3)
5357 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005358 context->handleError(
5359 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005360 return false;
5361 }
5362 break;
5363
5364 case GL_VERTEX_ATTRIB_BINDING:
5365 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5366 if (context->getClientVersion() < ES_3_1)
5367 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005368 context->handleError(InvalidEnum()
5369 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005370 return false;
5371 }
5372 break;
5373
5374 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005375 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005376 return false;
5377 }
5378 }
5379
5380 if (length)
5381 {
5382 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5383 {
5384 *length = 4;
5385 }
5386 else
5387 {
5388 *length = 1;
5389 }
5390 }
5391
5392 return true;
5393}
5394
Jamie Madill4928b7c2017-06-20 12:57:39 -04005395bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005396 GLint x,
5397 GLint y,
5398 GLsizei width,
5399 GLsizei height,
5400 GLenum format,
5401 GLenum type,
5402 GLsizei bufSize,
5403 GLsizei *length,
5404 GLsizei *columns,
5405 GLsizei *rows,
5406 void *pixels)
5407{
5408 if (length != nullptr)
5409 {
5410 *length = 0;
5411 }
5412 if (rows != nullptr)
5413 {
5414 *rows = 0;
5415 }
5416 if (columns != nullptr)
5417 {
5418 *columns = 0;
5419 }
5420
5421 if (width < 0 || height < 0)
5422 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005423 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005424 return false;
5425 }
5426
5427 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5428
5429 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5430 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005431 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005432 return false;
5433 }
5434
5435 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5436 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005437 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005438 return false;
5439 }
5440
5441 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5442 ASSERT(framebuffer);
5443
5444 if (framebuffer->getReadBufferState() == GL_NONE)
5445 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005446 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005447 return false;
5448 }
5449
5450 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5451 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5452 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5453 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5454 // situation is an application error that would lead to a crash in ANGLE.
5455 if (readBuffer == nullptr)
5456 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005457 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005458 return false;
5459 }
5460
Martin Radev28031682017-07-28 14:47:56 +03005461 // ANGLE_multiview, Revision 1:
5462 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5463 // current read framebuffer is not NONE.
5464 if (readBuffer->getMultiviewLayout() != GL_NONE)
5465 {
5466 context->handleError(InvalidFramebufferOperation()
5467 << "Attempting to read from a multi-view framebuffer.");
5468 return false;
5469 }
5470
Geoff Lang280ba992017-04-18 16:30:58 -04005471 if (context->getExtensions().webglCompatibility)
5472 {
5473 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5474 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5475 // and type before validating the combination of format and type. However, the
5476 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5477 // verifies that GL_INVALID_OPERATION is generated.
5478 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5479 // dEQP/WebGL.
5480 if (!ValidReadPixelsFormatEnum(context, format))
5481 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005482 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005483 return false;
5484 }
5485
5486 if (!ValidReadPixelsTypeEnum(context, type))
5487 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005488 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005489 return false;
5490 }
5491 }
5492
Jamie Madill4928b7c2017-06-20 12:57:39 -04005493 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5494 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005495 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5496
5497 bool validFormatTypeCombination =
5498 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5499
5500 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5501 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005502 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005503 return false;
5504 }
5505
5506 // Check for pixel pack buffer related API errors
5507 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5508 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5509 {
5510 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005511 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005512 return false;
5513 }
5514
5515 // .. the data would be packed to the buffer object such that the memory writes required
5516 // would exceed the data store size.
5517 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5518 const gl::Extents size(width, height, 1);
5519 const auto &pack = context->getGLState().getPackState();
5520
5521 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5522 if (endByteOrErr.isError())
5523 {
5524 context->handleError(endByteOrErr.getError());
5525 return false;
5526 }
5527
5528 size_t endByte = endByteOrErr.getResult();
5529 if (bufSize >= 0)
5530 {
5531 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5532 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005533 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005534 return false;
5535 }
5536 }
5537
5538 if (pixelPackBuffer != nullptr)
5539 {
5540 CheckedNumeric<size_t> checkedEndByte(endByte);
5541 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5542 checkedEndByte += checkedOffset;
5543
5544 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5545 {
5546 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005547 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005548 return false;
5549 }
5550 }
5551
5552 if (pixelPackBuffer == nullptr && length != nullptr)
5553 {
5554 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5555 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005556 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005557 return false;
5558 }
5559
5560 *length = static_cast<GLsizei>(endByte);
5561 }
5562
5563 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5564 angle::CheckedNumeric<int> clippedExtent(length);
5565 if (start < 0)
5566 {
5567 // "subtract" the area that is less than 0
5568 clippedExtent += start;
5569 }
5570
5571 const int readExtent = start + length;
5572 if (readExtent > bufferSize)
5573 {
5574 // Subtract the region to the right of the read buffer
5575 clippedExtent -= (readExtent - bufferSize);
5576 }
5577
5578 if (!clippedExtent.IsValid())
5579 {
5580 return 0;
5581 }
5582
5583 return std::max(clippedExtent.ValueOrDie(), 0);
5584 };
5585
5586 if (columns != nullptr)
5587 {
5588 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5589 }
5590
5591 if (rows != nullptr)
5592 {
5593 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5594 }
5595
5596 return true;
5597}
5598
5599template <typename ParamType>
5600bool ValidateTexParameterBase(Context *context,
5601 GLenum target,
5602 GLenum pname,
5603 GLsizei bufSize,
5604 const ParamType *params)
5605{
5606 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5607 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005608 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005609 return false;
5610 }
5611
5612 if (context->getTargetTexture(target) == nullptr)
5613 {
5614 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005615 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005616 return false;
5617 }
5618
5619 const GLsizei minBufSize = 1;
5620 if (bufSize >= 0 && bufSize < minBufSize)
5621 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005622 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005623 return false;
5624 }
5625
5626 switch (pname)
5627 {
5628 case GL_TEXTURE_WRAP_R:
5629 case GL_TEXTURE_SWIZZLE_R:
5630 case GL_TEXTURE_SWIZZLE_G:
5631 case GL_TEXTURE_SWIZZLE_B:
5632 case GL_TEXTURE_SWIZZLE_A:
5633 case GL_TEXTURE_BASE_LEVEL:
5634 case GL_TEXTURE_MAX_LEVEL:
5635 case GL_TEXTURE_COMPARE_MODE:
5636 case GL_TEXTURE_COMPARE_FUNC:
5637 case GL_TEXTURE_MIN_LOD:
5638 case GL_TEXTURE_MAX_LOD:
5639 if (context->getClientMajorVersion() < 3)
5640 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005641 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005642 return false;
5643 }
5644 if (target == GL_TEXTURE_EXTERNAL_OES &&
5645 !context->getExtensions().eglImageExternalEssl3)
5646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005647 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5648 "available without "
5649 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005650 return false;
5651 }
5652 break;
5653
5654 default:
5655 break;
5656 }
5657
JiangYizhou4cff8d62017-07-06 14:54:09 +08005658 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5659 {
5660 switch (pname)
5661 {
5662 case GL_TEXTURE_MIN_FILTER:
5663 case GL_TEXTURE_MAG_FILTER:
5664 case GL_TEXTURE_WRAP_S:
5665 case GL_TEXTURE_WRAP_T:
5666 case GL_TEXTURE_WRAP_R:
5667 case GL_TEXTURE_MIN_LOD:
5668 case GL_TEXTURE_MAX_LOD:
5669 case GL_TEXTURE_COMPARE_MODE:
5670 case GL_TEXTURE_COMPARE_FUNC:
5671 context->handleError(InvalidEnum()
5672 << "Invalid parameter for 2D multisampled textures.");
5673 return false;
5674 }
5675 }
5676
Jamie Madillbe849e42017-05-02 15:49:00 -04005677 switch (pname)
5678 {
5679 case GL_TEXTURE_WRAP_S:
5680 case GL_TEXTURE_WRAP_T:
5681 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005682 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005683 bool restrictedWrapModes =
5684 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5685 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5686 {
5687 return false;
5688 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005689 }
5690 break;
5691
5692 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005693 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005694 bool restrictedMinFilter =
5695 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5696 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5697 {
5698 return false;
5699 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005700 }
5701 break;
5702
5703 case GL_TEXTURE_MAG_FILTER:
5704 if (!ValidateTextureMagFilterValue(context, params))
5705 {
5706 return false;
5707 }
5708 break;
5709
5710 case GL_TEXTURE_USAGE_ANGLE:
5711 switch (ConvertToGLenum(params[0]))
5712 {
5713 case GL_NONE:
5714 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5715 break;
5716
5717 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005718 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005719 return false;
5720 }
5721 break;
5722
5723 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5724 if (!context->getExtensions().textureFilterAnisotropic)
5725 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005726 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005727 return false;
5728 }
5729
5730 // we assume the parameter passed to this validation method is truncated, not rounded
5731 if (params[0] < 1)
5732 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005733 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005734 return false;
5735 }
5736 break;
5737
5738 case GL_TEXTURE_MIN_LOD:
5739 case GL_TEXTURE_MAX_LOD:
5740 // any value is permissible
5741 break;
5742
5743 case GL_TEXTURE_COMPARE_MODE:
5744 if (!ValidateTextureCompareModeValue(context, params))
5745 {
5746 return false;
5747 }
5748 break;
5749
5750 case GL_TEXTURE_COMPARE_FUNC:
5751 if (!ValidateTextureCompareFuncValue(context, params))
5752 {
5753 return false;
5754 }
5755 break;
5756
5757 case GL_TEXTURE_SWIZZLE_R:
5758 case GL_TEXTURE_SWIZZLE_G:
5759 case GL_TEXTURE_SWIZZLE_B:
5760 case GL_TEXTURE_SWIZZLE_A:
5761 switch (ConvertToGLenum(params[0]))
5762 {
5763 case GL_RED:
5764 case GL_GREEN:
5765 case GL_BLUE:
5766 case GL_ALPHA:
5767 case GL_ZERO:
5768 case GL_ONE:
5769 break;
5770
5771 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005772 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005773 return false;
5774 }
5775 break;
5776
5777 case GL_TEXTURE_BASE_LEVEL:
5778 if (params[0] < 0)
5779 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005780 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005781 return false;
5782 }
5783 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5784 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005785 context->handleError(InvalidOperation()
5786 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005787 return false;
5788 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005789 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5790 {
5791 context->handleError(InvalidOperation()
5792 << "Base level must be 0 for multisampled textures.");
5793 return false;
5794 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005795 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5796 {
5797 context->handleError(InvalidOperation()
5798 << "Base level must be 0 for rectangle textures.");
5799 return false;
5800 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005801 break;
5802
5803 case GL_TEXTURE_MAX_LEVEL:
5804 if (params[0] < 0)
5805 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005806 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005807 return false;
5808 }
5809 break;
5810
5811 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5812 if (context->getClientVersion() < Version(3, 1))
5813 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005814 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005815 return false;
5816 }
5817 switch (ConvertToGLenum(params[0]))
5818 {
5819 case GL_DEPTH_COMPONENT:
5820 case GL_STENCIL_INDEX:
5821 break;
5822
5823 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005824 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005825 return false;
5826 }
5827 break;
5828
5829 case GL_TEXTURE_SRGB_DECODE_EXT:
5830 if (!ValidateTextureSRGBDecodeValue(context, params))
5831 {
5832 return false;
5833 }
5834 break;
5835
5836 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005837 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005838 return false;
5839 }
5840
5841 return true;
5842}
5843
5844template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5845template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5846
Jamie Madillc29968b2016-01-20 11:17:23 -05005847} // namespace gl