blob: eeefa3835d0687d7586f5fb1ed8ecea66114d8e8 [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 Lang0a9661f2016-10-20 10:59:20 -0700533bool ValidateGetInternalFormativBase(Context *context,
534 GLenum target,
535 GLenum internalformat,
536 GLenum pname,
537 GLsizei bufSize,
538 GLsizei *numParams)
539{
540 if (numParams)
541 {
542 *numParams = 0;
543 }
544
545 if (context->getClientMajorVersion() < 3)
546 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500547 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700548 return false;
549 }
550
551 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
552 if (!formatCaps.renderable)
553 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500554 context->handleError(InvalidEnum() << "Internal format is not renderable.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700555 return false;
556 }
557
558 switch (target)
559 {
560 case GL_RENDERBUFFER:
561 break;
562
JiangYizhoubddc46b2016-12-09 09:50:51 +0800563 case GL_TEXTURE_2D_MULTISAMPLE:
564 if (context->getClientVersion() < ES_3_1)
565 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500566 context->handleError(InvalidOperation()
567 << "Texture target requires at least OpenGL ES 3.1.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800568 return false;
569 }
570 break;
571
Geoff Lang0a9661f2016-10-20 10:59:20 -0700572 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700573 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
Geoff Lang0a9661f2016-10-20 10:59:20 -0700574 return false;
575 }
576
577 if (bufSize < 0)
578 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700579 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
Geoff Lang0a9661f2016-10-20 10:59:20 -0700580 return false;
581 }
582
583 GLsizei maxWriteParams = 0;
584 switch (pname)
585 {
586 case GL_NUM_SAMPLE_COUNTS:
587 maxWriteParams = 1;
588 break;
589
590 case GL_SAMPLES:
591 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
592 break;
593
594 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700595 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang0a9661f2016-10-20 10:59:20 -0700596 return false;
597 }
598
599 if (numParams)
600 {
601 // glGetInternalFormativ will not overflow bufSize
602 *numParams = std::min(bufSize, maxWriteParams);
603 }
604
605 return true;
606}
607
Jamie Madillc1d770e2017-04-13 17:31:24 -0400608bool ValidateUniformCommonBase(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500609 gl::Program *program,
610 GLint location,
611 GLsizei count,
612 const LinkedUniform **uniformOut)
613{
614 // TODO(Jiajia): Add image uniform check in future.
615 if (count < 0)
616 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700617 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500618 return false;
619 }
620
Brandon Jones6cad5662017-06-14 13:25:13 -0700621 if (!program)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500622 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700623 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
624 return false;
625 }
626
627 if (!program->isLinked())
628 {
629 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500630 return false;
631 }
632
633 if (location == -1)
634 {
635 // Silently ignore the uniform command
636 return false;
637 }
638
639 const auto &uniformLocations = program->getUniformLocations();
Jamie Madillbe849e42017-05-02 15:49:00 -0400640 size_t castedLocation = static_cast<size_t>(location);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500641 if (castedLocation >= uniformLocations.size())
642 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500643 context->handleError(InvalidOperation() << "Invalid uniform location");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500644 return false;
645 }
646
647 const auto &uniformLocation = uniformLocations[castedLocation];
648 if (uniformLocation.ignored)
649 {
650 // Silently ignore the uniform command
651 return false;
652 }
653
654 if (!uniformLocation.used)
655 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500656 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500657 return false;
658 }
659
660 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
661
662 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
663 if (!uniform.isArray() && count > 1)
664 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500665 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500666 return false;
667 }
668
669 *uniformOut = &uniform;
670 return true;
671}
672
Frank Henigman999b0fd2017-02-02 21:45:55 -0500673bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -0500674 GLenum uniformType,
675 GLsizei count,
676 const GLint *value)
677{
678 // Value type is GL_INT, because we only get here from glUniform1i{v}.
679 // It is compatible with INT or BOOL.
680 // Do these cheap tests first, for a little extra speed.
681 if (GL_INT == uniformType || GL_BOOL == uniformType)
682 {
683 return true;
684 }
685
686 if (IsSamplerType(uniformType))
687 {
Frank Henigman999b0fd2017-02-02 21:45:55 -0500688 // Check that the values are in range.
689 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
690 for (GLsizei i = 0; i < count; ++i)
691 {
692 if (value[i] < 0 || value[i] >= max)
693 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500694 context->handleError(InvalidValue() << "sampler uniform value out of range");
Frank Henigman999b0fd2017-02-02 21:45:55 -0500695 return false;
696 }
697 }
Frank Henigmana98a6472017-02-02 21:38:32 -0500698 return true;
699 }
700
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500701 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmana98a6472017-02-02 21:38:32 -0500702 return false;
703}
704
Jamie Madillc1d770e2017-04-13 17:31:24 -0400705bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500706{
707 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -0500708 // Do the cheaper test first, for a little extra speed.
709 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500710 {
711 return true;
712 }
713
Brandon Jonesafa75152017-07-21 13:11:29 -0700714 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500715 return false;
716}
717
Jamie Madillc1d770e2017-04-13 17:31:24 -0400718bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500719{
720 // Check that the value type is compatible with uniform type.
721 if (valueType == uniformType)
722 {
723 return true;
724 }
725
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500726 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500727 return false;
728}
729
Geoff Lange0cff192017-05-30 13:04:56 -0400730bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
731{
732 const Program *program = context->getGLState().getProgram();
733 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
734
735 const auto &programOutputTypes = program->getOutputVariableTypes();
736 for (size_t drawBufferIdx = 0; drawBufferIdx < programOutputTypes.size(); drawBufferIdx++)
737 {
738 GLenum outputType = programOutputTypes[drawBufferIdx];
739 GLenum inputType = framebuffer->getDrawbufferWriteType(drawBufferIdx);
740 if (outputType != GL_NONE && inputType != GL_NONE && inputType != outputType)
741 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500742 context->handleError(InvalidOperation() << "Fragment shader output type does not "
743 "match the bound framebuffer attachment "
744 "type.");
Geoff Lange0cff192017-05-30 13:04:56 -0400745 return false;
746 }
747 }
748
749 return true;
750}
751
Geoff Lang9ab5b822017-05-30 16:19:23 -0400752bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
753{
754 const Program *program = context->getGLState().getProgram();
755 const VertexArray *vao = context->getGLState().getVertexArray();
756
757 for (const auto &shaderAttribute : program->getAttributes())
758 {
Geoff Lang69df2422017-07-05 12:42:31 -0400759 // gl_VertexID and gl_InstanceID are active attributes but don't have a bound attribute.
760 if (shaderAttribute.isBuiltIn())
761 {
762 continue;
763 }
764
Geoff Lang9ab5b822017-05-30 16:19:23 -0400765 GLenum shaderInputType = VariableComponentType(shaderAttribute.type);
766
767 const auto &attrib = vao->getVertexAttribute(shaderAttribute.location);
768 const auto &currentValue =
769 context->getGLState().getVertexAttribCurrentValue(shaderAttribute.location);
770 GLenum vertexType = attrib.enabled ? GetVertexAttributeBaseType(attrib) : currentValue.Type;
771
772 if (shaderInputType != GL_NONE && vertexType != GL_NONE && shaderInputType != vertexType)
773 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500774 context->handleError(InvalidOperation() << "Vertex shader input type does not "
775 "match the type of the bound vertex "
776 "attribute.");
Geoff Lang9ab5b822017-05-30 16:19:23 -0400777 return false;
778 }
779 }
780
781 return true;
782}
783
Geoff Langf41a7152016-09-19 15:11:17 -0400784} // anonymous namespace
785
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500786bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400787{
Jamie Madilld7460c72014-01-21 16:38:14 -0500788 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400789 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800790 case GL_TEXTURE_2D:
791 case GL_TEXTURE_CUBE_MAP:
792 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400793
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400794 case GL_TEXTURE_RECTANGLE_ANGLE:
795 return context->getExtensions().textureRectangle;
796
He Yunchaoced53ae2016-11-29 15:00:51 +0800797 case GL_TEXTURE_3D:
798 case GL_TEXTURE_2D_ARRAY:
799 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500800
He Yunchaoced53ae2016-11-29 15:00:51 +0800801 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800802 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400803
He Yunchaoced53ae2016-11-29 15:00:51 +0800804 default:
805 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500806 }
Jamie Madill35d15012013-10-07 10:46:37 -0400807}
808
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500809bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
810{
811 switch (target)
812 {
813 case GL_TEXTURE_2D:
814 case GL_TEXTURE_CUBE_MAP:
815 return true;
816
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400817 case GL_TEXTURE_RECTANGLE_ANGLE:
818 return context->getExtensions().textureRectangle;
819
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500820 default:
821 return false;
822 }
823}
824
825bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
826{
827 switch (target)
828 {
829 case GL_TEXTURE_3D:
830 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300831 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500832
833 default:
834 return false;
835 }
836}
837
Ian Ewellbda75592016-04-18 17:25:54 -0400838// Most texture GL calls are not compatible with external textures, so we have a separate validation
839// function for use in the GL calls that do
840bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
841{
842 return (target == GL_TEXTURE_EXTERNAL_OES) &&
843 (context->getExtensions().eglImageExternal ||
844 context->getExtensions().eglStreamConsumerExternal);
845}
846
Shannon Woods4dfed832014-03-17 20:03:39 -0400847// This function differs from ValidTextureTarget in that the target must be
848// usable as the destination of a 2D operation-- so a cube face is valid, but
849// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400850// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500851bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400852{
853 switch (target)
854 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800855 case GL_TEXTURE_2D:
856 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
857 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
858 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
859 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
860 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
861 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
862 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400863 case GL_TEXTURE_RECTANGLE_ANGLE:
864 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800865 default:
866 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500867 }
868}
869
Jamie Madillbe849e42017-05-02 15:49:00 -0400870bool ValidateDrawElementsInstancedBase(ValidationContext *context,
871 GLenum mode,
872 GLsizei count,
873 GLenum type,
874 const GLvoid *indices,
875 GLsizei primcount)
876{
877 if (primcount < 0)
878 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700879 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400880 return false;
881 }
882
883 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
884 {
885 return false;
886 }
887
888 // No-op zero primitive count
889 return (primcount > 0);
890}
891
892bool ValidateDrawArraysInstancedBase(Context *context,
893 GLenum mode,
894 GLint first,
895 GLsizei count,
896 GLsizei primcount)
897{
898 if (primcount < 0)
899 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700900 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400901 return false;
902 }
903
904 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
905 {
906 return false;
907 }
908
909 // No-op if zero primitive count
910 return (primcount > 0);
911}
912
Corentin Wallez0dc97812017-06-22 14:38:44 -0400913bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400914{
915 // Verify there is at least one active attribute with a divisor of zero
916 const State &state = context->getGLState();
917
918 Program *program = state.getProgram();
919
920 const auto &attribs = state.getVertexArray()->getVertexAttributes();
921 const auto &bindings = state.getVertexArray()->getVertexBindings();
922 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
923 {
924 const VertexAttribute &attrib = attribs[attributeIndex];
925 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300926 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400927 {
928 return true;
929 }
930 }
931
Brandon Jonesafa75152017-07-21 13:11:29 -0700932 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400933 return false;
934}
935
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500936bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
937{
938 switch (target)
939 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800940 case GL_TEXTURE_3D:
941 case GL_TEXTURE_2D_ARRAY:
942 return true;
943 default:
944 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400945 }
946}
947
He Yunchao11b038b2016-11-22 21:24:04 +0800948bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
949{
950 switch (target)
951 {
952 case GL_TEXTURE_2D:
953 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
954 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
955 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
956 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
957 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
958 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
959 case GL_TEXTURE_3D:
960 case GL_TEXTURE_2D_ARRAY:
961 case GL_TEXTURE_2D_MULTISAMPLE:
962 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400963 case GL_TEXTURE_RECTANGLE_ANGLE:
964 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800965 default:
966 return false;
967 }
968}
969
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500970bool ValidFramebufferTarget(GLenum target)
971{
He Yunchaoced53ae2016-11-29 15:00:51 +0800972 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
973 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400974 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500975
976 switch (target)
977 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800978 case GL_FRAMEBUFFER:
979 return true;
980 case GL_READ_FRAMEBUFFER:
981 return true;
982 case GL_DRAW_FRAMEBUFFER:
983 return true;
984 default:
985 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500986 }
987}
988
Jamie Madill29639852016-09-02 15:00:09 -0400989bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -0500990{
991 switch (target)
992 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800993 case GL_ARRAY_BUFFER:
994 case GL_ELEMENT_ARRAY_BUFFER:
995 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -0500996
He Yunchaoced53ae2016-11-29 15:00:51 +0800997 case GL_PIXEL_PACK_BUFFER:
998 case GL_PIXEL_UNPACK_BUFFER:
999 return (context->getExtensions().pixelBufferObject ||
1000 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001001
He Yunchaoced53ae2016-11-29 15:00:51 +08001002 case GL_COPY_READ_BUFFER:
1003 case GL_COPY_WRITE_BUFFER:
1004 case GL_TRANSFORM_FEEDBACK_BUFFER:
1005 case GL_UNIFORM_BUFFER:
1006 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001007
He Yunchaoced53ae2016-11-29 15:00:51 +08001008 case GL_ATOMIC_COUNTER_BUFFER:
1009 case GL_SHADER_STORAGE_BUFFER:
1010 case GL_DRAW_INDIRECT_BUFFER:
1011 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001012 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001013
He Yunchaoced53ae2016-11-29 15:00:51 +08001014 default:
1015 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001016 }
1017}
1018
Jamie Madillc29968b2016-01-20 11:17:23 -05001019bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001020{
Jamie Madillc29968b2016-01-20 11:17:23 -05001021 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001022 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001023 switch (target)
1024 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001025 case GL_TEXTURE_2D:
1026 maxDimension = caps.max2DTextureSize;
1027 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001028 case GL_TEXTURE_CUBE_MAP:
1029 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1030 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1031 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1032 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1033 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1034 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1035 maxDimension = caps.maxCubeMapTextureSize;
1036 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001037 case GL_TEXTURE_RECTANGLE_ANGLE:
1038 return level == 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08001039 case GL_TEXTURE_3D:
1040 maxDimension = caps.max3DTextureSize;
1041 break;
1042 case GL_TEXTURE_2D_ARRAY:
1043 maxDimension = caps.max2DTextureSize;
1044 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001045 case GL_TEXTURE_2D_MULTISAMPLE:
1046 maxDimension = caps.max2DTextureSize;
1047 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001048 default:
1049 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001050 }
1051
Brandon Jones6cad5662017-06-14 13:25:13 -07001052 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -04001053}
1054
Brandon Jones6cad5662017-06-14 13:25:13 -07001055bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001056 GLenum target,
1057 GLint level,
1058 GLsizei width,
1059 GLsizei height,
1060 GLsizei depth,
1061 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001062{
Brandon Jones6cad5662017-06-14 13:25:13 -07001063 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -04001064 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001065 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -04001066 return false;
1067 }
Austin Kinross08528e12015-10-07 16:24:40 -07001068 // TexSubImage parameters can be NPOT without textureNPOT extension,
1069 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001070 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001071 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001072 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001073 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001074 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001075 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -04001076 return false;
1077 }
1078
1079 if (!ValidMipLevel(context, target, level))
1080 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001081 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -04001082 return false;
1083 }
1084
1085 return true;
1086}
1087
Geoff Lang0d8b7242015-09-09 14:56:53 -04001088bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1089{
1090 // List of compressed format that require that the texture size is smaller than or a multiple of
1091 // the compressed block size.
1092 switch (internalFormat)
1093 {
1094 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1095 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1096 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1097 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langfff7a7d2017-06-02 10:39:17 -04001098 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
1099 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
1100 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
1101 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
Minmin Gonge3939b92015-12-01 15:36:51 -08001102 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001103 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1104 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1105 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1106 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1107 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
1108 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001109 return true;
1110
1111 default:
1112 return false;
1113 }
1114}
1115
Geoff Lang966c9402017-04-18 12:38:27 -04001116bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
1117{
1118 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
1119 (size % blockSize == 0);
1120}
1121
Jamie Madillc29968b2016-01-20 11:17:23 -05001122bool ValidCompressedImageSize(const ValidationContext *context,
1123 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -04001124 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -05001125 GLsizei width,
1126 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001127{
Geoff Langca271392017-04-05 12:30:00 -04001128 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -04001129 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001130 {
1131 return false;
1132 }
1133
Geoff Lang966c9402017-04-18 12:38:27 -04001134 if (width < 0 || height < 0)
1135 {
1136 return false;
1137 }
1138
1139 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1140 {
1141 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
1142 // block size for level 0 but WebGL disallows this.
1143 bool smallerThanBlockSizeAllowed =
1144 level > 0 || !context->getExtensions().webglCompatibility;
1145
1146 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
1147 smallerThanBlockSizeAllowed) ||
1148 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
1149 smallerThanBlockSizeAllowed))
1150 {
1151 return false;
1152 }
1153 }
1154
1155 return true;
1156}
1157
1158bool ValidCompressedSubImageSize(const ValidationContext *context,
1159 GLenum internalFormat,
1160 GLint xoffset,
1161 GLint yoffset,
1162 GLsizei width,
1163 GLsizei height,
1164 size_t textureWidth,
1165 size_t textureHeight)
1166{
1167 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
1168 if (!formatInfo.compressed)
1169 {
1170 return false;
1171 }
1172
Geoff Lang44ff5a72017-02-03 15:15:43 -05001173 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001174 {
1175 return false;
1176 }
1177
Geoff Lang0d8b7242015-09-09 14:56:53 -04001178 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1179 {
Geoff Lang44ff5a72017-02-03 15:15:43 -05001180 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -04001181 yoffset % formatInfo.compressedBlockHeight != 0)
1182 {
1183 return false;
1184 }
1185
1186 // Allowed to either have data that is a multiple of block size or is smaller than the block
1187 // size but fills the entire mip
1188 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
1189 static_cast<size_t>(width) == textureWidth &&
1190 static_cast<size_t>(height) == textureHeight;
1191 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
1192 (height % formatInfo.compressedBlockHeight) == 0;
1193 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -04001194 {
1195 return false;
1196 }
1197 }
1198
Geoff Langd4f180b2013-09-24 13:57:44 -04001199 return true;
1200}
1201
Geoff Langff5b2d52016-09-07 11:32:23 -04001202bool ValidImageDataSize(ValidationContext *context,
1203 GLenum textureTarget,
1204 GLsizei width,
1205 GLsizei height,
1206 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -04001207 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -04001208 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001209 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001210 GLsizei imageSize)
1211{
1212 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1213 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1214 {
1215 // Checks are not required
1216 return true;
1217 }
1218
1219 // ...the data would be unpacked from the buffer object such that the memory reads required
1220 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -04001221 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
1222 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -04001223 const gl::Extents size(width, height, depth);
1224 const auto &unpack = context->getGLState().getUnpackState();
1225
1226 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1227 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1228 if (endByteOrErr.isError())
1229 {
1230 context->handleError(endByteOrErr.getError());
1231 return false;
1232 }
1233
1234 GLuint endByte = endByteOrErr.getResult();
1235
1236 if (pixelUnpackBuffer)
1237 {
1238 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1239 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1240 checkedEndByte += checkedOffset;
1241
1242 if (!checkedEndByte.IsValid() ||
1243 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1244 {
1245 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001246 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04001247 return false;
1248 }
1249 }
1250 else
1251 {
1252 ASSERT(imageSize >= 0);
1253 if (pixels == nullptr && imageSize != 0)
1254 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001255 context->handleError(InvalidOperation()
1256 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001257 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001258 }
1259
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001260 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001261 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001262 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001263 return false;
1264 }
1265 }
1266
1267 return true;
1268}
1269
Geoff Lang37dde692014-01-31 16:34:54 -05001270bool ValidQueryType(const Context *context, GLenum queryType)
1271{
He Yunchaoced53ae2016-11-29 15:00:51 +08001272 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1273 "GL extension enums not equal.");
1274 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1275 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001276
1277 switch (queryType)
1278 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001279 case GL_ANY_SAMPLES_PASSED:
1280 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1281 return true;
1282 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1283 return (context->getClientMajorVersion() >= 3);
1284 case GL_TIME_ELAPSED_EXT:
1285 return context->getExtensions().disjointTimerQuery;
1286 case GL_COMMANDS_COMPLETED_CHROMIUM:
1287 return context->getExtensions().syncQuery;
1288 default:
1289 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001290 }
1291}
1292
Geoff Lang2d62ab72017-03-23 16:54:40 -04001293bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
1294 GLenum type,
1295 GLboolean normalized,
1296 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001297 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001298 bool pureInteger)
1299{
1300 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001301 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1302 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1303 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1304 // parameter exceeds 255.
1305 constexpr GLsizei kMaxWebGLStride = 255;
1306 if (stride > kMaxWebGLStride)
1307 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001308 context->handleError(InvalidValue()
1309 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001310 return false;
1311 }
1312
1313 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1314 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1315 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1316 // or an INVALID_OPERATION error is generated.
1317 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1318 size_t typeSize = GetVertexFormatTypeSize(internalType);
1319
1320 ASSERT(isPow2(typeSize) && typeSize > 0);
1321 size_t sizeMask = (typeSize - 1);
1322 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1323 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001324 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001325 return false;
1326 }
1327
1328 if ((stride & sizeMask) != 0)
1329 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001330 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001331 return false;
1332 }
1333
1334 return true;
1335}
1336
Jamie Madillef300b12016-10-07 15:12:09 -04001337Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001338{
He Yunchaoced53ae2016-11-29 15:00:51 +08001339 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1340 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1341 // or program object and INVALID_OPERATION if the provided name identifies an object
1342 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001343
Dian Xiang769769a2015-09-09 15:20:08 -07001344 Program *validProgram = context->getProgram(id);
1345
1346 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001347 {
Dian Xiang769769a2015-09-09 15:20:08 -07001348 if (context->getShader(id))
1349 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001350 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001351 }
1352 else
1353 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001354 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001355 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001356 }
Dian Xiang769769a2015-09-09 15:20:08 -07001357
1358 return validProgram;
1359}
1360
Jamie Madillef300b12016-10-07 15:12:09 -04001361Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001362{
1363 // See ValidProgram for spec details.
1364
1365 Shader *validShader = context->getShader(id);
1366
1367 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001368 {
Dian Xiang769769a2015-09-09 15:20:08 -07001369 if (context->getProgram(id))
1370 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001371 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001372 }
1373 else
1374 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001375 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001376 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001377 }
Dian Xiang769769a2015-09-09 15:20:08 -07001378
1379 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001380}
1381
Geoff Langb1196682014-07-23 13:47:29 -04001382bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001383{
1384 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1385 {
1386 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1387
Geoff Langaae65a42014-05-26 12:43:44 -04001388 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001389 {
Martin Radevd178aa42017-07-13 14:03:22 +03001390 context->handleError(
1391 InvalidOperation()
1392 << "attachment index cannot be greater or equal to MAX_COLOR_ATTACHMENTS.");
Geoff Langb1196682014-07-23 13:47:29 -04001393 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001394 }
1395 }
1396 else
1397 {
1398 switch (attachment)
1399 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001400 case GL_DEPTH_ATTACHMENT:
1401 case GL_STENCIL_ATTACHMENT:
1402 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001403
He Yunchaoced53ae2016-11-29 15:00:51 +08001404 case GL_DEPTH_STENCIL_ATTACHMENT:
1405 if (!context->getExtensions().webglCompatibility &&
1406 context->getClientMajorVersion() < 3)
1407 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001408 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001409 return false;
1410 }
1411 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001412
He Yunchaoced53ae2016-11-29 15:00:51 +08001413 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001414 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001415 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001416 }
1417 }
1418
1419 return true;
1420}
1421
Jamie Madille8fb6402017-02-14 17:56:40 -05001422bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001423 GLenum target,
1424 GLsizei samples,
1425 GLenum internalformat,
1426 GLsizei width,
1427 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001428{
1429 switch (target)
1430 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001431 case GL_RENDERBUFFER:
1432 break;
1433 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001434 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001435 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001436 }
1437
1438 if (width < 0 || height < 0 || samples < 0)
1439 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001440 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001441 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001442 }
1443
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001444 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1445 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1446
1447 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001448 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001449 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001450 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001451 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001452 }
1453
1454 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1455 // 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 -08001456 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001457 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1458 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001459 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001460 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001461 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001462 }
1463
Geoff Langaae65a42014-05-26 12:43:44 -04001464 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001465 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001466 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001467 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001468 }
1469
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001470 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001471 if (handle == 0)
1472 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001473 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001474 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001475 }
1476
1477 return true;
1478}
1479
He Yunchaoced53ae2016-11-29 15:00:51 +08001480bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1481 GLenum target,
1482 GLenum attachment,
1483 GLenum renderbuffertarget,
1484 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001485{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001486 if (!ValidFramebufferTarget(target))
1487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001488 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001489 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001490 }
1491
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001492 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001493
Jamie Madill84115c92015-04-23 15:00:07 -04001494 ASSERT(framebuffer);
1495 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001496 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001497 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001498 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001499 }
1500
Jamie Madillb4472272014-07-03 10:38:55 -04001501 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001502 {
Jamie Madillb4472272014-07-03 10:38:55 -04001503 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001504 }
1505
Jamie Madillab9d82c2014-01-21 16:38:14 -05001506 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1507 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1508 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1509 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1510 if (renderbuffer != 0)
1511 {
1512 if (!context->getRenderbuffer(renderbuffer))
1513 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001514 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001515 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001516 }
1517 }
1518
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001519 return true;
1520}
1521
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001522bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001523 GLint srcX0,
1524 GLint srcY0,
1525 GLint srcX1,
1526 GLint srcY1,
1527 GLint dstX0,
1528 GLint dstY0,
1529 GLint dstX1,
1530 GLint dstY1,
1531 GLbitfield mask,
1532 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001533{
1534 switch (filter)
1535 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001536 case GL_NEAREST:
1537 break;
1538 case GL_LINEAR:
1539 break;
1540 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001541 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001542 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001543 }
1544
1545 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1546 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001547 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001548 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001549 }
1550
1551 if (mask == 0)
1552 {
1553 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1554 // buffers are copied.
1555 return false;
1556 }
1557
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001558 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1559 // color buffer, leaving only nearest being unfiltered from above
1560 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1561 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001562 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001563 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001564 }
1565
Jamie Madill51f40ec2016-06-15 14:06:00 -04001566 const auto &glState = context->getGLState();
1567 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1568 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001569
1570 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001571 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001572 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001573 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001574 }
1575
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001576 if (readFramebuffer->id() == drawFramebuffer->id())
1577 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001578 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001579 return false;
1580 }
1581
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001582 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001583 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001584 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001585 return false;
1586 }
1587
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001588 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001589 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001590 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001591 return false;
1592 }
1593
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001594 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001595 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001596 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001597 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001598 }
1599
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001600 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1601
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001602 if (mask & GL_COLOR_BUFFER_BIT)
1603 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001604 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001605 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001606
He Yunchao66a41a22016-12-15 16:45:05 +08001607 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001608 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001609 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001610
Geoff Langa15472a2015-08-11 11:48:03 -04001611 for (size_t drawbufferIdx = 0;
1612 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001613 {
Geoff Langa15472a2015-08-11 11:48:03 -04001614 const FramebufferAttachment *attachment =
1615 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1616 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001617 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001618 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001619
Geoff Langb2f3d052013-08-13 12:49:27 -04001620 // The GL ES 3.0.2 spec (pg 193) states that:
1621 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001622 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1623 // as well
1624 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1625 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001626 // Changes with EXT_color_buffer_float:
1627 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001628 GLenum readComponentType = readFormat.info->componentType;
1629 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001630 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001631 readComponentType == GL_SIGNED_NORMALIZED);
1632 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1633 drawComponentType == GL_SIGNED_NORMALIZED);
1634
1635 if (extensions.colorBufferFloat)
1636 {
1637 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1638 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1639
1640 if (readFixedOrFloat != drawFixedOrFloat)
1641 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001642 context->handleError(InvalidOperation()
1643 << "If the read buffer contains fixed-point or "
1644 "floating-point values, the draw buffer must "
1645 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001646 return false;
1647 }
1648 }
1649 else if (readFixedPoint != drawFixedPoint)
1650 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001651 context->handleError(InvalidOperation()
1652 << "If the read buffer contains fixed-point values, "
1653 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001654 return false;
1655 }
1656
1657 if (readComponentType == GL_UNSIGNED_INT &&
1658 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001659 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001660 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001661 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001662 }
1663
Jamie Madill6163c752015-12-07 16:32:59 -05001664 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001665 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001666 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001667 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001668 }
1669
Jamie Madilla3944d42016-07-22 22:13:26 -04001670 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001671 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001672 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001673 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001674 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001675 }
Geoff Lange4915782017-04-12 15:19:07 -04001676
1677 if (context->getExtensions().webglCompatibility &&
1678 *readColorBuffer == *attachment)
1679 {
1680 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001681 InvalidOperation()
1682 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001683 return false;
1684 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001685 }
1686 }
1687
Jamie Madilla3944d42016-07-22 22:13:26 -04001688 if ((readFormat.info->componentType == GL_INT ||
1689 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1690 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001691 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001692 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001693 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001694 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001695 }
He Yunchao66a41a22016-12-15 16:45:05 +08001696 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1697 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1698 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1699 // situation is an application error that would lead to a crash in ANGLE.
1700 else if (drawFramebuffer->hasEnabledDrawBuffer())
1701 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001702 context->handleError(
1703 InvalidOperation()
1704 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001705 return false;
1706 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001707 }
1708
He Yunchaoced53ae2016-11-29 15:00:51 +08001709 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001710 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1711 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001712 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001713 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001714 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001715 const gl::FramebufferAttachment *readBuffer =
1716 readFramebuffer->getAttachment(attachments[i]);
1717 const gl::FramebufferAttachment *drawBuffer =
1718 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001719
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001720 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001721 {
Kenneth Russell69382852017-07-21 16:38:44 -04001722 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001724 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001725 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001726 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001727
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001728 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001729 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001730 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001731 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001732 }
Geoff Lange4915782017-04-12 15:19:07 -04001733
1734 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1735 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001736 context->handleError(
1737 InvalidOperation()
1738 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001739 return false;
1740 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001741 }
He Yunchao66a41a22016-12-15 16:45:05 +08001742 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1743 else if (drawBuffer)
1744 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001745 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1746 "depth/stencil attachment of a "
1747 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001748 return false;
1749 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001750 }
1751 }
1752
Martin Radeva3ed4572017-07-27 18:29:37 +03001753 // ANGLE_multiview, Revision 1:
1754 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1755 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1756 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1757 {
1758 context->handleError(InvalidFramebufferOperation()
1759 << "Attempt to read from a multi-view framebuffer.");
1760 return false;
1761 }
1762 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1763 {
1764 context->handleError(InvalidFramebufferOperation()
1765 << "Attempt to write to a multi-view framebuffer.");
1766 return false;
1767 }
1768
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001769 return true;
1770}
1771
Jamie Madill4928b7c2017-06-20 12:57:39 -04001772bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001773 GLint x,
1774 GLint y,
1775 GLsizei width,
1776 GLsizei height,
1777 GLenum format,
1778 GLenum type,
1779 GLsizei bufSize,
1780 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001781 GLsizei *columns,
1782 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001783 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001784{
1785 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001786 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001787 return false;
1788 }
1789
Geoff Lang62fce5b2016-09-30 10:46:35 -04001790 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001791 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001792 {
Geoff Langb1196682014-07-23 13:47:29 -04001793 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001794 }
1795
Geoff Lang62fce5b2016-09-30 10:46:35 -04001796 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001797 {
Geoff Langb1196682014-07-23 13:47:29 -04001798 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001799 }
1800
Jamie Madillc29968b2016-01-20 11:17:23 -05001801 return true;
1802}
1803
1804bool ValidateReadnPixelsEXT(Context *context,
1805 GLint x,
1806 GLint y,
1807 GLsizei width,
1808 GLsizei height,
1809 GLenum format,
1810 GLenum type,
1811 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001812 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001813{
1814 if (bufSize < 0)
1815 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001816 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001817 return false;
1818 }
1819
Geoff Lang62fce5b2016-09-30 10:46:35 -04001820 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001821 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001822}
Jamie Madill26e91952014-03-05 15:01:27 -05001823
Jamie Madill4928b7c2017-06-20 12:57:39 -04001824bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001825 GLint x,
1826 GLint y,
1827 GLsizei width,
1828 GLsizei height,
1829 GLenum format,
1830 GLenum type,
1831 GLsizei bufSize,
1832 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001833 GLsizei *columns,
1834 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001835 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001836{
1837 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001838 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001839 return false;
1840 }
1841
Geoff Lange93daba2017-03-30 13:54:40 -04001842 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1843 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001844 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001845 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001846 }
1847
Geoff Lang62fce5b2016-09-30 10:46:35 -04001848 if (!ValidateRobustBufferSize(context, bufSize, *length))
1849 {
1850 return false;
1851 }
1852
1853 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001854}
1855
Jamie Madillf0e04492017-08-26 15:28:42 -04001856bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001857{
1858 if (!context->getExtensions().occlusionQueryBoolean &&
1859 !context->getExtensions().disjointTimerQuery)
1860 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001861 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001862 return false;
1863 }
1864
Olli Etuaho41997e72016-03-10 13:38:39 +02001865 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001866}
1867
Jamie Madillf0e04492017-08-26 15:28:42 -04001868bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001869{
1870 if (!context->getExtensions().occlusionQueryBoolean &&
1871 !context->getExtensions().disjointTimerQuery)
1872 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001873 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001874 return false;
1875 }
1876
Olli Etuaho41997e72016-03-10 13:38:39 +02001877 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001878}
1879
Jamie Madillf0e04492017-08-26 15:28:42 -04001880bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1881{
1882 if (!context->getExtensions().occlusionQueryBoolean &&
1883 !context->getExtensions().disjointTimerQuery)
1884 {
1885 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1886 return false;
1887 }
1888
1889 return true;
1890}
1891
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001892bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001893{
1894 if (!ValidQueryType(context, target))
1895 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001896 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001897 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001898 }
1899
1900 if (id == 0)
1901 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001902 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001903 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001904 }
1905
1906 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1907 // of zero, if the active query object name for <target> is non-zero (for the
1908 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1909 // the active query for either target is non-zero), if <id> is the name of an
1910 // existing query object whose type does not match <target>, or if <id> is the
1911 // active query object name for any query type, the error INVALID_OPERATION is
1912 // generated.
1913
1914 // Ensure no other queries are active
1915 // NOTE: If other queries than occlusion are supported, we will need to check
1916 // separately that:
1917 // a) The query ID passed is not the current active query for any target/type
1918 // b) There are no active queries for the requested target (and in the case
1919 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1920 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001921
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001922 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001923 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001924 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001925 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001926 }
1927
1928 Query *queryObject = context->getQuery(id, true, target);
1929
1930 // check that name was obtained with glGenQueries
1931 if (!queryObject)
1932 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001933 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001934 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001935 }
1936
1937 // check for type mismatch
1938 if (queryObject->getType() != target)
1939 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001940 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001941 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001942 }
1943
1944 return true;
1945}
1946
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001947bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1948{
1949 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001950 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001951 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001952 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001953 return false;
1954 }
1955
1956 return ValidateBeginQueryBase(context, target, id);
1957}
1958
1959bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001960{
1961 if (!ValidQueryType(context, target))
1962 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001963 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001964 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001965 }
1966
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001967 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001968
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001969 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001970 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001971 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001972 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001973 }
1974
Jamie Madill45c785d2014-05-13 14:09:34 -04001975 return true;
1976}
1977
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001978bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1979{
1980 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001981 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001982 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001983 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001984 return false;
1985 }
1986
1987 return ValidateEndQueryBase(context, target);
1988}
1989
1990bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1991{
1992 if (!context->getExtensions().disjointTimerQuery)
1993 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001994 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001995 return false;
1996 }
1997
1998 if (target != GL_TIMESTAMP_EXT)
1999 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002000 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002001 return false;
2002 }
2003
2004 Query *queryObject = context->getQuery(id, true, target);
2005 if (queryObject == nullptr)
2006 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002007 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002008 return false;
2009 }
2010
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002011 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002012 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002013 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002014 return false;
2015 }
2016
2017 return true;
2018}
2019
Geoff Lang2186c382016-10-14 10:54:54 -04002020bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002021{
Geoff Lang2186c382016-10-14 10:54:54 -04002022 if (numParams)
2023 {
2024 *numParams = 0;
2025 }
2026
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002027 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2028 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002029 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002030 return false;
2031 }
2032
2033 switch (pname)
2034 {
2035 case GL_CURRENT_QUERY_EXT:
2036 if (target == GL_TIMESTAMP_EXT)
2037 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002038 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002039 return false;
2040 }
2041 break;
2042 case GL_QUERY_COUNTER_BITS_EXT:
2043 if (!context->getExtensions().disjointTimerQuery ||
2044 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2045 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002046 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002047 return false;
2048 }
2049 break;
2050 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002051 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002052 return false;
2053 }
2054
Geoff Lang2186c382016-10-14 10:54:54 -04002055 if (numParams)
2056 {
2057 // All queries return only one value
2058 *numParams = 1;
2059 }
2060
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002061 return true;
2062}
2063
2064bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2065{
2066 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002067 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002068 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002069 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002070 return false;
2071 }
2072
Geoff Lang2186c382016-10-14 10:54:54 -04002073 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002074}
2075
Geoff Lang2186c382016-10-14 10:54:54 -04002076bool ValidateGetQueryivRobustANGLE(Context *context,
2077 GLenum target,
2078 GLenum pname,
2079 GLsizei bufSize,
2080 GLsizei *length,
2081 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002082{
Geoff Lang2186c382016-10-14 10:54:54 -04002083 if (!ValidateRobustEntryPoint(context, bufSize))
2084 {
2085 return false;
2086 }
2087
2088 if (!ValidateGetQueryivBase(context, target, pname, length))
2089 {
2090 return false;
2091 }
2092
2093 if (!ValidateRobustBufferSize(context, bufSize, *length))
2094 {
2095 return false;
2096 }
2097
2098 return true;
2099}
2100
2101bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2102{
2103 if (numParams)
2104 {
2105 *numParams = 0;
2106 }
2107
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002108 Query *queryObject = context->getQuery(id, false, GL_NONE);
2109
2110 if (!queryObject)
2111 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002112 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002113 return false;
2114 }
2115
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002116 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002117 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002118 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002119 return false;
2120 }
2121
2122 switch (pname)
2123 {
2124 case GL_QUERY_RESULT_EXT:
2125 case GL_QUERY_RESULT_AVAILABLE_EXT:
2126 break;
2127
2128 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002129 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002130 return false;
2131 }
2132
Geoff Lang2186c382016-10-14 10:54:54 -04002133 if (numParams)
2134 {
2135 *numParams = 1;
2136 }
2137
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002138 return true;
2139}
2140
2141bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2142{
2143 if (!context->getExtensions().disjointTimerQuery)
2144 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002145 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002146 return false;
2147 }
Geoff Lang2186c382016-10-14 10:54:54 -04002148 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2149}
2150
2151bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2152 GLuint id,
2153 GLenum pname,
2154 GLsizei bufSize,
2155 GLsizei *length,
2156 GLint *params)
2157{
2158 if (!context->getExtensions().disjointTimerQuery)
2159 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002160 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04002161 return false;
2162 }
2163
2164 if (!ValidateRobustEntryPoint(context, bufSize))
2165 {
2166 return false;
2167 }
2168
2169 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2170 {
2171 return false;
2172 }
2173
2174 if (!ValidateRobustBufferSize(context, bufSize, *length))
2175 {
2176 return false;
2177 }
2178
2179 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002180}
2181
2182bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2183{
2184 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002185 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002186 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002187 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002188 return false;
2189 }
Geoff Lang2186c382016-10-14 10:54:54 -04002190 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2191}
2192
2193bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2194 GLuint id,
2195 GLenum pname,
2196 GLsizei bufSize,
2197 GLsizei *length,
2198 GLuint *params)
2199{
2200 if (!context->getExtensions().disjointTimerQuery &&
2201 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2202 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002203 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002204 return false;
2205 }
2206
2207 if (!ValidateRobustEntryPoint(context, bufSize))
2208 {
2209 return false;
2210 }
2211
2212 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2213 {
2214 return false;
2215 }
2216
2217 if (!ValidateRobustBufferSize(context, bufSize, *length))
2218 {
2219 return false;
2220 }
2221
2222 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002223}
2224
2225bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2226{
2227 if (!context->getExtensions().disjointTimerQuery)
2228 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002229 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002230 return false;
2231 }
Geoff Lang2186c382016-10-14 10:54:54 -04002232 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2233}
2234
2235bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2236 GLuint id,
2237 GLenum pname,
2238 GLsizei bufSize,
2239 GLsizei *length,
2240 GLint64 *params)
2241{
2242 if (!context->getExtensions().disjointTimerQuery)
2243 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002244 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002245 return false;
2246 }
2247
2248 if (!ValidateRobustEntryPoint(context, bufSize))
2249 {
2250 return false;
2251 }
2252
2253 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2254 {
2255 return false;
2256 }
2257
2258 if (!ValidateRobustBufferSize(context, bufSize, *length))
2259 {
2260 return false;
2261 }
2262
2263 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002264}
2265
2266bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2267{
2268 if (!context->getExtensions().disjointTimerQuery)
2269 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002270 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002271 return false;
2272 }
Geoff Lang2186c382016-10-14 10:54:54 -04002273 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2274}
2275
2276bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2277 GLuint id,
2278 GLenum pname,
2279 GLsizei bufSize,
2280 GLsizei *length,
2281 GLuint64 *params)
2282{
2283 if (!context->getExtensions().disjointTimerQuery)
2284 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002285 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002286 return false;
2287 }
2288
2289 if (!ValidateRobustEntryPoint(context, bufSize))
2290 {
2291 return false;
2292 }
2293
2294 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2295 {
2296 return false;
2297 }
2298
2299 if (!ValidateRobustBufferSize(context, bufSize, *length))
2300 {
2301 return false;
2302 }
2303
2304 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002305}
2306
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002307bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002308 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002309 GLuint program,
2310 GLint location,
2311 GLsizei count)
2312{
2313 // Check for ES31 program uniform entry points
2314 if (context->getClientVersion() < Version(3, 1))
2315 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002316 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002317 return false;
2318 }
2319
2320 const LinkedUniform *uniform = nullptr;
2321 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002322 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2323 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002324}
2325
Frank Henigmana98a6472017-02-02 21:38:32 -05002326bool ValidateProgramUniform1iv(gl::Context *context,
2327 GLuint program,
2328 GLint location,
2329 GLsizei count,
2330 const GLint *value)
2331{
2332 // Check for ES31 program uniform entry points
2333 if (context->getClientVersion() < Version(3, 1))
2334 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002335 context->handleError(InvalidOperation());
Frank Henigmana98a6472017-02-02 21:38:32 -05002336 return false;
2337 }
2338
2339 const LinkedUniform *uniform = nullptr;
2340 gl::Program *programObject = GetValidProgram(context, program);
2341 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2342 ValidateUniform1ivValue(context, uniform->type, count, value);
2343}
2344
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002345bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002346 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002347 GLuint program,
2348 GLint location,
2349 GLsizei count,
2350 GLboolean transpose)
2351{
2352 // Check for ES31 program uniform entry points
2353 if (context->getClientVersion() < Version(3, 1))
2354 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002355 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002356 return false;
2357 }
2358
2359 const LinkedUniform *uniform = nullptr;
2360 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002361 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2362 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002363}
2364
Jamie Madillc1d770e2017-04-13 17:31:24 -04002365bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002366{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002367 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002368 gl::Program *programObject = context->getGLState().getProgram();
2369 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2370 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002371}
2372
Jamie Madillbe849e42017-05-02 15:49:00 -04002373bool ValidateUniform1iv(ValidationContext *context,
2374 GLint location,
2375 GLsizei count,
2376 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002377{
2378 const LinkedUniform *uniform = nullptr;
2379 gl::Program *programObject = context->getGLState().getProgram();
2380 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2381 ValidateUniform1ivValue(context, uniform->type, count, value);
2382}
2383
Jamie Madillc1d770e2017-04-13 17:31:24 -04002384bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002385 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002386 GLint location,
2387 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002388 GLboolean transpose)
2389{
Martin Radev1be913c2016-07-11 17:59:16 +03002390 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002391 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002392 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002393 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002394 }
2395
Jamie Madill62d31cb2015-09-11 13:25:51 -04002396 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002397 gl::Program *programObject = context->getGLState().getProgram();
2398 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2399 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002400}
2401
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002402bool ValidateStateQuery(ValidationContext *context,
2403 GLenum pname,
2404 GLenum *nativeType,
2405 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002406{
2407 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2408 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002409 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002410 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002411 }
2412
Jamie Madill0af26e12015-03-05 19:54:33 -05002413 const Caps &caps = context->getCaps();
2414
Jamie Madill893ab082014-05-16 16:56:10 -04002415 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2416 {
2417 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2418
Jamie Madill0af26e12015-03-05 19:54:33 -05002419 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002420 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002421 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002422 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002423 }
2424 }
2425
2426 switch (pname)
2427 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002428 case GL_TEXTURE_BINDING_2D:
2429 case GL_TEXTURE_BINDING_CUBE_MAP:
2430 case GL_TEXTURE_BINDING_3D:
2431 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002432 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002433 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002434 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2435 if (!context->getExtensions().textureRectangle)
2436 {
2437 context->handleError(InvalidEnum()
2438 << "ANGLE_texture_rectangle extension not present");
2439 return false;
2440 }
2441 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002442 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2443 if (!context->getExtensions().eglStreamConsumerExternal &&
2444 !context->getExtensions().eglImageExternal)
2445 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002446 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2447 "nor GL_OES_EGL_image_external "
2448 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002449 return false;
2450 }
2451 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002452
He Yunchaoced53ae2016-11-29 15:00:51 +08002453 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2454 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002455 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002456 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2457 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002458 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002459 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002460 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002461 }
2462
Jamie Madill51f40ec2016-06-15 14:06:00 -04002463 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2464 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002465
2466 if (framebuffer->getReadBufferState() == GL_NONE)
2467 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002468 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002469 return false;
2470 }
2471
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002472 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002473 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002474 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002475 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002476 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002477 }
2478 }
2479 break;
2480
He Yunchaoced53ae2016-11-29 15:00:51 +08002481 default:
2482 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002483 }
2484
2485 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002486 if (*numParams == 0)
2487 {
2488 return false;
2489 }
2490
2491 return true;
2492}
2493
2494bool ValidateRobustStateQuery(ValidationContext *context,
2495 GLenum pname,
2496 GLsizei bufSize,
2497 GLenum *nativeType,
2498 unsigned int *numParams)
2499{
2500 if (!ValidateRobustEntryPoint(context, bufSize))
2501 {
2502 return false;
2503 }
2504
2505 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2506 {
2507 return false;
2508 }
2509
2510 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002511 {
2512 return false;
2513 }
2514
2515 return true;
2516}
2517
Jamie Madillc29968b2016-01-20 11:17:23 -05002518bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2519 GLenum target,
2520 GLint level,
2521 GLenum internalformat,
2522 bool isSubImage,
2523 GLint xoffset,
2524 GLint yoffset,
2525 GLint zoffset,
2526 GLint x,
2527 GLint y,
2528 GLsizei width,
2529 GLsizei height,
2530 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002531 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002532{
Brandon Jones6cad5662017-06-14 13:25:13 -07002533 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002534 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002535 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2536 return false;
2537 }
2538
2539 if (width < 0 || height < 0)
2540 {
2541 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002542 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002543 }
2544
He Yunchaoced53ae2016-11-29 15:00:51 +08002545 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2546 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002547 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002548 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002549 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002550 }
2551
2552 if (border != 0)
2553 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002554 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002555 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002556 }
2557
2558 if (!ValidMipLevel(context, target, level))
2559 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002560 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002561 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002562 }
2563
Jamie Madill51f40ec2016-06-15 14:06:00 -04002564 const auto &state = context->getGLState();
2565 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002566 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002567 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002568 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002569 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002570 }
2571
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002572 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002573 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002574 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002575 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002576 }
2577
Martin Radev138064f2016-07-15 12:03:41 +03002578 if (readFramebuffer->getReadBufferState() == GL_NONE)
2579 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002580 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002581 return false;
2582 }
2583
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002584 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2585 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002586 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002587 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002588 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2589 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002590 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002591 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002592 return false;
2593 }
2594
Martin Radev04e2c3b2017-07-27 16:54:35 +03002595 // ANGLE_multiview spec, Revision 1:
2596 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2597 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2598 // is not NONE.
2599 if (source->getMultiviewLayout() != GL_NONE)
2600 {
2601 context->handleError(InvalidFramebufferOperation()
2602 << "The active read framebuffer object has multiview attachments.");
2603 return false;
2604 }
2605
Geoff Langaae65a42014-05-26 12:43:44 -04002606 const gl::Caps &caps = context->getCaps();
2607
Geoff Langaae65a42014-05-26 12:43:44 -04002608 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002609 switch (target)
2610 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002611 case GL_TEXTURE_2D:
2612 maxDimension = caps.max2DTextureSize;
2613 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002614
He Yunchaoced53ae2016-11-29 15:00:51 +08002615 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2616 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2617 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2618 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2619 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2620 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2621 maxDimension = caps.maxCubeMapTextureSize;
2622 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002623
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002624 case GL_TEXTURE_RECTANGLE_ANGLE:
2625 maxDimension = caps.maxRectangleTextureSize;
2626 break;
2627
He Yunchaoced53ae2016-11-29 15:00:51 +08002628 case GL_TEXTURE_2D_ARRAY:
2629 maxDimension = caps.max2DTextureSize;
2630 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002631
He Yunchaoced53ae2016-11-29 15:00:51 +08002632 case GL_TEXTURE_3D:
2633 maxDimension = caps.max3DTextureSize;
2634 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002635
He Yunchaoced53ae2016-11-29 15:00:51 +08002636 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002637 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002638 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002639 }
2640
Jamie Madillc29968b2016-01-20 11:17:23 -05002641 gl::Texture *texture =
2642 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002643 if (!texture)
2644 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002645 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002646 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002647 }
2648
Geoff Lang69cce582015-09-17 13:20:36 -04002649 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002650 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002651 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002652 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002653 }
2654
Geoff Langca271392017-04-05 12:30:00 -04002655 const gl::InternalFormat &formatInfo =
2656 gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002657
Geoff Lang966c9402017-04-18 12:38:27 -04002658 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002659 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002660 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002661 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002662 }
2663
2664 if (isSubImage)
2665 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002666 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2667 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2668 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002669 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002670 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002671 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002672 }
2673 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002674 else
2675 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002676 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002677 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002678 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002679 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002680 }
2681
Geoff Langeb66a6e2016-10-31 13:06:12 -04002682 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002683 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002684 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002685 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002686 }
2687
2688 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002689 if (static_cast<int>(width) > maxLevelDimension ||
2690 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002691 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002692 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002693 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002694 }
2695 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002696
Jamie Madill0c8abca2016-07-22 20:21:26 -04002697 if (textureFormatOut)
2698 {
2699 *textureFormatOut = texture->getFormat(target, level);
2700 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002701
2702 // Detect texture copying feedback loops for WebGL.
2703 if (context->getExtensions().webglCompatibility)
2704 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002705 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002706 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002707 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002708 return false;
2709 }
2710 }
2711
Jamie Madill560a8d82014-05-21 13:06:20 -04002712 return true;
2713}
2714
Jiajia Qind9671222016-11-29 16:30:31 +08002715bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002716{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002717 switch (mode)
2718 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002719 case GL_POINTS:
2720 case GL_LINES:
2721 case GL_LINE_LOOP:
2722 case GL_LINE_STRIP:
2723 case GL_TRIANGLES:
2724 case GL_TRIANGLE_STRIP:
2725 case GL_TRIANGLE_FAN:
2726 break;
2727 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002728 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002729 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002730 }
2731
Jamie Madill250d33f2014-06-06 17:09:03 -04002732 if (count < 0)
2733 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002734 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002735 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002736 }
2737
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002738 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002739
Jamie Madill250d33f2014-06-06 17:09:03 -04002740 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002741 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002743 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002744 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002745 }
2746
Jamie Madillcbcde722017-01-06 14:50:00 -05002747 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2748 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002749 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002750 const Extensions &extensions = context->getExtensions();
2751 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002752 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002753 const FramebufferAttachment *dsAttachment =
2754 framebuffer->getStencilOrDepthStencilAttachment();
2755 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002756 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002757 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002758
2759 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2760 bool differentWritemasks =
2761 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2762 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2763 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2764 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2765
2766 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002767 {
Martin Radevffe754b2017-07-31 10:38:07 +03002768 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002769 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002770 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2771 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002772 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002773 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002774 return false;
2775 }
Jamie Madillac528012014-06-20 13:21:23 -04002776 }
2777
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002778 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002779 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002780 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002781 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002782 }
2783
Geoff Lang7dd2e102014-11-10 15:19:26 -05002784 gl::Program *program = state.getProgram();
2785 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002786 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002787 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002788 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002789 }
2790
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002791 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002792 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002793 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002794 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002795 }
2796
Martin Radevffe754b2017-07-31 10:38:07 +03002797 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002798 {
Martin Radev7e69f762017-07-27 14:54:13 +03002799 const int programNumViews = program->getNumViews();
2800 const int framebufferNumViews = framebuffer->getNumViews();
2801 if (programNumViews != -1 && framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002802 {
2803 context->handleError(InvalidOperation() << "The number of views in the active program "
2804 "and draw framebuffer does not match.");
2805 return false;
2806 }
Martin Radev7e69f762017-07-27 14:54:13 +03002807
2808 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2809 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2810 framebufferNumViews > 1)
2811 {
2812 context->handleError(InvalidOperation()
2813 << "There is an active transform feedback object "
2814 "when the number of views in the active draw "
2815 "framebuffer is greater than 1.");
2816 return false;
2817 }
Martin Radevffe754b2017-07-31 10:38:07 +03002818
2819 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2820 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2821 {
2822 context->handleError(InvalidOperation() << "There is an active query for target "
2823 "GL_TIME_ELAPSED_EXT when the number of "
2824 "views in the active draw framebuffer is "
2825 "greater than 1.");
2826 return false;
2827 }
Martin Radev7cf61662017-07-26 17:10:53 +03002828 }
2829
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002830 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002831 for (unsigned int uniformBlockIndex = 0;
2832 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002833 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002834 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002835 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002836 const OffsetBindingPointer<Buffer> &uniformBuffer =
2837 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002838
Geoff Lang5d124a62015-09-15 13:03:27 -04002839 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002840 {
2841 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002842 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002843 InvalidOperation()
2844 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002845 return false;
2846 }
2847
Geoff Lang5d124a62015-09-15 13:03:27 -04002848 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002849 if (uniformBufferSize == 0)
2850 {
2851 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002852 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002853 }
2854
Jamie Madill62d31cb2015-09-11 13:25:51 -04002855 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002856 {
2857 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002858 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002859 InvalidOperation()
2860 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002861 return false;
2862 }
2863 }
2864
Geoff Lange0cff192017-05-30 13:04:56 -04002865 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002866 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002867 {
Geoff Lange0cff192017-05-30 13:04:56 -04002868 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002869 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2870 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002871 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002872 return false;
2873 }
Geoff Lange0cff192017-05-30 13:04:56 -04002874
Geoff Lang9ab5b822017-05-30 16:19:23 -04002875 // Detect that the vertex shader input types match the attribute types
2876 if (!ValidateVertexShaderAttributeTypeMatch(context))
2877 {
2878 return false;
2879 }
2880
Geoff Lange0cff192017-05-30 13:04:56 -04002881 // Detect that the color buffer types match the fragment shader output types
2882 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2883 {
2884 return false;
2885 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002886 }
2887
Jamie Madill250d33f2014-06-06 17:09:03 -04002888 // No-op if zero count
2889 return (count > 0);
2890}
2891
Jamie Madillc1d770e2017-04-13 17:31:24 -04002892bool ValidateDrawArraysCommon(ValidationContext *context,
2893 GLenum mode,
2894 GLint first,
2895 GLsizei count,
2896 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002897{
Jamie Madillfd716582014-06-06 17:09:04 -04002898 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002899 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002900 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002901 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002902 }
2903
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002904 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002905 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002906 if (curTransformFeedback && curTransformFeedback->isActive() &&
2907 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002908 {
2909 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002910 // that does not match the current transform feedback object's draw mode (if transform
2911 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002912 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002913 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002914 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002915 }
2916
Jiajia Qind9671222016-11-29 16:30:31 +08002917 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002918 {
2919 return false;
2920 }
2921
Corentin Wallez71168a02016-12-19 15:11:18 -08002922 // Check the computation of maxVertex doesn't overflow.
2923 // - first < 0 or count < 0 have been checked as an error condition
2924 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2925 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2926 ASSERT(count > 0 && first >= 0);
2927 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2928 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002929 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002930 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002931 return false;
2932 }
2933
Corentin Wallez71168a02016-12-19 15:11:18 -08002934 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002935 {
2936 return false;
2937 }
2938
2939 return true;
2940}
2941
He Yunchaoced53ae2016-11-29 15:00:51 +08002942bool ValidateDrawArraysInstancedANGLE(Context *context,
2943 GLenum mode,
2944 GLint first,
2945 GLsizei count,
2946 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002947{
Corentin Wallez170efbf2017-05-02 13:45:01 -04002948 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002949 {
2950 return false;
2951 }
2952
Corentin Wallez0dc97812017-06-22 14:38:44 -04002953 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002954}
2955
Jiajia Qind9671222016-11-29 16:30:31 +08002956bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002957{
Jamie Madill250d33f2014-06-06 17:09:03 -04002958 switch (type)
2959 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002960 case GL_UNSIGNED_BYTE:
2961 case GL_UNSIGNED_SHORT:
2962 break;
2963 case GL_UNSIGNED_INT:
2964 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2965 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002966 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002967 return false;
2968 }
2969 break;
2970 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002971 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002972 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002973 }
2974
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002975 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002976
2977 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002978 if (curTransformFeedback && curTransformFeedback->isActive() &&
2979 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002980 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002981 // It is an invalid operation to call DrawElements, DrawRangeElements or
2982 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002983 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002984 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002985 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002986 }
2987
Jiajia Qind9671222016-11-29 16:30:31 +08002988 return true;
2989}
2990
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002991bool ValidateDrawElementsCommon(ValidationContext *context,
2992 GLenum mode,
2993 GLsizei count,
2994 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002995 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002996 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002997{
2998 if (!ValidateDrawElementsBase(context, type))
2999 return false;
3000
3001 const State &state = context->getGLState();
3002
Corentin Wallez170efbf2017-05-02 13:45:01 -04003003 if (!ValidateDrawBase(context, mode, count))
3004 {
3005 return false;
3006 }
3007
Jamie Madill250d33f2014-06-06 17:09:03 -04003008 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003009 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003010 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003011 context->handleError(InvalidOperation() << "Index buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -04003012 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003013 }
3014
He Yunchaoced53ae2016-11-29 15:00:51 +08003015 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003016 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003017
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003018 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3019
3020 if (context->getExtensions().webglCompatibility)
3021 {
3022 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3023 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3024 {
3025 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3026 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3027 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003028 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003029 return false;
3030 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003031
3032 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3033 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3034 // error is generated.
3035 if (reinterpret_cast<intptr_t>(indices) < 0)
3036 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003037 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003038 return false;
3039 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003040 }
3041
3042 if (context->getExtensions().webglCompatibility ||
3043 !context->getGLState().areClientArraysEnabled())
3044 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003045 if (!elementArrayBuffer && count > 0)
3046 {
3047 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3048 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3049 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003050 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003051 return false;
3052 }
3053 }
3054
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003055 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003056 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003057 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003058 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003059 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3060 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3061 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3062 constexpr uint64_t kMaxTypeSize = 8;
3063 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3064 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3065 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003066
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003067 uint64_t typeSize = typeBytes;
3068 uint64_t elementCount = static_cast<uint64_t>(count);
3069 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3070
3071 // Doing the multiplication here is overflow-safe
3072 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3073
3074 // The offset can be any value, check for overflows
3075 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3076 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003077 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003078 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003079 return false;
3080 }
3081
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003082 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3083 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003084 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003085 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003086 return false;
3087 }
3088 }
3089 else if (!indices)
3090 {
3091 // This is an application error that would normally result in a crash,
3092 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003093 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04003094 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003095 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003096 }
3097
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003098 // Use the parameter buffer to retrieve and cache the index range.
3099 // TODO: offer fast path, with disabled index validation.
3100 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3101 const auto &params = context->getParams<HasIndexRange>();
3102 const auto &indexRangeOpt = params.getIndexRange();
3103 if (!indexRangeOpt.valid())
3104 {
3105 // Unexpected error.
3106 return false;
3107 }
3108
3109 // If we use an index greater than our maximum supported index range, return an error.
3110 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3111 // return an error if possible here.
3112 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
3113 {
3114 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3115 return false;
3116 }
3117
3118 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
3119 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003120 {
3121 return false;
3122 }
3123
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003124 // No op if there are no real indices in the index data (all are primitive restart).
3125 return (indexRangeOpt.value().vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003126}
3127
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003128bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
3129 GLenum mode,
3130 GLsizei count,
3131 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003132 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003133 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003134{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003135 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003136}
3137
Geoff Lang3edfe032015-09-04 16:38:24 -04003138bool ValidateDrawElementsInstancedANGLE(Context *context,
3139 GLenum mode,
3140 GLsizei count,
3141 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003142 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003143 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003144{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003145 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003146 {
3147 return false;
3148 }
3149
Corentin Wallez0dc97812017-06-22 14:38:44 -04003150 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003151}
3152
He Yunchaoced53ae2016-11-29 15:00:51 +08003153bool ValidateFramebufferTextureBase(Context *context,
3154 GLenum target,
3155 GLenum attachment,
3156 GLuint texture,
3157 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003158{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003159 if (!ValidFramebufferTarget(target))
3160 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003161 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003162 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003163 }
3164
3165 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003166 {
3167 return false;
3168 }
3169
Jamie Madill55ec3b12014-07-03 10:38:57 -04003170 if (texture != 0)
3171 {
3172 gl::Texture *tex = context->getTexture(texture);
3173
Jamie Madillbe849e42017-05-02 15:49:00 -04003174 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003176 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003177 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003178 }
3179
3180 if (level < 0)
3181 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003182 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003183 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003184 }
3185 }
3186
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003187 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003188 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003189
Jamie Madill84115c92015-04-23 15:00:07 -04003190 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003191 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003192 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003193 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003194 }
3195
3196 return true;
3197}
3198
Geoff Langb1196682014-07-23 13:47:29 -04003199bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003200{
3201 if (program == 0)
3202 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003203 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003204 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003205 }
3206
Dian Xiang769769a2015-09-09 15:20:08 -07003207 gl::Program *programObject = GetValidProgram(context, program);
3208 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003209 {
3210 return false;
3211 }
3212
Jamie Madill0063c512014-08-25 15:47:53 -04003213 if (!programObject || !programObject->isLinked())
3214 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003215 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003216 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003217 }
3218
Geoff Lang7dd2e102014-11-10 15:19:26 -05003219 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003220 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003221 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003222 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003223 }
3224
Jamie Madill0063c512014-08-25 15:47:53 -04003225 return true;
3226}
3227
Geoff Langf41d0ee2016-10-07 13:04:23 -04003228static bool ValidateSizedGetUniform(Context *context,
3229 GLuint program,
3230 GLint location,
3231 GLsizei bufSize,
3232 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003233{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003234 if (length)
3235 {
3236 *length = 0;
3237 }
3238
Jamie Madill78f41802014-08-25 15:47:55 -04003239 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003240 {
Jamie Madill78f41802014-08-25 15:47:55 -04003241 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003242 }
3243
Geoff Langf41d0ee2016-10-07 13:04:23 -04003244 if (bufSize < 0)
3245 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003246 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003247 return false;
3248 }
3249
Jamie Madilla502c742014-08-28 17:19:13 -04003250 gl::Program *programObject = context->getProgram(program);
3251 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003252
Jamie Madill78f41802014-08-25 15:47:55 -04003253 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003254 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003255 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003256 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003257 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003258 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003259 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003260 }
3261
Geoff Langf41d0ee2016-10-07 13:04:23 -04003262 if (length)
3263 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003264 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003265 }
3266
Jamie Madill0063c512014-08-25 15:47:53 -04003267 return true;
3268}
3269
He Yunchaoced53ae2016-11-29 15:00:51 +08003270bool ValidateGetnUniformfvEXT(Context *context,
3271 GLuint program,
3272 GLint location,
3273 GLsizei bufSize,
3274 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003275{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003276 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003277}
3278
He Yunchaoced53ae2016-11-29 15:00:51 +08003279bool ValidateGetnUniformivEXT(Context *context,
3280 GLuint program,
3281 GLint location,
3282 GLsizei bufSize,
3283 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003284{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003285 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3286}
3287
3288bool ValidateGetUniformfvRobustANGLE(Context *context,
3289 GLuint program,
3290 GLint location,
3291 GLsizei bufSize,
3292 GLsizei *length,
3293 GLfloat *params)
3294{
3295 if (!ValidateRobustEntryPoint(context, bufSize))
3296 {
3297 return false;
3298 }
3299
3300 // bufSize is validated in ValidateSizedGetUniform
3301 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3302}
3303
3304bool ValidateGetUniformivRobustANGLE(Context *context,
3305 GLuint program,
3306 GLint location,
3307 GLsizei bufSize,
3308 GLsizei *length,
3309 GLint *params)
3310{
3311 if (!ValidateRobustEntryPoint(context, bufSize))
3312 {
3313 return false;
3314 }
3315
3316 // bufSize is validated in ValidateSizedGetUniform
3317 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3318}
3319
3320bool ValidateGetUniformuivRobustANGLE(Context *context,
3321 GLuint program,
3322 GLint location,
3323 GLsizei bufSize,
3324 GLsizei *length,
3325 GLuint *params)
3326{
3327 if (!ValidateRobustEntryPoint(context, bufSize))
3328 {
3329 return false;
3330 }
3331
3332 if (context->getClientMajorVersion() < 3)
3333 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003334 context->handleError(InvalidOperation() << "Entry point requires at least OpenGL ES 3.0.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003335 return false;
3336 }
3337
3338 // bufSize is validated in ValidateSizedGetUniform
3339 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003340}
3341
He Yunchaoced53ae2016-11-29 15:00:51 +08003342bool ValidateDiscardFramebufferBase(Context *context,
3343 GLenum target,
3344 GLsizei numAttachments,
3345 const GLenum *attachments,
3346 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003347{
3348 if (numAttachments < 0)
3349 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003350 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003351 return false;
3352 }
3353
3354 for (GLsizei i = 0; i < numAttachments; ++i)
3355 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003356 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003357 {
3358 if (defaultFramebuffer)
3359 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003360 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003361 return false;
3362 }
3363
3364 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3365 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003366 context->handleError(InvalidOperation() << "Requested color attachment is "
3367 "greater than the maximum supported "
3368 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003369 return false;
3370 }
3371 }
3372 else
3373 {
3374 switch (attachments[i])
3375 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003376 case GL_DEPTH_ATTACHMENT:
3377 case GL_STENCIL_ATTACHMENT:
3378 case GL_DEPTH_STENCIL_ATTACHMENT:
3379 if (defaultFramebuffer)
3380 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003381 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3382 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003383 return false;
3384 }
3385 break;
3386 case GL_COLOR:
3387 case GL_DEPTH:
3388 case GL_STENCIL:
3389 if (!defaultFramebuffer)
3390 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003391 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3392 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003393 return false;
3394 }
3395 break;
3396 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003397 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003398 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003399 }
3400 }
3401 }
3402
3403 return true;
3404}
3405
Austin Kinross6ee1e782015-05-29 17:05:37 -07003406bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3407{
3408 // Note that debug marker calls must not set error state
3409
3410 if (length < 0)
3411 {
3412 return false;
3413 }
3414
3415 if (marker == nullptr)
3416 {
3417 return false;
3418 }
3419
3420 return true;
3421}
3422
3423bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3424{
3425 // Note that debug marker calls must not set error state
3426
3427 if (length < 0)
3428 {
3429 return false;
3430 }
3431
3432 if (length > 0 && marker == nullptr)
3433 {
3434 return false;
3435 }
3436
3437 return true;
3438}
3439
Geoff Langdcab33b2015-07-21 13:03:16 -04003440bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003441 GLenum target,
3442 egl::Image *image)
3443{
Geoff Langa8406172015-07-21 16:53:39 -04003444 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3445 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003446 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003447 return false;
3448 }
3449
3450 switch (target)
3451 {
3452 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003453 if (!context->getExtensions().eglImage)
3454 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003455 context->handleError(InvalidEnum()
3456 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003457 }
3458 break;
3459
3460 case GL_TEXTURE_EXTERNAL_OES:
3461 if (!context->getExtensions().eglImageExternal)
3462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003463 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3464 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003465 }
Geoff Langa8406172015-07-21 16:53:39 -04003466 break;
3467
3468 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003469 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003470 return false;
3471 }
3472
Jamie Madill61e16b42017-06-19 11:13:23 -04003473 ASSERT(context->getCurrentDisplay());
3474 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003475 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003476 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003477 return false;
3478 }
3479
3480 if (image->getSamples() > 0)
3481 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003482 context->handleError(InvalidOperation()
3483 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003484 return false;
3485 }
3486
Geoff Langca271392017-04-05 12:30:00 -04003487 const TextureCaps &textureCaps =
3488 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003489 if (!textureCaps.texturable)
3490 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003491 context->handleError(InvalidOperation()
3492 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003493 return false;
3494 }
3495
Geoff Langdcab33b2015-07-21 13:03:16 -04003496 return true;
3497}
3498
3499bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003500 GLenum target,
3501 egl::Image *image)
3502{
Geoff Langa8406172015-07-21 16:53:39 -04003503 if (!context->getExtensions().eglImage)
3504 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003505 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003506 return false;
3507 }
3508
3509 switch (target)
3510 {
3511 case GL_RENDERBUFFER:
3512 break;
3513
3514 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003515 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003516 return false;
3517 }
3518
Jamie Madill61e16b42017-06-19 11:13:23 -04003519 ASSERT(context->getCurrentDisplay());
3520 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003521 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003522 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003523 return false;
3524 }
3525
Geoff Langca271392017-04-05 12:30:00 -04003526 const TextureCaps &textureCaps =
3527 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003528 if (!textureCaps.renderable)
3529 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003530 context->handleError(InvalidOperation()
3531 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003532 return false;
3533 }
3534
Geoff Langdcab33b2015-07-21 13:03:16 -04003535 return true;
3536}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003537
3538bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3539{
Geoff Lang36167ab2015-12-07 10:27:14 -05003540 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003541 {
3542 // The default VAO should always exist
3543 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003544 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003545 return false;
3546 }
3547
3548 return true;
3549}
3550
Geoff Langc5629752015-12-07 16:29:04 -05003551bool ValidateProgramBinaryBase(Context *context,
3552 GLuint program,
3553 GLenum binaryFormat,
3554 const void *binary,
3555 GLint length)
3556{
3557 Program *programObject = GetValidProgram(context, program);
3558 if (programObject == nullptr)
3559 {
3560 return false;
3561 }
3562
3563 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3564 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3565 programBinaryFormats.end())
3566 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003567 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003568 return false;
3569 }
3570
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003571 if (context->hasActiveTransformFeedback(program))
3572 {
3573 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003574 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3575 "is associated with an active transform "
3576 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003577 return false;
3578 }
3579
Geoff Langc5629752015-12-07 16:29:04 -05003580 return true;
3581}
3582
3583bool ValidateGetProgramBinaryBase(Context *context,
3584 GLuint program,
3585 GLsizei bufSize,
3586 GLsizei *length,
3587 GLenum *binaryFormat,
3588 void *binary)
3589{
3590 Program *programObject = GetValidProgram(context, program);
3591 if (programObject == nullptr)
3592 {
3593 return false;
3594 }
3595
3596 if (!programObject->isLinked())
3597 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003598 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003599 return false;
3600 }
3601
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003602 if (context->getCaps().programBinaryFormats.empty())
3603 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003604 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003605 return false;
3606 }
3607
Geoff Langc5629752015-12-07 16:29:04 -05003608 return true;
3609}
Jamie Madillc29968b2016-01-20 11:17:23 -05003610
Jamie Madillc29968b2016-01-20 11:17:23 -05003611bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3612{
3613 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003614 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003615 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003616 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3617 return false;
3618 }
3619 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3620 {
3621 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003622 return false;
3623 }
3624
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003625 ASSERT(context->getGLState().getDrawFramebuffer());
3626 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003627 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3628
3629 // This should come first before the check for the default frame buffer
3630 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3631 // rather than INVALID_OPERATION
3632 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3633 {
3634 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3635
3636 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003637 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3638 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003639 {
3640 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003641 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3642 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3643 // 3.1 is still a bit ambiguous about the error, but future specs are
3644 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003645 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003646 return false;
3647 }
3648 else if (bufs[colorAttachment] >= maxColorAttachment)
3649 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003650 context->handleError(InvalidOperation()
3651 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003652 return false;
3653 }
3654 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3655 frameBufferId != 0)
3656 {
3657 // INVALID_OPERATION-GL is bound to buffer and ith argument
3658 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003659 context->handleError(InvalidOperation()
3660 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003661 return false;
3662 }
3663 }
3664
3665 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3666 // and n is not 1 or bufs is bound to value other than BACK and NONE
3667 if (frameBufferId == 0)
3668 {
3669 if (n != 1)
3670 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003671 context->handleError(InvalidOperation()
3672 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003673 return false;
3674 }
3675
3676 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3677 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003678 context->handleError(
3679 InvalidOperation()
3680 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003681 return false;
3682 }
3683 }
3684
3685 return true;
3686}
3687
Geoff Lang496c02d2016-10-20 11:38:11 -07003688bool ValidateGetBufferPointervBase(Context *context,
3689 GLenum target,
3690 GLenum pname,
3691 GLsizei *length,
3692 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003693{
Geoff Lang496c02d2016-10-20 11:38:11 -07003694 if (length)
3695 {
3696 *length = 0;
3697 }
3698
3699 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3700 {
3701 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003702 InvalidOperation()
3703 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003704 return false;
3705 }
3706
Olli Etuaho4f667482016-03-30 15:56:35 +03003707 if (!ValidBufferTarget(context, target))
3708 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003709 context->handleError(InvalidEnum() << "Buffer target not valid: 0x" << std::hex
3710 << std::uppercase << target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003711 return false;
3712 }
3713
Geoff Lang496c02d2016-10-20 11:38:11 -07003714 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003715 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003716 case GL_BUFFER_MAP_POINTER:
3717 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003718
Geoff Lang496c02d2016-10-20 11:38:11 -07003719 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003720 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003721 return false;
3722 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003723
3724 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3725 // target bound to zero generate an INVALID_OPERATION error."
3726 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003727 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003728 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003729 context->handleError(InvalidOperation()
3730 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003731 return false;
3732 }
3733
Geoff Lang496c02d2016-10-20 11:38:11 -07003734 if (length)
3735 {
3736 *length = 1;
3737 }
3738
Olli Etuaho4f667482016-03-30 15:56:35 +03003739 return true;
3740}
3741
3742bool ValidateUnmapBufferBase(Context *context, GLenum target)
3743{
3744 if (!ValidBufferTarget(context, target))
3745 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003746 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003747 return false;
3748 }
3749
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003750 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003751
3752 if (buffer == nullptr || !buffer->isMapped())
3753 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003754 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003755 return false;
3756 }
3757
3758 return true;
3759}
3760
3761bool ValidateMapBufferRangeBase(Context *context,
3762 GLenum target,
3763 GLintptr offset,
3764 GLsizeiptr length,
3765 GLbitfield access)
3766{
3767 if (!ValidBufferTarget(context, target))
3768 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003769 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003770 return false;
3771 }
3772
Brandon Jones6cad5662017-06-14 13:25:13 -07003773 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003774 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003775 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3776 return false;
3777 }
3778
3779 if (length < 0)
3780 {
3781 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003782 return false;
3783 }
3784
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003785 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003786
3787 if (!buffer)
3788 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003789 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003790 return false;
3791 }
3792
3793 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003794 CheckedNumeric<size_t> checkedOffset(offset);
3795 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003796
Jamie Madille2e406c2016-06-02 13:04:10 -04003797 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003798 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003799 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003800 return false;
3801 }
3802
3803 // Check for invalid bits in the mask
3804 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3805 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3806 GL_MAP_UNSYNCHRONIZED_BIT;
3807
3808 if (access & ~(allAccessBits))
3809 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003810 context->handleError(InvalidValue()
3811 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003812 return false;
3813 }
3814
3815 if (length == 0)
3816 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003817 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003818 return false;
3819 }
3820
3821 if (buffer->isMapped())
3822 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003823 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003824 return false;
3825 }
3826
3827 // Check for invalid bit combinations
3828 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3829 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003830 context->handleError(InvalidOperation()
3831 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003832 return false;
3833 }
3834
3835 GLbitfield writeOnlyBits =
3836 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3837
3838 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3839 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003840 context->handleError(InvalidOperation()
3841 << "Invalid access bits when mapping buffer for reading: 0x"
3842 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003843 return false;
3844 }
3845
3846 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3847 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003848 context->handleError(
3849 InvalidOperation()
3850 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003851 return false;
3852 }
Geoff Lang79f71042017-08-14 16:43:43 -04003853
3854 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003855}
3856
3857bool ValidateFlushMappedBufferRangeBase(Context *context,
3858 GLenum target,
3859 GLintptr offset,
3860 GLsizeiptr length)
3861{
Brandon Jones6cad5662017-06-14 13:25:13 -07003862 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003863 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003864 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3865 return false;
3866 }
3867
3868 if (length < 0)
3869 {
3870 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003871 return false;
3872 }
3873
3874 if (!ValidBufferTarget(context, target))
3875 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003876 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003877 return false;
3878 }
3879
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003880 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003881
3882 if (buffer == nullptr)
3883 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003884 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003885 return false;
3886 }
3887
3888 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3889 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003890 context->handleError(InvalidOperation()
3891 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003892 return false;
3893 }
3894
3895 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003896 CheckedNumeric<size_t> checkedOffset(offset);
3897 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003898
Jamie Madille2e406c2016-06-02 13:04:10 -04003899 if (!checkedSize.IsValid() ||
3900 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003901 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003902 context->handleError(InvalidValue()
3903 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003904 return false;
3905 }
3906
3907 return true;
3908}
3909
Olli Etuaho41997e72016-03-10 13:38:39 +02003910bool ValidateGenOrDelete(Context *context, GLint n)
3911{
3912 if (n < 0)
3913 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003914 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003915 return false;
3916 }
3917 return true;
3918}
3919
Geoff Langff5b2d52016-09-07 11:32:23 -04003920bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3921{
3922 if (!context->getExtensions().robustClientMemory)
3923 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003924 context->handleError(InvalidOperation()
3925 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003926 return false;
3927 }
3928
3929 if (bufSize < 0)
3930 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003931 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003932 return false;
3933 }
3934
3935 return true;
3936}
3937
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003938bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3939{
3940 if (bufSize < numParams)
3941 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003942 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3943 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003944 return false;
3945 }
3946
3947 return true;
3948}
3949
Jamie Madillbe849e42017-05-02 15:49:00 -04003950bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3951 GLenum target,
3952 GLenum attachment,
3953 GLenum pname,
3954 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003955{
Geoff Langff5b2d52016-09-07 11:32:23 -04003956 if (!ValidFramebufferTarget(target))
3957 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003958 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003959 return false;
3960 }
3961
3962 int clientVersion = context->getClientMajorVersion();
3963
3964 switch (pname)
3965 {
3966 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3967 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3968 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3969 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3970 break;
3971
Martin Radeve5285d22017-07-14 16:23:53 +03003972 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3973 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3974 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3975 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3976 if (clientVersion < 3 || !context->getExtensions().multiview)
3977 {
3978 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3979 return false;
3980 }
3981 break;
3982
Geoff Langff5b2d52016-09-07 11:32:23 -04003983 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3984 if (clientVersion < 3 && !context->getExtensions().sRGB)
3985 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003986 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003987 return false;
3988 }
3989 break;
3990
3991 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3992 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3993 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3994 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3995 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3996 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3997 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3998 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3999 if (clientVersion < 3)
4000 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004001 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004002 return false;
4003 }
4004 break;
4005
4006 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004007 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004008 return false;
4009 }
4010
4011 // Determine if the attachment is a valid enum
4012 switch (attachment)
4013 {
4014 case GL_BACK:
4015 case GL_FRONT:
4016 case GL_DEPTH:
4017 case GL_STENCIL:
4018 case GL_DEPTH_STENCIL_ATTACHMENT:
4019 if (clientVersion < 3)
4020 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004021 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004022 return false;
4023 }
4024 break;
4025
4026 case GL_DEPTH_ATTACHMENT:
4027 case GL_STENCIL_ATTACHMENT:
4028 break;
4029
4030 default:
4031 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4032 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4033 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004034 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004035 return false;
4036 }
4037 break;
4038 }
4039
4040 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4041 ASSERT(framebuffer);
4042
4043 if (framebuffer->id() == 0)
4044 {
4045 if (clientVersion < 3)
4046 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004047 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004048 return false;
4049 }
4050
4051 switch (attachment)
4052 {
4053 case GL_BACK:
4054 case GL_DEPTH:
4055 case GL_STENCIL:
4056 break;
4057
4058 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004059 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004060 return false;
4061 }
4062 }
4063 else
4064 {
4065 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4066 {
4067 // Valid attachment query
4068 }
4069 else
4070 {
4071 switch (attachment)
4072 {
4073 case GL_DEPTH_ATTACHMENT:
4074 case GL_STENCIL_ATTACHMENT:
4075 break;
4076
4077 case GL_DEPTH_STENCIL_ATTACHMENT:
4078 if (!framebuffer->hasValidDepthStencil())
4079 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004080 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004081 return false;
4082 }
4083 break;
4084
4085 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004086 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004087 return false;
4088 }
4089 }
4090 }
4091
4092 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4093 if (attachmentObject)
4094 {
4095 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4096 attachmentObject->type() == GL_TEXTURE ||
4097 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4098
4099 switch (pname)
4100 {
4101 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4102 if (attachmentObject->type() != GL_RENDERBUFFER &&
4103 attachmentObject->type() != GL_TEXTURE)
4104 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004105 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004106 return false;
4107 }
4108 break;
4109
4110 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4111 if (attachmentObject->type() != GL_TEXTURE)
4112 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004113 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004114 return false;
4115 }
4116 break;
4117
4118 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4119 if (attachmentObject->type() != GL_TEXTURE)
4120 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004121 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004122 return false;
4123 }
4124 break;
4125
4126 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4127 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4128 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004129 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004130 return false;
4131 }
4132 break;
4133
4134 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4135 if (attachmentObject->type() != GL_TEXTURE)
4136 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004137 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004138 return false;
4139 }
4140 break;
4141
4142 default:
4143 break;
4144 }
4145 }
4146 else
4147 {
4148 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4149 // is NONE, then querying any other pname will generate INVALID_ENUM.
4150
4151 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4152 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4153 // INVALID_OPERATION for all other pnames
4154
4155 switch (pname)
4156 {
4157 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4158 break;
4159
4160 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4161 if (clientVersion < 3)
4162 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004163 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004164 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004165 return false;
4166 }
4167 break;
4168
4169 default:
4170 if (clientVersion < 3)
4171 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004172 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004173 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004174 return false;
4175 }
4176 else
4177 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004178 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004179 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004180 return false;
4181 }
4182 }
4183 }
4184
Martin Radeve5285d22017-07-14 16:23:53 +03004185 if (numParams)
4186 {
4187 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4188 {
4189 // Only when the viewport offsets are queried we can have a varying number of output
4190 // parameters.
4191 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4192 *numParams = numViews * 2;
4193 }
4194 else
4195 {
4196 // For all other queries we can have only one output parameter.
4197 *numParams = 1;
4198 }
4199 }
4200
Geoff Langff5b2d52016-09-07 11:32:23 -04004201 return true;
4202}
4203
4204bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4205 GLenum target,
4206 GLenum attachment,
4207 GLenum pname,
4208 GLsizei bufSize,
4209 GLsizei *numParams)
4210{
4211 if (!ValidateRobustEntryPoint(context, bufSize))
4212 {
4213 return false;
4214 }
4215
Jamie Madillbe849e42017-05-02 15:49:00 -04004216 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4217 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004218 {
4219 return false;
4220 }
4221
4222 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4223 {
4224 return false;
4225 }
4226
4227 return true;
4228}
4229
Geoff Langff5b2d52016-09-07 11:32:23 -04004230bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4231 GLenum target,
4232 GLenum pname,
4233 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004234 GLsizei *length,
4235 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004236{
4237 if (!ValidateRobustEntryPoint(context, bufSize))
4238 {
4239 return false;
4240 }
4241
Geoff Langebebe1c2016-10-14 12:01:31 -04004242 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004243 {
4244 return false;
4245 }
4246
Geoff Langebebe1c2016-10-14 12:01:31 -04004247 if (!ValidateRobustBufferSize(context, bufSize, *length))
4248 {
4249 return false;
4250 }
4251
4252 return true;
4253}
4254
4255bool ValidateGetBufferParameteri64v(ValidationContext *context,
4256 GLenum target,
4257 GLenum pname,
4258 GLint64 *params)
4259{
4260 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4261}
4262
4263bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4264 GLenum target,
4265 GLenum pname,
4266 GLsizei bufSize,
4267 GLsizei *length,
4268 GLint64 *params)
4269{
4270 if (!ValidateRobustEntryPoint(context, bufSize))
4271 {
4272 return false;
4273 }
4274
4275 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4276 {
4277 return false;
4278 }
4279
4280 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004281 {
4282 return false;
4283 }
4284
4285 return true;
4286}
4287
Jamie Madillbe849e42017-05-02 15:49:00 -04004288bool ValidateGetProgramivBase(ValidationContext *context,
4289 GLuint program,
4290 GLenum pname,
4291 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004292{
4293 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004294 if (numParams)
4295 {
4296 *numParams = 1;
4297 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004298
4299 Program *programObject = GetValidProgram(context, program);
4300 if (!programObject)
4301 {
4302 return false;
4303 }
4304
4305 switch (pname)
4306 {
4307 case GL_DELETE_STATUS:
4308 case GL_LINK_STATUS:
4309 case GL_VALIDATE_STATUS:
4310 case GL_INFO_LOG_LENGTH:
4311 case GL_ATTACHED_SHADERS:
4312 case GL_ACTIVE_ATTRIBUTES:
4313 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4314 case GL_ACTIVE_UNIFORMS:
4315 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4316 break;
4317
4318 case GL_PROGRAM_BINARY_LENGTH:
4319 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4320 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004321 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4322 "requires GL_OES_get_program_binary or "
4323 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004324 return false;
4325 }
4326 break;
4327
4328 case GL_ACTIVE_UNIFORM_BLOCKS:
4329 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4330 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4331 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4332 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4333 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4334 if (context->getClientMajorVersion() < 3)
4335 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004336 context->handleError(InvalidEnum() << "Querying requires at least ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004337 return false;
4338 }
4339 break;
4340
Yunchao He61afff12017-03-14 15:34:03 +08004341 case GL_PROGRAM_SEPARABLE:
4342 if (context->getClientVersion() < Version(3, 1))
4343 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004344 context->handleError(InvalidEnum() << "Querying requires at least ES 3.1.");
Yunchao He61afff12017-03-14 15:34:03 +08004345 return false;
4346 }
4347 break;
4348
Geoff Langff5b2d52016-09-07 11:32:23 -04004349 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004350 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004351 return false;
4352 }
4353
4354 return true;
4355}
4356
4357bool ValidateGetProgramivRobustANGLE(Context *context,
4358 GLuint program,
4359 GLenum pname,
4360 GLsizei bufSize,
4361 GLsizei *numParams)
4362{
4363 if (!ValidateRobustEntryPoint(context, bufSize))
4364 {
4365 return false;
4366 }
4367
Jamie Madillbe849e42017-05-02 15:49:00 -04004368 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004369 {
4370 return false;
4371 }
4372
4373 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4374 {
4375 return false;
4376 }
4377
4378 return true;
4379}
4380
Geoff Lang740d9022016-10-07 11:20:52 -04004381bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4382 GLenum target,
4383 GLenum pname,
4384 GLsizei bufSize,
4385 GLsizei *length,
4386 GLint *params)
4387{
4388 if (!ValidateRobustEntryPoint(context, bufSize))
4389 {
4390 return false;
4391 }
4392
4393 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4394 {
4395 return false;
4396 }
4397
4398 if (!ValidateRobustBufferSize(context, bufSize, *length))
4399 {
4400 return false;
4401 }
4402
4403 return true;
4404}
4405
Geoff Langd7d0ed32016-10-07 11:33:51 -04004406bool ValidateGetShaderivRobustANGLE(Context *context,
4407 GLuint shader,
4408 GLenum pname,
4409 GLsizei bufSize,
4410 GLsizei *length,
4411 GLint *params)
4412{
4413 if (!ValidateRobustEntryPoint(context, bufSize))
4414 {
4415 return false;
4416 }
4417
4418 if (!ValidateGetShaderivBase(context, shader, pname, length))
4419 {
4420 return false;
4421 }
4422
4423 if (!ValidateRobustBufferSize(context, bufSize, *length))
4424 {
4425 return false;
4426 }
4427
4428 return true;
4429}
4430
Geoff Langc1984ed2016-10-07 12:41:00 -04004431bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4432 GLenum target,
4433 GLenum pname,
4434 GLsizei bufSize,
4435 GLsizei *length,
4436 GLfloat *params)
4437{
4438 if (!ValidateRobustEntryPoint(context, bufSize))
4439 {
4440 return false;
4441 }
4442
4443 if (!ValidateGetTexParameterBase(context, target, pname, length))
4444 {
4445 return false;
4446 }
4447
4448 if (!ValidateRobustBufferSize(context, bufSize, *length))
4449 {
4450 return false;
4451 }
4452
4453 return true;
4454}
4455
Geoff Langc1984ed2016-10-07 12:41:00 -04004456bool ValidateGetTexParameterivRobustANGLE(Context *context,
4457 GLenum target,
4458 GLenum pname,
4459 GLsizei bufSize,
4460 GLsizei *length,
4461 GLint *params)
4462{
4463 if (!ValidateRobustEntryPoint(context, bufSize))
4464 {
4465 return false;
4466 }
4467
4468 if (!ValidateGetTexParameterBase(context, target, pname, length))
4469 {
4470 return false;
4471 }
4472
4473 if (!ValidateRobustBufferSize(context, bufSize, *length))
4474 {
4475 return false;
4476 }
4477
4478 return true;
4479}
4480
Geoff Langc1984ed2016-10-07 12:41:00 -04004481bool ValidateTexParameterfvRobustANGLE(Context *context,
4482 GLenum target,
4483 GLenum pname,
4484 GLsizei bufSize,
4485 const GLfloat *params)
4486{
4487 if (!ValidateRobustEntryPoint(context, bufSize))
4488 {
4489 return false;
4490 }
4491
4492 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4493}
4494
Geoff Langc1984ed2016-10-07 12:41:00 -04004495bool ValidateTexParameterivRobustANGLE(Context *context,
4496 GLenum target,
4497 GLenum pname,
4498 GLsizei bufSize,
4499 const GLint *params)
4500{
4501 if (!ValidateRobustEntryPoint(context, bufSize))
4502 {
4503 return false;
4504 }
4505
4506 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4507}
4508
4509bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4510{
4511 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4512}
4513
4514bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4515 GLuint sampler,
4516 GLenum pname,
4517 GLuint bufSize,
4518 GLsizei *length,
4519 GLfloat *params)
4520{
4521 if (!ValidateRobustEntryPoint(context, bufSize))
4522 {
4523 return false;
4524 }
4525
4526 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4527 {
4528 return false;
4529 }
4530
4531 if (!ValidateRobustBufferSize(context, bufSize, *length))
4532 {
4533 return false;
4534 }
4535
4536 return true;
4537}
4538
4539bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4540{
4541 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4542}
4543
4544bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4545 GLuint sampler,
4546 GLenum pname,
4547 GLuint bufSize,
4548 GLsizei *length,
4549 GLint *params)
4550{
4551 if (!ValidateRobustEntryPoint(context, bufSize))
4552 {
4553 return false;
4554 }
4555
4556 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4557 {
4558 return false;
4559 }
4560
4561 if (!ValidateRobustBufferSize(context, bufSize, *length))
4562 {
4563 return false;
4564 }
4565
4566 return true;
4567}
4568
4569bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4570{
4571 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4572}
4573
4574bool ValidateSamplerParameterfv(Context *context,
4575 GLuint sampler,
4576 GLenum pname,
4577 const GLfloat *params)
4578{
4579 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4580}
4581
4582bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4583 GLuint sampler,
4584 GLenum pname,
4585 GLsizei bufSize,
4586 const GLfloat *params)
4587{
4588 if (!ValidateRobustEntryPoint(context, bufSize))
4589 {
4590 return false;
4591 }
4592
4593 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4594}
4595
4596bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4597{
4598 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4599}
4600
4601bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4602{
4603 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4604}
4605
4606bool ValidateSamplerParameterivRobustANGLE(Context *context,
4607 GLuint sampler,
4608 GLenum pname,
4609 GLsizei bufSize,
4610 const GLint *params)
4611{
4612 if (!ValidateRobustEntryPoint(context, bufSize))
4613 {
4614 return false;
4615 }
4616
4617 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4618}
4619
Geoff Lang0b031062016-10-13 14:30:04 -04004620bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4621 GLuint index,
4622 GLenum pname,
4623 GLsizei bufSize,
4624 GLsizei *length,
4625 GLfloat *params)
4626{
4627 if (!ValidateRobustEntryPoint(context, bufSize))
4628 {
4629 return false;
4630 }
4631
4632 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4633 {
4634 return false;
4635 }
4636
4637 if (!ValidateRobustBufferSize(context, bufSize, *length))
4638 {
4639 return false;
4640 }
4641
4642 return true;
4643}
4644
Geoff Lang0b031062016-10-13 14:30:04 -04004645bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4646 GLuint index,
4647 GLenum pname,
4648 GLsizei bufSize,
4649 GLsizei *length,
4650 GLint *params)
4651{
4652 if (!ValidateRobustEntryPoint(context, bufSize))
4653 {
4654 return false;
4655 }
4656
4657 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4658 {
4659 return false;
4660 }
4661
4662 if (!ValidateRobustBufferSize(context, bufSize, *length))
4663 {
4664 return false;
4665 }
4666
4667 return true;
4668}
4669
Geoff Lang0b031062016-10-13 14:30:04 -04004670bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4671 GLuint index,
4672 GLenum pname,
4673 GLsizei bufSize,
4674 GLsizei *length,
4675 void **pointer)
4676{
4677 if (!ValidateRobustEntryPoint(context, bufSize))
4678 {
4679 return false;
4680 }
4681
4682 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4683 {
4684 return false;
4685 }
4686
4687 if (!ValidateRobustBufferSize(context, bufSize, *length))
4688 {
4689 return false;
4690 }
4691
4692 return true;
4693}
4694
4695bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
4696{
4697 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4698}
4699
4700bool ValidateGetVertexAttribIivRobustANGLE(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, true))
4713 {
4714 return false;
4715 }
4716
4717 if (!ValidateRobustBufferSize(context, bufSize, *length))
4718 {
4719 return false;
4720 }
4721
4722 return true;
4723}
4724
4725bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
4726{
4727 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4728}
4729
4730bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4731 GLuint index,
4732 GLenum pname,
4733 GLsizei bufSize,
4734 GLsizei *length,
4735 GLuint *params)
4736{
4737 if (!ValidateRobustEntryPoint(context, bufSize))
4738 {
4739 return false;
4740 }
4741
4742 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4743 {
4744 return false;
4745 }
4746
4747 if (!ValidateRobustBufferSize(context, bufSize, *length))
4748 {
4749 return false;
4750 }
4751
4752 return true;
4753}
4754
Geoff Lang6899b872016-10-14 11:30:13 -04004755bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4756 GLuint program,
4757 GLuint uniformBlockIndex,
4758 GLenum pname,
4759 GLsizei bufSize,
4760 GLsizei *length,
4761 GLint *params)
4762{
4763 if (!ValidateRobustEntryPoint(context, bufSize))
4764 {
4765 return false;
4766 }
4767
4768 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4769 {
4770 return false;
4771 }
4772
4773 if (!ValidateRobustBufferSize(context, bufSize, *length))
4774 {
4775 return false;
4776 }
4777
4778 return true;
4779}
4780
Geoff Lang0a9661f2016-10-20 10:59:20 -07004781bool ValidateGetInternalFormativ(Context *context,
4782 GLenum target,
4783 GLenum internalformat,
4784 GLenum pname,
4785 GLsizei bufSize,
4786 GLint *params)
4787{
4788 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4789 nullptr);
4790}
4791
4792bool ValidateGetInternalFormativRobustANGLE(Context *context,
4793 GLenum target,
4794 GLenum internalformat,
4795 GLenum pname,
4796 GLsizei bufSize,
4797 GLsizei *length,
4798 GLint *params)
4799{
4800 if (!ValidateRobustEntryPoint(context, bufSize))
4801 {
4802 return false;
4803 }
4804
4805 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4806 {
4807 return false;
4808 }
4809
4810 if (!ValidateRobustBufferSize(context, bufSize, *length))
4811 {
4812 return false;
4813 }
4814
4815 return true;
4816}
4817
Shao80957d92017-02-20 21:25:59 +08004818bool ValidateVertexFormatBase(ValidationContext *context,
4819 GLuint attribIndex,
4820 GLint size,
4821 GLenum type,
4822 GLboolean pureInteger)
4823{
4824 const Caps &caps = context->getCaps();
4825 if (attribIndex >= caps.maxVertexAttributes)
4826 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004827 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004828 return false;
4829 }
4830
4831 if (size < 1 || size > 4)
4832 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004833 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004834 return false;
Shao80957d92017-02-20 21:25:59 +08004835 }
4836
4837 switch (type)
4838 {
4839 case GL_BYTE:
4840 case GL_UNSIGNED_BYTE:
4841 case GL_SHORT:
4842 case GL_UNSIGNED_SHORT:
4843 break;
4844
4845 case GL_INT:
4846 case GL_UNSIGNED_INT:
4847 if (context->getClientMajorVersion() < 3)
4848 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004849 context->handleError(InvalidEnum()
4850 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004851 return false;
4852 }
4853 break;
4854
4855 case GL_FIXED:
4856 case GL_FLOAT:
4857 if (pureInteger)
4858 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004859 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004860 return false;
4861 }
4862 break;
4863
4864 case GL_HALF_FLOAT:
4865 if (context->getClientMajorVersion() < 3)
4866 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004867 context->handleError(InvalidEnum()
4868 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004869 return false;
4870 }
4871 if (pureInteger)
4872 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004873 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004874 return false;
4875 }
4876 break;
4877
4878 case GL_INT_2_10_10_10_REV:
4879 case GL_UNSIGNED_INT_2_10_10_10_REV:
4880 if (context->getClientMajorVersion() < 3)
4881 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004882 context->handleError(InvalidEnum()
4883 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004884 return false;
4885 }
4886 if (pureInteger)
4887 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004888 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004889 return false;
4890 }
4891 if (size != 4)
4892 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004893 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4894 "UNSIGNED_INT_2_10_10_10_REV and "
4895 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004896 return false;
4897 }
4898 break;
4899
4900 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004901 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004902 return false;
4903 }
4904
4905 return true;
4906}
4907
Geoff Lang76e65652017-03-27 14:58:02 -04004908// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4909// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4910// specified clear value and the type of a buffer that is being cleared generates an
4911// INVALID_OPERATION error instead of producing undefined results
4912bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4913 GLint drawbuffer,
4914 const GLenum *validComponentTypes,
4915 size_t validComponentTypeCount)
4916{
4917 const FramebufferAttachment *attachment =
4918 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4919 if (attachment)
4920 {
4921 GLenum componentType = attachment->getFormat().info->componentType;
4922 const GLenum *end = validComponentTypes + validComponentTypeCount;
4923 if (std::find(validComponentTypes, end, componentType) == end)
4924 {
4925 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004926 InvalidOperation()
4927 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004928 return false;
4929 }
4930 }
4931
4932 return true;
4933}
4934
Corentin Wallezb2931602017-04-11 15:58:57 -04004935bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4936 GLsizei imageSize,
4937 GLsizei dataSize)
4938{
4939 if (!ValidateRobustEntryPoint(context, dataSize))
4940 {
4941 return false;
4942 }
4943
4944 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
4945 if (pixelUnpackBuffer == nullptr)
4946 {
4947 if (dataSize < imageSize)
4948 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004949 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004950 }
4951 }
4952 return true;
4953}
4954
Jamie Madillbe849e42017-05-02 15:49:00 -04004955bool ValidateGetBufferParameterBase(ValidationContext *context,
4956 GLenum target,
4957 GLenum pname,
4958 bool pointerVersion,
4959 GLsizei *numParams)
4960{
4961 if (numParams)
4962 {
4963 *numParams = 0;
4964 }
4965
4966 if (!ValidBufferTarget(context, target))
4967 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004968 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004969 return false;
4970 }
4971
4972 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4973 if (!buffer)
4974 {
4975 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004976 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004977 return false;
4978 }
4979
4980 const Extensions &extensions = context->getExtensions();
4981
4982 switch (pname)
4983 {
4984 case GL_BUFFER_USAGE:
4985 case GL_BUFFER_SIZE:
4986 break;
4987
4988 case GL_BUFFER_ACCESS_OES:
4989 if (!extensions.mapBuffer)
4990 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004991 context->handleError(InvalidEnum()
4992 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004993 return false;
4994 }
4995 break;
4996
4997 case GL_BUFFER_MAPPED:
4998 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4999 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5000 !extensions.mapBufferRange)
5001 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005002 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5003 "GL_OES_mapbuffer or "
5004 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005005 return false;
5006 }
5007 break;
5008
5009 case GL_BUFFER_MAP_POINTER:
5010 if (!pointerVersion)
5011 {
5012 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005013 InvalidEnum()
5014 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005015 return false;
5016 }
5017 break;
5018
5019 case GL_BUFFER_ACCESS_FLAGS:
5020 case GL_BUFFER_MAP_OFFSET:
5021 case GL_BUFFER_MAP_LENGTH:
5022 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5023 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005024 context->handleError(InvalidEnum()
5025 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005026 return false;
5027 }
5028 break;
5029
5030 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005031 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005032 return false;
5033 }
5034
5035 // All buffer parameter queries return one value.
5036 if (numParams)
5037 {
5038 *numParams = 1;
5039 }
5040
5041 return true;
5042}
5043
5044bool ValidateGetRenderbufferParameterivBase(Context *context,
5045 GLenum target,
5046 GLenum pname,
5047 GLsizei *length)
5048{
5049 if (length)
5050 {
5051 *length = 0;
5052 }
5053
5054 if (target != GL_RENDERBUFFER)
5055 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005056 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005057 return false;
5058 }
5059
5060 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5061 if (renderbuffer == nullptr)
5062 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005063 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005064 return false;
5065 }
5066
5067 switch (pname)
5068 {
5069 case GL_RENDERBUFFER_WIDTH:
5070 case GL_RENDERBUFFER_HEIGHT:
5071 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5072 case GL_RENDERBUFFER_RED_SIZE:
5073 case GL_RENDERBUFFER_GREEN_SIZE:
5074 case GL_RENDERBUFFER_BLUE_SIZE:
5075 case GL_RENDERBUFFER_ALPHA_SIZE:
5076 case GL_RENDERBUFFER_DEPTH_SIZE:
5077 case GL_RENDERBUFFER_STENCIL_SIZE:
5078 break;
5079
5080 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5081 if (!context->getExtensions().framebufferMultisample)
5082 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005083 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005084 return false;
5085 }
5086 break;
5087
5088 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005089 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005090 return false;
5091 }
5092
5093 if (length)
5094 {
5095 *length = 1;
5096 }
5097 return true;
5098}
5099
5100bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5101{
5102 if (length)
5103 {
5104 *length = 0;
5105 }
5106
5107 if (GetValidShader(context, shader) == nullptr)
5108 {
5109 return false;
5110 }
5111
5112 switch (pname)
5113 {
5114 case GL_SHADER_TYPE:
5115 case GL_DELETE_STATUS:
5116 case GL_COMPILE_STATUS:
5117 case GL_INFO_LOG_LENGTH:
5118 case GL_SHADER_SOURCE_LENGTH:
5119 break;
5120
5121 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5122 if (!context->getExtensions().translatedShaderSource)
5123 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005124 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005125 return false;
5126 }
5127 break;
5128
5129 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005130 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005131 return false;
5132 }
5133
5134 if (length)
5135 {
5136 *length = 1;
5137 }
5138 return true;
5139}
5140
5141bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
5142{
5143 if (length)
5144 {
5145 *length = 0;
5146 }
5147
5148 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5149 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005150 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005151 return false;
5152 }
5153
5154 if (context->getTargetTexture(target) == nullptr)
5155 {
5156 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005157 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005158 return false;
5159 }
5160
5161 switch (pname)
5162 {
5163 case GL_TEXTURE_MAG_FILTER:
5164 case GL_TEXTURE_MIN_FILTER:
5165 case GL_TEXTURE_WRAP_S:
5166 case GL_TEXTURE_WRAP_T:
5167 break;
5168
5169 case GL_TEXTURE_USAGE_ANGLE:
5170 if (!context->getExtensions().textureUsage)
5171 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005172 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005173 return false;
5174 }
5175 break;
5176
5177 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5178 if (!context->getExtensions().textureFilterAnisotropic)
5179 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005180 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005181 return false;
5182 }
5183 break;
5184
5185 case GL_TEXTURE_IMMUTABLE_FORMAT:
5186 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
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 case GL_TEXTURE_WRAP_R:
5194 case GL_TEXTURE_IMMUTABLE_LEVELS:
5195 case GL_TEXTURE_SWIZZLE_R:
5196 case GL_TEXTURE_SWIZZLE_G:
5197 case GL_TEXTURE_SWIZZLE_B:
5198 case GL_TEXTURE_SWIZZLE_A:
5199 case GL_TEXTURE_BASE_LEVEL:
5200 case GL_TEXTURE_MAX_LEVEL:
5201 case GL_TEXTURE_MIN_LOD:
5202 case GL_TEXTURE_MAX_LOD:
5203 case GL_TEXTURE_COMPARE_MODE:
5204 case GL_TEXTURE_COMPARE_FUNC:
5205 if (context->getClientMajorVersion() < 3)
5206 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005207 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005208 return false;
5209 }
5210 break;
5211
5212 case GL_TEXTURE_SRGB_DECODE_EXT:
5213 if (!context->getExtensions().textureSRGBDecode)
5214 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005215 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005216 return false;
5217 }
5218 break;
5219
5220 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005221 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005222 return false;
5223 }
5224
5225 if (length)
5226 {
5227 *length = 1;
5228 }
5229 return true;
5230}
5231
5232bool ValidateGetVertexAttribBase(Context *context,
5233 GLuint index,
5234 GLenum pname,
5235 GLsizei *length,
5236 bool pointer,
5237 bool pureIntegerEntryPoint)
5238{
5239 if (length)
5240 {
5241 *length = 0;
5242 }
5243
5244 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5245 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005246 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005247 return false;
5248 }
5249
5250 if (index >= context->getCaps().maxVertexAttributes)
5251 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005252 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005253 return false;
5254 }
5255
5256 if (pointer)
5257 {
5258 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5259 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005260 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005261 return false;
5262 }
5263 }
5264 else
5265 {
5266 switch (pname)
5267 {
5268 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5269 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5270 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5271 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5272 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5273 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5274 case GL_CURRENT_VERTEX_ATTRIB:
5275 break;
5276
5277 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5278 static_assert(
5279 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5280 "ANGLE extension enums not equal to GL enums.");
5281 if (context->getClientMajorVersion() < 3 &&
5282 !context->getExtensions().instancedArrays)
5283 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005284 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5285 "requires OpenGL ES 3.0 or "
5286 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005287 return false;
5288 }
5289 break;
5290
5291 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5292 if (context->getClientMajorVersion() < 3)
5293 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005294 context->handleError(
5295 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005296 return false;
5297 }
5298 break;
5299
5300 case GL_VERTEX_ATTRIB_BINDING:
5301 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5302 if (context->getClientVersion() < ES_3_1)
5303 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005304 context->handleError(InvalidEnum()
5305 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005306 return false;
5307 }
5308 break;
5309
5310 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005311 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005312 return false;
5313 }
5314 }
5315
5316 if (length)
5317 {
5318 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5319 {
5320 *length = 4;
5321 }
5322 else
5323 {
5324 *length = 1;
5325 }
5326 }
5327
5328 return true;
5329}
5330
Jamie Madill4928b7c2017-06-20 12:57:39 -04005331bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005332 GLint x,
5333 GLint y,
5334 GLsizei width,
5335 GLsizei height,
5336 GLenum format,
5337 GLenum type,
5338 GLsizei bufSize,
5339 GLsizei *length,
5340 GLsizei *columns,
5341 GLsizei *rows,
5342 void *pixels)
5343{
5344 if (length != nullptr)
5345 {
5346 *length = 0;
5347 }
5348 if (rows != nullptr)
5349 {
5350 *rows = 0;
5351 }
5352 if (columns != nullptr)
5353 {
5354 *columns = 0;
5355 }
5356
5357 if (width < 0 || height < 0)
5358 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005359 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005360 return false;
5361 }
5362
5363 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5364
5365 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5366 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005367 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005368 return false;
5369 }
5370
5371 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5372 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005373 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005374 return false;
5375 }
5376
5377 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5378 ASSERT(framebuffer);
5379
5380 if (framebuffer->getReadBufferState() == GL_NONE)
5381 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005382 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005383 return false;
5384 }
5385
5386 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5387 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5388 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5389 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5390 // situation is an application error that would lead to a crash in ANGLE.
5391 if (readBuffer == nullptr)
5392 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005393 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005394 return false;
5395 }
5396
Martin Radev28031682017-07-28 14:47:56 +03005397 // ANGLE_multiview, Revision 1:
5398 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5399 // current read framebuffer is not NONE.
5400 if (readBuffer->getMultiviewLayout() != GL_NONE)
5401 {
5402 context->handleError(InvalidFramebufferOperation()
5403 << "Attempting to read from a multi-view framebuffer.");
5404 return false;
5405 }
5406
Geoff Lang280ba992017-04-18 16:30:58 -04005407 if (context->getExtensions().webglCompatibility)
5408 {
5409 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5410 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5411 // and type before validating the combination of format and type. However, the
5412 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5413 // verifies that GL_INVALID_OPERATION is generated.
5414 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5415 // dEQP/WebGL.
5416 if (!ValidReadPixelsFormatEnum(context, format))
5417 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005418 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005419 return false;
5420 }
5421
5422 if (!ValidReadPixelsTypeEnum(context, type))
5423 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005424 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005425 return false;
5426 }
5427 }
5428
Jamie Madill4928b7c2017-06-20 12:57:39 -04005429 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5430 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005431 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5432
5433 bool validFormatTypeCombination =
5434 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5435
5436 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5437 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005438 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005439 return false;
5440 }
5441
5442 // Check for pixel pack buffer related API errors
5443 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5444 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5445 {
5446 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005447 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005448 return false;
5449 }
5450
5451 // .. the data would be packed to the buffer object such that the memory writes required
5452 // would exceed the data store size.
5453 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5454 const gl::Extents size(width, height, 1);
5455 const auto &pack = context->getGLState().getPackState();
5456
5457 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5458 if (endByteOrErr.isError())
5459 {
5460 context->handleError(endByteOrErr.getError());
5461 return false;
5462 }
5463
5464 size_t endByte = endByteOrErr.getResult();
5465 if (bufSize >= 0)
5466 {
5467 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5468 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005469 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005470 return false;
5471 }
5472 }
5473
5474 if (pixelPackBuffer != nullptr)
5475 {
5476 CheckedNumeric<size_t> checkedEndByte(endByte);
5477 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5478 checkedEndByte += checkedOffset;
5479
5480 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5481 {
5482 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005483 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005484 return false;
5485 }
5486 }
5487
5488 if (pixelPackBuffer == nullptr && length != nullptr)
5489 {
5490 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5491 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005492 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005493 return false;
5494 }
5495
5496 *length = static_cast<GLsizei>(endByte);
5497 }
5498
5499 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5500 angle::CheckedNumeric<int> clippedExtent(length);
5501 if (start < 0)
5502 {
5503 // "subtract" the area that is less than 0
5504 clippedExtent += start;
5505 }
5506
5507 const int readExtent = start + length;
5508 if (readExtent > bufferSize)
5509 {
5510 // Subtract the region to the right of the read buffer
5511 clippedExtent -= (readExtent - bufferSize);
5512 }
5513
5514 if (!clippedExtent.IsValid())
5515 {
5516 return 0;
5517 }
5518
5519 return std::max(clippedExtent.ValueOrDie(), 0);
5520 };
5521
5522 if (columns != nullptr)
5523 {
5524 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5525 }
5526
5527 if (rows != nullptr)
5528 {
5529 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5530 }
5531
5532 return true;
5533}
5534
5535template <typename ParamType>
5536bool ValidateTexParameterBase(Context *context,
5537 GLenum target,
5538 GLenum pname,
5539 GLsizei bufSize,
5540 const ParamType *params)
5541{
5542 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5543 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005544 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005545 return false;
5546 }
5547
5548 if (context->getTargetTexture(target) == nullptr)
5549 {
5550 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005551 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005552 return false;
5553 }
5554
5555 const GLsizei minBufSize = 1;
5556 if (bufSize >= 0 && bufSize < minBufSize)
5557 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005558 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005559 return false;
5560 }
5561
5562 switch (pname)
5563 {
5564 case GL_TEXTURE_WRAP_R:
5565 case GL_TEXTURE_SWIZZLE_R:
5566 case GL_TEXTURE_SWIZZLE_G:
5567 case GL_TEXTURE_SWIZZLE_B:
5568 case GL_TEXTURE_SWIZZLE_A:
5569 case GL_TEXTURE_BASE_LEVEL:
5570 case GL_TEXTURE_MAX_LEVEL:
5571 case GL_TEXTURE_COMPARE_MODE:
5572 case GL_TEXTURE_COMPARE_FUNC:
5573 case GL_TEXTURE_MIN_LOD:
5574 case GL_TEXTURE_MAX_LOD:
5575 if (context->getClientMajorVersion() < 3)
5576 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005577 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005578 return false;
5579 }
5580 if (target == GL_TEXTURE_EXTERNAL_OES &&
5581 !context->getExtensions().eglImageExternalEssl3)
5582 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005583 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5584 "available without "
5585 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005586 return false;
5587 }
5588 break;
5589
5590 default:
5591 break;
5592 }
5593
JiangYizhou4cff8d62017-07-06 14:54:09 +08005594 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5595 {
5596 switch (pname)
5597 {
5598 case GL_TEXTURE_MIN_FILTER:
5599 case GL_TEXTURE_MAG_FILTER:
5600 case GL_TEXTURE_WRAP_S:
5601 case GL_TEXTURE_WRAP_T:
5602 case GL_TEXTURE_WRAP_R:
5603 case GL_TEXTURE_MIN_LOD:
5604 case GL_TEXTURE_MAX_LOD:
5605 case GL_TEXTURE_COMPARE_MODE:
5606 case GL_TEXTURE_COMPARE_FUNC:
5607 context->handleError(InvalidEnum()
5608 << "Invalid parameter for 2D multisampled textures.");
5609 return false;
5610 }
5611 }
5612
Jamie Madillbe849e42017-05-02 15:49:00 -04005613 switch (pname)
5614 {
5615 case GL_TEXTURE_WRAP_S:
5616 case GL_TEXTURE_WRAP_T:
5617 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005618 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005619 bool restrictedWrapModes =
5620 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5621 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5622 {
5623 return false;
5624 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005625 }
5626 break;
5627
5628 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005629 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005630 bool restrictedMinFilter =
5631 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5632 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5633 {
5634 return false;
5635 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005636 }
5637 break;
5638
5639 case GL_TEXTURE_MAG_FILTER:
5640 if (!ValidateTextureMagFilterValue(context, params))
5641 {
5642 return false;
5643 }
5644 break;
5645
5646 case GL_TEXTURE_USAGE_ANGLE:
5647 switch (ConvertToGLenum(params[0]))
5648 {
5649 case GL_NONE:
5650 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5651 break;
5652
5653 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005654 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005655 return false;
5656 }
5657 break;
5658
5659 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5660 if (!context->getExtensions().textureFilterAnisotropic)
5661 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005662 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005663 return false;
5664 }
5665
5666 // we assume the parameter passed to this validation method is truncated, not rounded
5667 if (params[0] < 1)
5668 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005669 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005670 return false;
5671 }
5672 break;
5673
5674 case GL_TEXTURE_MIN_LOD:
5675 case GL_TEXTURE_MAX_LOD:
5676 // any value is permissible
5677 break;
5678
5679 case GL_TEXTURE_COMPARE_MODE:
5680 if (!ValidateTextureCompareModeValue(context, params))
5681 {
5682 return false;
5683 }
5684 break;
5685
5686 case GL_TEXTURE_COMPARE_FUNC:
5687 if (!ValidateTextureCompareFuncValue(context, params))
5688 {
5689 return false;
5690 }
5691 break;
5692
5693 case GL_TEXTURE_SWIZZLE_R:
5694 case GL_TEXTURE_SWIZZLE_G:
5695 case GL_TEXTURE_SWIZZLE_B:
5696 case GL_TEXTURE_SWIZZLE_A:
5697 switch (ConvertToGLenum(params[0]))
5698 {
5699 case GL_RED:
5700 case GL_GREEN:
5701 case GL_BLUE:
5702 case GL_ALPHA:
5703 case GL_ZERO:
5704 case GL_ONE:
5705 break;
5706
5707 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005708 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005709 return false;
5710 }
5711 break;
5712
5713 case GL_TEXTURE_BASE_LEVEL:
5714 if (params[0] < 0)
5715 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005716 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005717 return false;
5718 }
5719 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5720 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005721 context->handleError(InvalidOperation()
5722 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005723 return false;
5724 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005725 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5726 {
5727 context->handleError(InvalidOperation()
5728 << "Base level must be 0 for multisampled textures.");
5729 return false;
5730 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005731 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5732 {
5733 context->handleError(InvalidOperation()
5734 << "Base level must be 0 for rectangle textures.");
5735 return false;
5736 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005737 break;
5738
5739 case GL_TEXTURE_MAX_LEVEL:
5740 if (params[0] < 0)
5741 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005742 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005743 return false;
5744 }
5745 break;
5746
5747 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5748 if (context->getClientVersion() < Version(3, 1))
5749 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005750 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005751 return false;
5752 }
5753 switch (ConvertToGLenum(params[0]))
5754 {
5755 case GL_DEPTH_COMPONENT:
5756 case GL_STENCIL_INDEX:
5757 break;
5758
5759 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005760 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005761 return false;
5762 }
5763 break;
5764
5765 case GL_TEXTURE_SRGB_DECODE_EXT:
5766 if (!ValidateTextureSRGBDecodeValue(context, params))
5767 {
5768 return false;
5769 }
5770 break;
5771
5772 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005773 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005774 return false;
5775 }
5776
5777 return true;
5778}
5779
5780template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5781template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5782
Jamie Madill12e957f2017-08-26 21:42:26 -04005783bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5784{
5785 if (index >= MAX_VERTEX_ATTRIBS)
5786 {
5787 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5788 return false;
5789 }
5790
5791 return true;
5792}
5793
5794bool ValidateGetActiveUniformBlockivBase(Context *context,
5795 GLuint program,
5796 GLuint uniformBlockIndex,
5797 GLenum pname,
5798 GLsizei *length)
5799{
5800 if (length)
5801 {
5802 *length = 0;
5803 }
5804
5805 if (context->getClientMajorVersion() < 3)
5806 {
5807 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5808 return false;
5809 }
5810
5811 Program *programObject = GetValidProgram(context, program);
5812 if (!programObject)
5813 {
5814 return false;
5815 }
5816
5817 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5818 {
5819 context->handleError(InvalidValue()
5820 << "uniformBlockIndex exceeds active uniform block count.");
5821 return false;
5822 }
5823
5824 switch (pname)
5825 {
5826 case GL_UNIFORM_BLOCK_BINDING:
5827 case GL_UNIFORM_BLOCK_DATA_SIZE:
5828 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5829 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5830 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5831 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5832 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5833 break;
5834
5835 default:
5836 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5837 return false;
5838 }
5839
5840 if (length)
5841 {
5842 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5843 {
5844 const UniformBlock &uniformBlock =
5845 programObject->getUniformBlockByIndex(uniformBlockIndex);
5846 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5847 }
5848 else
5849 {
5850 *length = 1;
5851 }
5852 }
5853
5854 return true;
5855}
5856
Jamie Madillc29968b2016-01-20 11:17:23 -05005857} // namespace gl