blob: 41ddc4ecea48ddaa64737fc0c42de66a18d34fb3 [file] [log] [blame]
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
Geoff Lange8ebe7f2013-08-05 15:03:13 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// validationES.h: Validation functions for generic OpenGL ES entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Context.h"
Geoff Langa8406172015-07-21 16:53:39 -040012#include "libANGLE/Display.h"
Brandon Jones6cad5662017-06-14 13:25:13 -070013#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Framebuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
Geoff Langa8406172015-07-21 16:53:39 -040016#include "libANGLE/Image.h"
Geoff Lang7dd2e102014-11-10 15:19:26 -050017#include "libANGLE/Program.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Query.h"
19#include "libANGLE/Texture.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050020#include "libANGLE/TransformFeedback.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040021#include "libANGLE/Uniform.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050022#include "libANGLE/VertexArray.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040023#include "libANGLE/formatutils.h"
24#include "libANGLE/validationES2.h"
25#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040026
27#include "common/mathutil.h"
28#include "common/utilities.h"
29
Jamie Madille2e406c2016-06-02 13:04:10 -040030using namespace angle;
31
Geoff Lange8ebe7f2013-08-05 15:03:13 -040032namespace gl
33{
Jamie Madill1ca74672015-07-21 15:14:11 -040034namespace
35{
Corentin Wallez92db6942016-12-09 13:10:36 -050036bool ValidateDrawAttribs(ValidationContext *context,
37 GLint primcount,
38 GLint maxVertex,
39 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040040{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070041 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040042 const gl::Program *program = state.getProgram();
43
Corentin Wallez327411e2016-12-09 11:09:17 -050044 bool webglCompatibility = context->getExtensions().webglCompatibility;
45
Jamie Madill231c7f52017-04-26 13:45:37 -040046 const VertexArray *vao = state.getVertexArray();
47 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080048 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madill231c7f52017-04-26 13:45:37 -040049 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040050 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
51 {
52 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallez672f7f32017-06-15 17:42:17 -040053
54 // No need to range check for disabled attribs.
55 if (!attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040056 {
Corentin Wallezfd456442016-12-21 17:57:00 -050057 continue;
58 }
Jamie Madill1ca74672015-07-21 15:14:11 -040059
Jamie Madill231c7f52017-04-26 13:45:37 -040060 // If we have no buffer, then we either get an error, or there are no more checks to be
61 // done.
Corentin Wallez672f7f32017-06-15 17:42:17 -040062 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
63 gl::Buffer *buffer = binding.getBuffer().get();
Corentin Wallezfd456442016-12-21 17:57:00 -050064 if (!buffer)
65 {
Geoff Langfeb8c682017-02-13 16:07:35 -050066 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -050067 {
68 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050069 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
70 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
71 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
72 // error.
Brandon Jonesafa75152017-07-21 13:11:29 -070073 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
Corentin Wallezfd456442016-12-21 17:57:00 -050074 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050075 }
Corentin Wallezfd456442016-12-21 17:57:00 -050076 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040077 {
78 // This is an application error that would normally result in a crash,
79 // but we catch it and return an error
Brandon Jonesafa75152017-07-21 13:11:29 -070080 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
Jamie Madill1ca74672015-07-21 15:14:11 -040081 return false;
82 }
Corentin Wallezfd456442016-12-21 17:57:00 -050083 continue;
84 }
85
Corentin Wallez672f7f32017-06-15 17:42:17 -040086 // This needs to come after the check for client arrays as even unused attributes cannot use
87 // client-side arrays
88 if (!program->isAttribLocationActive(attributeIndex))
89 {
90 continue;
91 }
92
Corentin Wallezfd456442016-12-21 17:57:00 -050093 // If we're drawing zero vertices, we have enough data.
94 if (vertexCount <= 0 || primcount <= 0)
95 {
96 continue;
97 }
98
99 GLint maxVertexElement = 0;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300100 GLuint divisor = binding.getDivisor();
101 if (divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500102 {
103 maxVertexElement = maxVertex;
104 }
105 else
106 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300107 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500108 }
109
110 // We do manual overflow checks here instead of using safe_math.h because it was
111 // a bottleneck. Thanks to some properties of GL we know inequalities that can
112 // help us make the overflow checks faster.
113
114 // The max possible attribSize is 16 for a vector of 4 32 bit values.
115 constexpr uint64_t kMaxAttribSize = 16;
116 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
117 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
118
119 // We know attribStride is given as a GLsizei which is typedefed to int.
120 // We also know an upper bound for attribSize.
121 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800122 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500123 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
124 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
125
126 // Computing the max offset using uint64_t without attrib.offset is overflow
127 // safe. Note: Last vertex element does not take the full stride!
128 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
129 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
130
131 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800132 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
133 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500134 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700135 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500136 return false;
137 }
138 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
139
140 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
141 // We can return INVALID_OPERATION if our vertex attribute does not have
142 // enough backing data.
143 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
144 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700145 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500146 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400147 }
148 }
149
150 return true;
151}
152
Geoff Lang280ba992017-04-18 16:30:58 -0400153bool ValidReadPixelsTypeEnum(ValidationContext *context, GLenum type)
154{
155 switch (type)
156 {
157 // Types referenced in Table 3.4 of the ES 2.0.25 spec
158 case GL_UNSIGNED_BYTE:
159 case GL_UNSIGNED_SHORT_4_4_4_4:
160 case GL_UNSIGNED_SHORT_5_5_5_1:
161 case GL_UNSIGNED_SHORT_5_6_5:
162 return context->getClientVersion() >= ES_2_0;
163
164 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
165 case GL_BYTE:
166 case GL_INT:
167 case GL_SHORT:
168 case GL_UNSIGNED_INT:
169 case GL_UNSIGNED_INT_10F_11F_11F_REV:
170 case GL_UNSIGNED_INT_24_8:
171 case GL_UNSIGNED_INT_2_10_10_10_REV:
172 case GL_UNSIGNED_INT_5_9_9_9_REV:
173 case GL_UNSIGNED_SHORT:
174 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
175 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
176 return context->getClientVersion() >= ES_3_0;
177
178 case GL_FLOAT:
179 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat;
180
181 case GL_HALF_FLOAT:
182 return context->getClientVersion() >= ES_3_0 ||
183 context->getExtensions().textureHalfFloat;
184
185 case GL_HALF_FLOAT_OES:
186 return context->getExtensions().colorBufferHalfFloat;
187
188 default:
189 return false;
190 }
191}
192
193bool ValidReadPixelsFormatEnum(ValidationContext *context, GLenum format)
194{
195 switch (format)
196 {
197 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
198 case GL_RGBA:
199 case GL_RGB:
200 case GL_ALPHA:
201 return context->getClientVersion() >= ES_2_0;
202
203 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
204 case GL_RG:
205 case GL_RED:
206 case GL_RGBA_INTEGER:
207 case GL_RGB_INTEGER:
208 case GL_RG_INTEGER:
209 case GL_RED_INTEGER:
210 return context->getClientVersion() >= ES_3_0;
211
212 case GL_SRGB_ALPHA_EXT:
213 case GL_SRGB_EXT:
214 return context->getExtensions().sRGB;
215
216 case GL_BGRA_EXT:
217 return context->getExtensions().readFormatBGRA;
218
219 default:
220 return false;
221 }
222}
223
Geoff Langf607c602016-09-21 11:46:48 -0400224bool ValidReadPixelsFormatType(ValidationContext *context,
225 GLenum framebufferComponentType,
226 GLenum format,
227 GLenum type)
228{
229 switch (framebufferComponentType)
230 {
231 case GL_UNSIGNED_NORMALIZED:
232 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
233 // ReadPixels with BGRA even if the extension is not present
234 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
235 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
236 type == GL_UNSIGNED_BYTE);
237
238 case GL_SIGNED_NORMALIZED:
239 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
240
241 case GL_INT:
242 return (format == GL_RGBA_INTEGER && type == GL_INT);
243
244 case GL_UNSIGNED_INT:
245 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
246
247 case GL_FLOAT:
248 return (format == GL_RGBA && type == GL_FLOAT);
249
250 default:
251 UNREACHABLE();
252 return false;
253 }
254}
255
Geoff Langc1984ed2016-10-07 12:41:00 -0400256template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400257bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400258{
259 switch (ConvertToGLenum(params[0]))
260 {
261 case GL_CLAMP_TO_EDGE:
262 break;
263
264 case GL_REPEAT:
265 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400266 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400267 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400268 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700269 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400270 return false;
271 }
272 break;
273
274 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700275 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400276 return false;
277 }
278
279 return true;
280}
281
282template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400283bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400284{
285 switch (ConvertToGLenum(params[0]))
286 {
287 case GL_NEAREST:
288 case GL_LINEAR:
289 break;
290
291 case GL_NEAREST_MIPMAP_NEAREST:
292 case GL_LINEAR_MIPMAP_NEAREST:
293 case GL_NEAREST_MIPMAP_LINEAR:
294 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400295 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400296 {
297 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700298 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400299 return false;
300 }
301 break;
302
303 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700304 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400305 return false;
306 }
307
308 return true;
309}
310
311template <typename ParamType>
312bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
313{
314 switch (ConvertToGLenum(params[0]))
315 {
316 case GL_NEAREST:
317 case GL_LINEAR:
318 break;
319
320 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700321 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400322 return false;
323 }
324
325 return true;
326}
327
328template <typename ParamType>
329bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
330{
331 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
332 switch (ConvertToGLenum(params[0]))
333 {
334 case GL_NONE:
335 case GL_COMPARE_REF_TO_TEXTURE:
336 break;
337
338 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700339 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400340 return false;
341 }
342
343 return true;
344}
345
346template <typename ParamType>
347bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
348{
349 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
350 switch (ConvertToGLenum(params[0]))
351 {
352 case GL_LEQUAL:
353 case GL_GEQUAL:
354 case GL_LESS:
355 case GL_GREATER:
356 case GL_EQUAL:
357 case GL_NOTEQUAL:
358 case GL_ALWAYS:
359 case GL_NEVER:
360 break;
361
362 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700363 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400364 return false;
365 }
366
367 return true;
368}
369
370template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700371bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
372{
373 if (!context->getExtensions().textureSRGBDecode)
374 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700375 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700376 return false;
377 }
378
379 switch (ConvertToGLenum(params[0]))
380 {
381 case GL_DECODE_EXT:
382 case GL_SKIP_DECODE_EXT:
383 break;
384
385 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700386 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700387 return false;
388 }
389
390 return true;
391}
392
393template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400394bool ValidateSamplerParameterBase(Context *context,
395 GLuint sampler,
396 GLenum pname,
397 GLsizei bufSize,
398 ParamType *params)
399{
400 if (context->getClientMajorVersion() < 3)
401 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700402 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc1984ed2016-10-07 12:41:00 -0400403 return false;
404 }
405
406 if (!context->isSampler(sampler))
407 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700408 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
Geoff Langc1984ed2016-10-07 12:41:00 -0400409 return false;
410 }
411
412 const GLsizei minBufSize = 1;
413 if (bufSize >= 0 && bufSize < minBufSize)
414 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700415 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langc1984ed2016-10-07 12:41:00 -0400416 return false;
417 }
418
419 switch (pname)
420 {
421 case GL_TEXTURE_WRAP_S:
422 case GL_TEXTURE_WRAP_T:
423 case GL_TEXTURE_WRAP_R:
424 if (!ValidateTextureWrapModeValue(context, params, false))
425 {
426 return false;
427 }
428 break;
429
430 case GL_TEXTURE_MIN_FILTER:
431 if (!ValidateTextureMinFilterValue(context, params, false))
432 {
433 return false;
434 }
435 break;
436
437 case GL_TEXTURE_MAG_FILTER:
438 if (!ValidateTextureMagFilterValue(context, params))
439 {
440 return false;
441 }
442 break;
443
444 case GL_TEXTURE_MIN_LOD:
445 case GL_TEXTURE_MAX_LOD:
446 // any value is permissible
447 break;
448
449 case GL_TEXTURE_COMPARE_MODE:
450 if (!ValidateTextureCompareModeValue(context, params))
451 {
452 return false;
453 }
454 break;
455
456 case GL_TEXTURE_COMPARE_FUNC:
457 if (!ValidateTextureCompareFuncValue(context, params))
458 {
459 return false;
460 }
461 break;
462
Geoff Lang81c6b572016-10-19 14:07:52 -0700463 case GL_TEXTURE_SRGB_DECODE_EXT:
464 if (!ValidateTextureSRGBDecodeValue(context, params))
465 {
466 return false;
467 }
468 break;
469
Geoff Langc1984ed2016-10-07 12:41:00 -0400470 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700471 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langc1984ed2016-10-07 12:41:00 -0400472 return false;
473 }
474
475 return true;
476}
477
478bool ValidateGetSamplerParameterBase(Context *context,
479 GLuint sampler,
480 GLenum pname,
481 GLsizei *length)
482{
483 if (length)
484 {
485 *length = 0;
486 }
487
488 if (context->getClientMajorVersion() < 3)
489 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700490 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc1984ed2016-10-07 12:41:00 -0400491 return false;
492 }
493
494 if (!context->isSampler(sampler))
495 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700496 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
Geoff Langc1984ed2016-10-07 12:41:00 -0400497 return false;
498 }
499
500 switch (pname)
501 {
502 case GL_TEXTURE_WRAP_S:
503 case GL_TEXTURE_WRAP_T:
504 case GL_TEXTURE_WRAP_R:
505 case GL_TEXTURE_MIN_FILTER:
506 case GL_TEXTURE_MAG_FILTER:
507 case GL_TEXTURE_MIN_LOD:
508 case GL_TEXTURE_MAX_LOD:
509 case GL_TEXTURE_COMPARE_MODE:
510 case GL_TEXTURE_COMPARE_FUNC:
511 break;
512
Geoff Lang81c6b572016-10-19 14:07:52 -0700513 case GL_TEXTURE_SRGB_DECODE_EXT:
514 if (!context->getExtensions().textureSRGBDecode)
515 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500516 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Geoff Lang81c6b572016-10-19 14:07:52 -0700517 return false;
518 }
519 break;
520
Geoff Langc1984ed2016-10-07 12:41:00 -0400521 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700522 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langc1984ed2016-10-07 12:41:00 -0400523 return false;
524 }
525
526 if (length)
527 {
528 *length = 1;
529 }
530 return true;
531}
532
Geoff Lang6899b872016-10-14 11:30:13 -0400533bool ValidateGetActiveUniformBlockivBase(Context *context,
534 GLuint program,
535 GLuint uniformBlockIndex,
536 GLenum pname,
537 GLsizei *length)
538{
539 if (length)
540 {
541 *length = 0;
542 }
543
544 if (context->getClientMajorVersion() < 3)
545 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500546 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Lang6899b872016-10-14 11:30:13 -0400547 return false;
548 }
549
550 Program *programObject = GetValidProgram(context, program);
551 if (!programObject)
552 {
553 return false;
554 }
555
556 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
557 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500558 context->handleError(InvalidValue()
559 << "uniformBlockIndex exceeds active uniform block count.");
Geoff Lang6899b872016-10-14 11:30:13 -0400560 return false;
561 }
562
563 switch (pname)
564 {
565 case GL_UNIFORM_BLOCK_BINDING:
566 case GL_UNIFORM_BLOCK_DATA_SIZE:
567 case GL_UNIFORM_BLOCK_NAME_LENGTH:
568 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
569 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
570 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
571 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
572 break;
573
574 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700575 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang6899b872016-10-14 11:30:13 -0400576 return false;
577 }
578
579 if (length)
580 {
581 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
582 {
583 const UniformBlock &uniformBlock =
584 programObject->getUniformBlockByIndex(uniformBlockIndex);
jchen10eaef1e52017-06-13 10:44:11 +0800585 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
Geoff Lang6899b872016-10-14 11:30:13 -0400586 }
587 else
588 {
589 *length = 1;
590 }
591 }
592
593 return true;
594}
595
Geoff Lang0a9661f2016-10-20 10:59:20 -0700596bool ValidateGetInternalFormativBase(Context *context,
597 GLenum target,
598 GLenum internalformat,
599 GLenum pname,
600 GLsizei bufSize,
601 GLsizei *numParams)
602{
603 if (numParams)
604 {
605 *numParams = 0;
606 }
607
608 if (context->getClientMajorVersion() < 3)
609 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500610 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700611 return false;
612 }
613
614 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
615 if (!formatCaps.renderable)
616 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500617 context->handleError(InvalidEnum() << "Internal format is not renderable.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700618 return false;
619 }
620
621 switch (target)
622 {
623 case GL_RENDERBUFFER:
624 break;
625
JiangYizhoubddc46b2016-12-09 09:50:51 +0800626 case GL_TEXTURE_2D_MULTISAMPLE:
627 if (context->getClientVersion() < ES_3_1)
628 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500629 context->handleError(InvalidOperation()
630 << "Texture target requires at least OpenGL ES 3.1.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800631 return false;
632 }
633 break;
634
Geoff Lang0a9661f2016-10-20 10:59:20 -0700635 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700636 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
Geoff Lang0a9661f2016-10-20 10:59:20 -0700637 return false;
638 }
639
640 if (bufSize < 0)
641 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700642 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
Geoff Lang0a9661f2016-10-20 10:59:20 -0700643 return false;
644 }
645
646 GLsizei maxWriteParams = 0;
647 switch (pname)
648 {
649 case GL_NUM_SAMPLE_COUNTS:
650 maxWriteParams = 1;
651 break;
652
653 case GL_SAMPLES:
654 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
655 break;
656
657 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700658 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang0a9661f2016-10-20 10:59:20 -0700659 return false;
660 }
661
662 if (numParams)
663 {
664 // glGetInternalFormativ will not overflow bufSize
665 *numParams = std::min(bufSize, maxWriteParams);
666 }
667
668 return true;
669}
670
Jamie Madillc1d770e2017-04-13 17:31:24 -0400671bool ValidateUniformCommonBase(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500672 gl::Program *program,
673 GLint location,
674 GLsizei count,
675 const LinkedUniform **uniformOut)
676{
677 // TODO(Jiajia): Add image uniform check in future.
678 if (count < 0)
679 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700680 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500681 return false;
682 }
683
Brandon Jones6cad5662017-06-14 13:25:13 -0700684 if (!program)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500685 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700686 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
687 return false;
688 }
689
690 if (!program->isLinked())
691 {
692 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500693 return false;
694 }
695
696 if (location == -1)
697 {
698 // Silently ignore the uniform command
699 return false;
700 }
701
702 const auto &uniformLocations = program->getUniformLocations();
Jamie Madillbe849e42017-05-02 15:49:00 -0400703 size_t castedLocation = static_cast<size_t>(location);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500704 if (castedLocation >= uniformLocations.size())
705 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500706 context->handleError(InvalidOperation() << "Invalid uniform location");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500707 return false;
708 }
709
710 const auto &uniformLocation = uniformLocations[castedLocation];
711 if (uniformLocation.ignored)
712 {
713 // Silently ignore the uniform command
714 return false;
715 }
716
717 if (!uniformLocation.used)
718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500719 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500720 return false;
721 }
722
723 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
724
725 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
726 if (!uniform.isArray() && count > 1)
727 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500728 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500729 return false;
730 }
731
732 *uniformOut = &uniform;
733 return true;
734}
735
Frank Henigman999b0fd2017-02-02 21:45:55 -0500736bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -0500737 GLenum uniformType,
738 GLsizei count,
739 const GLint *value)
740{
741 // Value type is GL_INT, because we only get here from glUniform1i{v}.
742 // It is compatible with INT or BOOL.
743 // Do these cheap tests first, for a little extra speed.
744 if (GL_INT == uniformType || GL_BOOL == uniformType)
745 {
746 return true;
747 }
748
749 if (IsSamplerType(uniformType))
750 {
Frank Henigman999b0fd2017-02-02 21:45:55 -0500751 // Check that the values are in range.
752 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
753 for (GLsizei i = 0; i < count; ++i)
754 {
755 if (value[i] < 0 || value[i] >= max)
756 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500757 context->handleError(InvalidValue() << "sampler uniform value out of range");
Frank Henigman999b0fd2017-02-02 21:45:55 -0500758 return false;
759 }
760 }
Frank Henigmana98a6472017-02-02 21:38:32 -0500761 return true;
762 }
763
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500764 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmana98a6472017-02-02 21:38:32 -0500765 return false;
766}
767
Jamie Madillc1d770e2017-04-13 17:31:24 -0400768bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500769{
770 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -0500771 // Do the cheaper test first, for a little extra speed.
772 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500773 {
774 return true;
775 }
776
Brandon Jonesafa75152017-07-21 13:11:29 -0700777 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500778 return false;
779}
780
Jamie Madillc1d770e2017-04-13 17:31:24 -0400781bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500782{
783 // Check that the value type is compatible with uniform type.
784 if (valueType == uniformType)
785 {
786 return true;
787 }
788
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500789 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500790 return false;
791}
792
Geoff Lange0cff192017-05-30 13:04:56 -0400793bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
794{
795 const Program *program = context->getGLState().getProgram();
796 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
797
798 const auto &programOutputTypes = program->getOutputVariableTypes();
799 for (size_t drawBufferIdx = 0; drawBufferIdx < programOutputTypes.size(); drawBufferIdx++)
800 {
801 GLenum outputType = programOutputTypes[drawBufferIdx];
802 GLenum inputType = framebuffer->getDrawbufferWriteType(drawBufferIdx);
803 if (outputType != GL_NONE && inputType != GL_NONE && inputType != outputType)
804 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500805 context->handleError(InvalidOperation() << "Fragment shader output type does not "
806 "match the bound framebuffer attachment "
807 "type.");
Geoff Lange0cff192017-05-30 13:04:56 -0400808 return false;
809 }
810 }
811
812 return true;
813}
814
Geoff Lang9ab5b822017-05-30 16:19:23 -0400815bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
816{
817 const Program *program = context->getGLState().getProgram();
818 const VertexArray *vao = context->getGLState().getVertexArray();
819
820 for (const auto &shaderAttribute : program->getAttributes())
821 {
Geoff Lang69df2422017-07-05 12:42:31 -0400822 // gl_VertexID and gl_InstanceID are active attributes but don't have a bound attribute.
823 if (shaderAttribute.isBuiltIn())
824 {
825 continue;
826 }
827
Geoff Lang9ab5b822017-05-30 16:19:23 -0400828 GLenum shaderInputType = VariableComponentType(shaderAttribute.type);
829
830 const auto &attrib = vao->getVertexAttribute(shaderAttribute.location);
831 const auto &currentValue =
832 context->getGLState().getVertexAttribCurrentValue(shaderAttribute.location);
833 GLenum vertexType = attrib.enabled ? GetVertexAttributeBaseType(attrib) : currentValue.Type;
834
835 if (shaderInputType != GL_NONE && vertexType != GL_NONE && shaderInputType != vertexType)
836 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500837 context->handleError(InvalidOperation() << "Vertex shader input type does not "
838 "match the type of the bound vertex "
839 "attribute.");
Geoff Lang9ab5b822017-05-30 16:19:23 -0400840 return false;
841 }
842 }
843
844 return true;
845}
846
Geoff Langf41a7152016-09-19 15:11:17 -0400847} // anonymous namespace
848
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500849bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400850{
Jamie Madilld7460c72014-01-21 16:38:14 -0500851 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400852 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800853 case GL_TEXTURE_2D:
854 case GL_TEXTURE_CUBE_MAP:
855 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400856
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400857 case GL_TEXTURE_RECTANGLE_ANGLE:
858 return context->getExtensions().textureRectangle;
859
He Yunchaoced53ae2016-11-29 15:00:51 +0800860 case GL_TEXTURE_3D:
861 case GL_TEXTURE_2D_ARRAY:
862 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500863
He Yunchaoced53ae2016-11-29 15:00:51 +0800864 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800865 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400866
He Yunchaoced53ae2016-11-29 15:00:51 +0800867 default:
868 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500869 }
Jamie Madill35d15012013-10-07 10:46:37 -0400870}
871
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500872bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
873{
874 switch (target)
875 {
876 case GL_TEXTURE_2D:
877 case GL_TEXTURE_CUBE_MAP:
878 return true;
879
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400880 case GL_TEXTURE_RECTANGLE_ANGLE:
881 return context->getExtensions().textureRectangle;
882
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500883 default:
884 return false;
885 }
886}
887
888bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
889{
890 switch (target)
891 {
892 case GL_TEXTURE_3D:
893 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300894 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500895
896 default:
897 return false;
898 }
899}
900
Ian Ewellbda75592016-04-18 17:25:54 -0400901// Most texture GL calls are not compatible with external textures, so we have a separate validation
902// function for use in the GL calls that do
903bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
904{
905 return (target == GL_TEXTURE_EXTERNAL_OES) &&
906 (context->getExtensions().eglImageExternal ||
907 context->getExtensions().eglStreamConsumerExternal);
908}
909
Shannon Woods4dfed832014-03-17 20:03:39 -0400910// This function differs from ValidTextureTarget in that the target must be
911// usable as the destination of a 2D operation-- so a cube face is valid, but
912// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400913// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500914bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400915{
916 switch (target)
917 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800918 case GL_TEXTURE_2D:
919 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
920 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
921 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
922 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
923 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
924 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
925 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400926 case GL_TEXTURE_RECTANGLE_ANGLE:
927 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800928 default:
929 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500930 }
931}
932
Jamie Madillbe849e42017-05-02 15:49:00 -0400933bool ValidateDrawElementsInstancedBase(ValidationContext *context,
934 GLenum mode,
935 GLsizei count,
936 GLenum type,
937 const GLvoid *indices,
938 GLsizei primcount)
939{
940 if (primcount < 0)
941 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700942 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400943 return false;
944 }
945
946 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
947 {
948 return false;
949 }
950
951 // No-op zero primitive count
952 return (primcount > 0);
953}
954
955bool ValidateDrawArraysInstancedBase(Context *context,
956 GLenum mode,
957 GLint first,
958 GLsizei count,
959 GLsizei primcount)
960{
961 if (primcount < 0)
962 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700963 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400964 return false;
965 }
966
967 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
968 {
969 return false;
970 }
971
972 // No-op if zero primitive count
973 return (primcount > 0);
974}
975
Corentin Wallez0dc97812017-06-22 14:38:44 -0400976bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400977{
978 // Verify there is at least one active attribute with a divisor of zero
979 const State &state = context->getGLState();
980
981 Program *program = state.getProgram();
982
983 const auto &attribs = state.getVertexArray()->getVertexAttributes();
984 const auto &bindings = state.getVertexArray()->getVertexBindings();
985 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
986 {
987 const VertexAttribute &attrib = attribs[attributeIndex];
988 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300989 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400990 {
991 return true;
992 }
993 }
994
Brandon Jonesafa75152017-07-21 13:11:29 -0700995 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400996 return false;
997}
998
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500999bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1000{
1001 switch (target)
1002 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001003 case GL_TEXTURE_3D:
1004 case GL_TEXTURE_2D_ARRAY:
1005 return true;
1006 default:
1007 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001008 }
1009}
1010
He Yunchao11b038b2016-11-22 21:24:04 +08001011bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
1012{
1013 switch (target)
1014 {
1015 case GL_TEXTURE_2D:
1016 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1017 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1018 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1019 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1020 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1021 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1022 case GL_TEXTURE_3D:
1023 case GL_TEXTURE_2D_ARRAY:
1024 case GL_TEXTURE_2D_MULTISAMPLE:
1025 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001026 case GL_TEXTURE_RECTANGLE_ANGLE:
1027 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +08001028 default:
1029 return false;
1030 }
1031}
1032
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001033bool ValidFramebufferTarget(GLenum target)
1034{
He Yunchaoced53ae2016-11-29 15:00:51 +08001035 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1036 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001037 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001038
1039 switch (target)
1040 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001041 case GL_FRAMEBUFFER:
1042 return true;
1043 case GL_READ_FRAMEBUFFER:
1044 return true;
1045 case GL_DRAW_FRAMEBUFFER:
1046 return true;
1047 default:
1048 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001049 }
1050}
1051
Jamie Madill29639852016-09-02 15:00:09 -04001052bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001053{
1054 switch (target)
1055 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001056 case GL_ARRAY_BUFFER:
1057 case GL_ELEMENT_ARRAY_BUFFER:
1058 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001059
He Yunchaoced53ae2016-11-29 15:00:51 +08001060 case GL_PIXEL_PACK_BUFFER:
1061 case GL_PIXEL_UNPACK_BUFFER:
1062 return (context->getExtensions().pixelBufferObject ||
1063 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001064
He Yunchaoced53ae2016-11-29 15:00:51 +08001065 case GL_COPY_READ_BUFFER:
1066 case GL_COPY_WRITE_BUFFER:
1067 case GL_TRANSFORM_FEEDBACK_BUFFER:
1068 case GL_UNIFORM_BUFFER:
1069 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001070
He Yunchaoced53ae2016-11-29 15:00:51 +08001071 case GL_ATOMIC_COUNTER_BUFFER:
1072 case GL_SHADER_STORAGE_BUFFER:
1073 case GL_DRAW_INDIRECT_BUFFER:
1074 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001075 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001076
He Yunchaoced53ae2016-11-29 15:00:51 +08001077 default:
1078 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001079 }
1080}
1081
Jamie Madillc29968b2016-01-20 11:17:23 -05001082bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001083{
Jamie Madillc29968b2016-01-20 11:17:23 -05001084 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001085 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001086 switch (target)
1087 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001088 case GL_TEXTURE_2D:
1089 maxDimension = caps.max2DTextureSize;
1090 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001091 case GL_TEXTURE_CUBE_MAP:
1092 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1093 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1094 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1095 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1096 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1097 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1098 maxDimension = caps.maxCubeMapTextureSize;
1099 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001100 case GL_TEXTURE_RECTANGLE_ANGLE:
1101 return level == 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08001102 case GL_TEXTURE_3D:
1103 maxDimension = caps.max3DTextureSize;
1104 break;
1105 case GL_TEXTURE_2D_ARRAY:
1106 maxDimension = caps.max2DTextureSize;
1107 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001108 case GL_TEXTURE_2D_MULTISAMPLE:
1109 maxDimension = caps.max2DTextureSize;
1110 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001111 default:
1112 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001113 }
1114
Brandon Jones6cad5662017-06-14 13:25:13 -07001115 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -04001116}
1117
Brandon Jones6cad5662017-06-14 13:25:13 -07001118bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001119 GLenum target,
1120 GLint level,
1121 GLsizei width,
1122 GLsizei height,
1123 GLsizei depth,
1124 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001125{
Brandon Jones6cad5662017-06-14 13:25:13 -07001126 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -04001127 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001128 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -04001129 return false;
1130 }
Austin Kinross08528e12015-10-07 16:24:40 -07001131 // TexSubImage parameters can be NPOT without textureNPOT extension,
1132 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001133 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001134 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001135 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001136 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001137 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001138 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -04001139 return false;
1140 }
1141
1142 if (!ValidMipLevel(context, target, level))
1143 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001144 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -04001145 return false;
1146 }
1147
1148 return true;
1149}
1150
Geoff Lang0d8b7242015-09-09 14:56:53 -04001151bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1152{
1153 // List of compressed format that require that the texture size is smaller than or a multiple of
1154 // the compressed block size.
1155 switch (internalFormat)
1156 {
1157 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1158 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1159 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1160 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langfff7a7d2017-06-02 10:39:17 -04001161 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
1162 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
1163 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
1164 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
Minmin Gonge3939b92015-12-01 15:36:51 -08001165 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001166 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1167 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1168 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1169 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1170 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
1171 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001172 return true;
1173
1174 default:
1175 return false;
1176 }
1177}
1178
Geoff Lang966c9402017-04-18 12:38:27 -04001179bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
1180{
1181 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
1182 (size % blockSize == 0);
1183}
1184
Jamie Madillc29968b2016-01-20 11:17:23 -05001185bool ValidCompressedImageSize(const ValidationContext *context,
1186 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -04001187 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -05001188 GLsizei width,
1189 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001190{
Geoff Langca271392017-04-05 12:30:00 -04001191 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -04001192 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001193 {
1194 return false;
1195 }
1196
Geoff Lang966c9402017-04-18 12:38:27 -04001197 if (width < 0 || height < 0)
1198 {
1199 return false;
1200 }
1201
1202 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1203 {
1204 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
1205 // block size for level 0 but WebGL disallows this.
1206 bool smallerThanBlockSizeAllowed =
1207 level > 0 || !context->getExtensions().webglCompatibility;
1208
1209 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
1210 smallerThanBlockSizeAllowed) ||
1211 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
1212 smallerThanBlockSizeAllowed))
1213 {
1214 return false;
1215 }
1216 }
1217
1218 return true;
1219}
1220
1221bool ValidCompressedSubImageSize(const ValidationContext *context,
1222 GLenum internalFormat,
1223 GLint xoffset,
1224 GLint yoffset,
1225 GLsizei width,
1226 GLsizei height,
1227 size_t textureWidth,
1228 size_t textureHeight)
1229{
1230 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
1231 if (!formatInfo.compressed)
1232 {
1233 return false;
1234 }
1235
Geoff Lang44ff5a72017-02-03 15:15:43 -05001236 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001237 {
1238 return false;
1239 }
1240
Geoff Lang0d8b7242015-09-09 14:56:53 -04001241 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1242 {
Geoff Lang44ff5a72017-02-03 15:15:43 -05001243 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -04001244 yoffset % formatInfo.compressedBlockHeight != 0)
1245 {
1246 return false;
1247 }
1248
1249 // Allowed to either have data that is a multiple of block size or is smaller than the block
1250 // size but fills the entire mip
1251 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
1252 static_cast<size_t>(width) == textureWidth &&
1253 static_cast<size_t>(height) == textureHeight;
1254 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
1255 (height % formatInfo.compressedBlockHeight) == 0;
1256 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -04001257 {
1258 return false;
1259 }
1260 }
1261
Geoff Langd4f180b2013-09-24 13:57:44 -04001262 return true;
1263}
1264
Geoff Langff5b2d52016-09-07 11:32:23 -04001265bool ValidImageDataSize(ValidationContext *context,
1266 GLenum textureTarget,
1267 GLsizei width,
1268 GLsizei height,
1269 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -04001270 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -04001271 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001272 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001273 GLsizei imageSize)
1274{
1275 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1276 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1277 {
1278 // Checks are not required
1279 return true;
1280 }
1281
1282 // ...the data would be unpacked from the buffer object such that the memory reads required
1283 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -04001284 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
1285 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -04001286 const gl::Extents size(width, height, depth);
1287 const auto &unpack = context->getGLState().getUnpackState();
1288
1289 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1290 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1291 if (endByteOrErr.isError())
1292 {
1293 context->handleError(endByteOrErr.getError());
1294 return false;
1295 }
1296
1297 GLuint endByte = endByteOrErr.getResult();
1298
1299 if (pixelUnpackBuffer)
1300 {
1301 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1302 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1303 checkedEndByte += checkedOffset;
1304
1305 if (!checkedEndByte.IsValid() ||
1306 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1307 {
1308 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001309 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04001310 return false;
1311 }
1312 }
1313 else
1314 {
1315 ASSERT(imageSize >= 0);
1316 if (pixels == nullptr && imageSize != 0)
1317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001318 context->handleError(InvalidOperation()
1319 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001320 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001321 }
1322
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001323 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001324 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001325 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001326 return false;
1327 }
1328 }
1329
1330 return true;
1331}
1332
Geoff Lang37dde692014-01-31 16:34:54 -05001333bool ValidQueryType(const Context *context, GLenum queryType)
1334{
He Yunchaoced53ae2016-11-29 15:00:51 +08001335 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1336 "GL extension enums not equal.");
1337 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1338 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001339
1340 switch (queryType)
1341 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001342 case GL_ANY_SAMPLES_PASSED:
1343 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1344 return true;
1345 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1346 return (context->getClientMajorVersion() >= 3);
1347 case GL_TIME_ELAPSED_EXT:
1348 return context->getExtensions().disjointTimerQuery;
1349 case GL_COMMANDS_COMPLETED_CHROMIUM:
1350 return context->getExtensions().syncQuery;
1351 default:
1352 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001353 }
1354}
1355
Geoff Lang2d62ab72017-03-23 16:54:40 -04001356bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
1357 GLenum type,
1358 GLboolean normalized,
1359 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001360 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001361 bool pureInteger)
1362{
1363 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001364 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1365 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1366 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1367 // parameter exceeds 255.
1368 constexpr GLsizei kMaxWebGLStride = 255;
1369 if (stride > kMaxWebGLStride)
1370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001371 context->handleError(InvalidValue()
1372 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001373 return false;
1374 }
1375
1376 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1377 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1378 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1379 // or an INVALID_OPERATION error is generated.
1380 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1381 size_t typeSize = GetVertexFormatTypeSize(internalType);
1382
1383 ASSERT(isPow2(typeSize) && typeSize > 0);
1384 size_t sizeMask = (typeSize - 1);
1385 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1386 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001387 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001388 return false;
1389 }
1390
1391 if ((stride & sizeMask) != 0)
1392 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001393 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001394 return false;
1395 }
1396
1397 return true;
1398}
1399
Jamie Madillef300b12016-10-07 15:12:09 -04001400Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001401{
He Yunchaoced53ae2016-11-29 15:00:51 +08001402 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1403 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1404 // or program object and INVALID_OPERATION if the provided name identifies an object
1405 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001406
Dian Xiang769769a2015-09-09 15:20:08 -07001407 Program *validProgram = context->getProgram(id);
1408
1409 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001410 {
Dian Xiang769769a2015-09-09 15:20:08 -07001411 if (context->getShader(id))
1412 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001413 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001414 }
1415 else
1416 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001417 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001418 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001419 }
Dian Xiang769769a2015-09-09 15:20:08 -07001420
1421 return validProgram;
1422}
1423
Jamie Madillef300b12016-10-07 15:12:09 -04001424Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001425{
1426 // See ValidProgram for spec details.
1427
1428 Shader *validShader = context->getShader(id);
1429
1430 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001431 {
Dian Xiang769769a2015-09-09 15:20:08 -07001432 if (context->getProgram(id))
1433 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001434 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001435 }
1436 else
1437 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001438 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001439 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001440 }
Dian Xiang769769a2015-09-09 15:20:08 -07001441
1442 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001443}
1444
Geoff Langb1196682014-07-23 13:47:29 -04001445bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001446{
1447 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1448 {
1449 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1450
Geoff Langaae65a42014-05-26 12:43:44 -04001451 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001452 {
Martin Radevd178aa42017-07-13 14:03:22 +03001453 context->handleError(
1454 InvalidOperation()
1455 << "attachment index cannot be greater or equal to MAX_COLOR_ATTACHMENTS.");
Geoff Langb1196682014-07-23 13:47:29 -04001456 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001457 }
1458 }
1459 else
1460 {
1461 switch (attachment)
1462 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001463 case GL_DEPTH_ATTACHMENT:
1464 case GL_STENCIL_ATTACHMENT:
1465 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001466
He Yunchaoced53ae2016-11-29 15:00:51 +08001467 case GL_DEPTH_STENCIL_ATTACHMENT:
1468 if (!context->getExtensions().webglCompatibility &&
1469 context->getClientMajorVersion() < 3)
1470 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001471 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001472 return false;
1473 }
1474 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001475
He Yunchaoced53ae2016-11-29 15:00:51 +08001476 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001477 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001478 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001479 }
1480 }
1481
1482 return true;
1483}
1484
Jamie Madille8fb6402017-02-14 17:56:40 -05001485bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001486 GLenum target,
1487 GLsizei samples,
1488 GLenum internalformat,
1489 GLsizei width,
1490 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001491{
1492 switch (target)
1493 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001494 case GL_RENDERBUFFER:
1495 break;
1496 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001497 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001498 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001499 }
1500
1501 if (width < 0 || height < 0 || samples < 0)
1502 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001503 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001504 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001505 }
1506
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001507 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1508 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1509
1510 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001511 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001513 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001514 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001515 }
1516
1517 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1518 // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
Corentin Walleze0902642014-11-04 12:32:15 -08001519 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001520 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1521 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001522 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001523 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001524 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001525 }
1526
Geoff Langaae65a42014-05-26 12:43:44 -04001527 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001528 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001529 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001530 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001531 }
1532
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001533 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001534 if (handle == 0)
1535 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001536 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001537 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001538 }
1539
1540 return true;
1541}
1542
He Yunchaoced53ae2016-11-29 15:00:51 +08001543bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1544 GLenum target,
1545 GLenum attachment,
1546 GLenum renderbuffertarget,
1547 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001548{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001549 if (!ValidFramebufferTarget(target))
1550 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001551 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001552 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001553 }
1554
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001555 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001556
Jamie Madill84115c92015-04-23 15:00:07 -04001557 ASSERT(framebuffer);
1558 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001559 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001560 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001561 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001562 }
1563
Jamie Madillb4472272014-07-03 10:38:55 -04001564 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001565 {
Jamie Madillb4472272014-07-03 10:38:55 -04001566 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001567 }
1568
Jamie Madillab9d82c2014-01-21 16:38:14 -05001569 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1570 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1571 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1572 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1573 if (renderbuffer != 0)
1574 {
1575 if (!context->getRenderbuffer(renderbuffer))
1576 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001577 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001578 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001579 }
1580 }
1581
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001582 return true;
1583}
1584
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001585bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001586 GLint srcX0,
1587 GLint srcY0,
1588 GLint srcX1,
1589 GLint srcY1,
1590 GLint dstX0,
1591 GLint dstY0,
1592 GLint dstX1,
1593 GLint dstY1,
1594 GLbitfield mask,
1595 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001596{
1597 switch (filter)
1598 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001599 case GL_NEAREST:
1600 break;
1601 case GL_LINEAR:
1602 break;
1603 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001604 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001605 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001606 }
1607
1608 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1609 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001610 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001611 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001612 }
1613
1614 if (mask == 0)
1615 {
1616 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1617 // buffers are copied.
1618 return false;
1619 }
1620
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001621 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1622 // color buffer, leaving only nearest being unfiltered from above
1623 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001625 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001626 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001627 }
1628
Jamie Madill51f40ec2016-06-15 14:06:00 -04001629 const auto &glState = context->getGLState();
1630 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1631 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001632
1633 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001634 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001635 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001636 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001637 }
1638
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001639 if (readFramebuffer->id() == drawFramebuffer->id())
1640 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001641 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001642 return false;
1643 }
1644
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001645 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001647 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001648 return false;
1649 }
1650
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001651 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001652 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001653 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001654 return false;
1655 }
1656
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001657 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001659 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001660 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001661 }
1662
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001663 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1664
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001665 if (mask & GL_COLOR_BUFFER_BIT)
1666 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001667 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001668 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001669
He Yunchao66a41a22016-12-15 16:45:05 +08001670 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001671 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001672 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001673
Geoff Langa15472a2015-08-11 11:48:03 -04001674 for (size_t drawbufferIdx = 0;
1675 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001676 {
Geoff Langa15472a2015-08-11 11:48:03 -04001677 const FramebufferAttachment *attachment =
1678 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1679 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001680 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001681 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001682
Geoff Langb2f3d052013-08-13 12:49:27 -04001683 // The GL ES 3.0.2 spec (pg 193) states that:
1684 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001685 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1686 // as well
1687 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1688 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001689 // Changes with EXT_color_buffer_float:
1690 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001691 GLenum readComponentType = readFormat.info->componentType;
1692 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001693 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001694 readComponentType == GL_SIGNED_NORMALIZED);
1695 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1696 drawComponentType == GL_SIGNED_NORMALIZED);
1697
1698 if (extensions.colorBufferFloat)
1699 {
1700 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1701 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1702
1703 if (readFixedOrFloat != drawFixedOrFloat)
1704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001705 context->handleError(InvalidOperation()
1706 << "If the read buffer contains fixed-point or "
1707 "floating-point values, the draw buffer must "
1708 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001709 return false;
1710 }
1711 }
1712 else if (readFixedPoint != drawFixedPoint)
1713 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001714 context->handleError(InvalidOperation()
1715 << "If the read buffer contains fixed-point values, "
1716 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001717 return false;
1718 }
1719
1720 if (readComponentType == GL_UNSIGNED_INT &&
1721 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001722 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001723 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001724 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001725 }
1726
Jamie Madill6163c752015-12-07 16:32:59 -05001727 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001728 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001729 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001730 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001731 }
1732
Jamie Madilla3944d42016-07-22 22:13:26 -04001733 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001734 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001735 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001736 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001737 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001738 }
Geoff Lange4915782017-04-12 15:19:07 -04001739
1740 if (context->getExtensions().webglCompatibility &&
1741 *readColorBuffer == *attachment)
1742 {
1743 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001744 InvalidOperation()
1745 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001746 return false;
1747 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001748 }
1749 }
1750
Jamie Madilla3944d42016-07-22 22:13:26 -04001751 if ((readFormat.info->componentType == GL_INT ||
1752 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1753 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001754 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001755 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001756 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001757 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001758 }
He Yunchao66a41a22016-12-15 16:45:05 +08001759 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1760 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1761 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1762 // situation is an application error that would lead to a crash in ANGLE.
1763 else if (drawFramebuffer->hasEnabledDrawBuffer())
1764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001765 context->handleError(
1766 InvalidOperation()
1767 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001768 return false;
1769 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001770 }
1771
He Yunchaoced53ae2016-11-29 15:00:51 +08001772 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001773 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1774 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001775 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001776 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001777 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001778 const gl::FramebufferAttachment *readBuffer =
1779 readFramebuffer->getAttachment(attachments[i]);
1780 const gl::FramebufferAttachment *drawBuffer =
1781 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001782
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001783 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001784 {
Kenneth Russell69382852017-07-21 16:38:44 -04001785 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001786 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001787 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001788 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001789 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001790
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001791 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001792 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001793 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001794 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001795 }
Geoff Lange4915782017-04-12 15:19:07 -04001796
1797 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1798 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001799 context->handleError(
1800 InvalidOperation()
1801 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001802 return false;
1803 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001804 }
He Yunchao66a41a22016-12-15 16:45:05 +08001805 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1806 else if (drawBuffer)
1807 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001808 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1809 "depth/stencil attachment of a "
1810 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001811 return false;
1812 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001813 }
1814 }
1815
Martin Radeva3ed4572017-07-27 18:29:37 +03001816 // ANGLE_multiview, Revision 1:
1817 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1818 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1819 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1820 {
1821 context->handleError(InvalidFramebufferOperation()
1822 << "Attempt to read from a multi-view framebuffer.");
1823 return false;
1824 }
1825 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1826 {
1827 context->handleError(InvalidFramebufferOperation()
1828 << "Attempt to write to a multi-view framebuffer.");
1829 return false;
1830 }
1831
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001832 return true;
1833}
1834
Jamie Madill4928b7c2017-06-20 12:57:39 -04001835bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001836 GLint x,
1837 GLint y,
1838 GLsizei width,
1839 GLsizei height,
1840 GLenum format,
1841 GLenum type,
1842 GLsizei bufSize,
1843 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001844 GLsizei *columns,
1845 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001846 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001847{
1848 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001849 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001850 return false;
1851 }
1852
Geoff Lang62fce5b2016-09-30 10:46:35 -04001853 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001854 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001855 {
Geoff Langb1196682014-07-23 13:47:29 -04001856 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001857 }
1858
Geoff Lang62fce5b2016-09-30 10:46:35 -04001859 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001860 {
Geoff Langb1196682014-07-23 13:47:29 -04001861 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001862 }
1863
Jamie Madillc29968b2016-01-20 11:17:23 -05001864 return true;
1865}
1866
1867bool ValidateReadnPixelsEXT(Context *context,
1868 GLint x,
1869 GLint y,
1870 GLsizei width,
1871 GLsizei height,
1872 GLenum format,
1873 GLenum type,
1874 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001875 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001876{
1877 if (bufSize < 0)
1878 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001879 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001880 return false;
1881 }
1882
Geoff Lang62fce5b2016-09-30 10:46:35 -04001883 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001884 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001885}
Jamie Madill26e91952014-03-05 15:01:27 -05001886
Jamie Madill4928b7c2017-06-20 12:57:39 -04001887bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001888 GLint x,
1889 GLint y,
1890 GLsizei width,
1891 GLsizei height,
1892 GLenum format,
1893 GLenum type,
1894 GLsizei bufSize,
1895 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001896 GLsizei *columns,
1897 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001898 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001899{
1900 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001901 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001902 return false;
1903 }
1904
Geoff Lange93daba2017-03-30 13:54:40 -04001905 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1906 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001907 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001908 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001909 }
1910
Geoff Lang62fce5b2016-09-30 10:46:35 -04001911 if (!ValidateRobustBufferSize(context, bufSize, *length))
1912 {
1913 return false;
1914 }
1915
1916 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001917}
1918
Jamie Madillf0e04492017-08-26 15:28:42 -04001919bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001920{
1921 if (!context->getExtensions().occlusionQueryBoolean &&
1922 !context->getExtensions().disjointTimerQuery)
1923 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001924 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001925 return false;
1926 }
1927
Olli Etuaho41997e72016-03-10 13:38:39 +02001928 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001929}
1930
Jamie Madillf0e04492017-08-26 15:28:42 -04001931bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001932{
1933 if (!context->getExtensions().occlusionQueryBoolean &&
1934 !context->getExtensions().disjointTimerQuery)
1935 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001936 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001937 return false;
1938 }
1939
Olli Etuaho41997e72016-03-10 13:38:39 +02001940 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001941}
1942
Jamie Madillf0e04492017-08-26 15:28:42 -04001943bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1944{
1945 if (!context->getExtensions().occlusionQueryBoolean &&
1946 !context->getExtensions().disjointTimerQuery)
1947 {
1948 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1949 return false;
1950 }
1951
1952 return true;
1953}
1954
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001955bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001956{
1957 if (!ValidQueryType(context, target))
1958 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001959 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001960 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001961 }
1962
1963 if (id == 0)
1964 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001965 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001966 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001967 }
1968
1969 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1970 // of zero, if the active query object name for <target> is non-zero (for the
1971 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1972 // the active query for either target is non-zero), if <id> is the name of an
1973 // existing query object whose type does not match <target>, or if <id> is the
1974 // active query object name for any query type, the error INVALID_OPERATION is
1975 // generated.
1976
1977 // Ensure no other queries are active
1978 // NOTE: If other queries than occlusion are supported, we will need to check
1979 // separately that:
1980 // a) The query ID passed is not the current active query for any target/type
1981 // b) There are no active queries for the requested target (and in the case
1982 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1983 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001984
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001985 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001986 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001987 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001988 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001989 }
1990
1991 Query *queryObject = context->getQuery(id, true, target);
1992
1993 // check that name was obtained with glGenQueries
1994 if (!queryObject)
1995 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001996 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001997 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001998 }
1999
2000 // check for type mismatch
2001 if (queryObject->getType() != target)
2002 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002003 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04002004 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04002005 }
2006
2007 return true;
2008}
2009
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002010bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2011{
2012 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002013 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002014 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002015 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002016 return false;
2017 }
2018
2019 return ValidateBeginQueryBase(context, target, id);
2020}
2021
2022bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002023{
2024 if (!ValidQueryType(context, target))
2025 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002026 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04002027 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002028 }
2029
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002030 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002031
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002032 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002033 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002034 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04002035 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002036 }
2037
Jamie Madill45c785d2014-05-13 14:09:34 -04002038 return true;
2039}
2040
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002041bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2042{
2043 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002044 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002045 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002046 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002047 return false;
2048 }
2049
2050 return ValidateEndQueryBase(context, target);
2051}
2052
2053bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2054{
2055 if (!context->getExtensions().disjointTimerQuery)
2056 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002057 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002058 return false;
2059 }
2060
2061 if (target != GL_TIMESTAMP_EXT)
2062 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002063 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002064 return false;
2065 }
2066
2067 Query *queryObject = context->getQuery(id, true, target);
2068 if (queryObject == nullptr)
2069 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002070 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002071 return false;
2072 }
2073
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002074 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002075 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002076 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002077 return false;
2078 }
2079
2080 return true;
2081}
2082
Geoff Lang2186c382016-10-14 10:54:54 -04002083bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002084{
Geoff Lang2186c382016-10-14 10:54:54 -04002085 if (numParams)
2086 {
2087 *numParams = 0;
2088 }
2089
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002090 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2091 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002092 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002093 return false;
2094 }
2095
2096 switch (pname)
2097 {
2098 case GL_CURRENT_QUERY_EXT:
2099 if (target == GL_TIMESTAMP_EXT)
2100 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002101 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002102 return false;
2103 }
2104 break;
2105 case GL_QUERY_COUNTER_BITS_EXT:
2106 if (!context->getExtensions().disjointTimerQuery ||
2107 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2108 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002109 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002110 return false;
2111 }
2112 break;
2113 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002114 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002115 return false;
2116 }
2117
Geoff Lang2186c382016-10-14 10:54:54 -04002118 if (numParams)
2119 {
2120 // All queries return only one value
2121 *numParams = 1;
2122 }
2123
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002124 return true;
2125}
2126
2127bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2128{
2129 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002130 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002131 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002132 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002133 return false;
2134 }
2135
Geoff Lang2186c382016-10-14 10:54:54 -04002136 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002137}
2138
Geoff Lang2186c382016-10-14 10:54:54 -04002139bool ValidateGetQueryivRobustANGLE(Context *context,
2140 GLenum target,
2141 GLenum pname,
2142 GLsizei bufSize,
2143 GLsizei *length,
2144 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002145{
Geoff Lang2186c382016-10-14 10:54:54 -04002146 if (!ValidateRobustEntryPoint(context, bufSize))
2147 {
2148 return false;
2149 }
2150
2151 if (!ValidateGetQueryivBase(context, target, pname, length))
2152 {
2153 return false;
2154 }
2155
2156 if (!ValidateRobustBufferSize(context, bufSize, *length))
2157 {
2158 return false;
2159 }
2160
2161 return true;
2162}
2163
2164bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2165{
2166 if (numParams)
2167 {
2168 *numParams = 0;
2169 }
2170
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002171 Query *queryObject = context->getQuery(id, false, GL_NONE);
2172
2173 if (!queryObject)
2174 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002175 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002176 return false;
2177 }
2178
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002179 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002180 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002181 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002182 return false;
2183 }
2184
2185 switch (pname)
2186 {
2187 case GL_QUERY_RESULT_EXT:
2188 case GL_QUERY_RESULT_AVAILABLE_EXT:
2189 break;
2190
2191 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002192 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002193 return false;
2194 }
2195
Geoff Lang2186c382016-10-14 10:54:54 -04002196 if (numParams)
2197 {
2198 *numParams = 1;
2199 }
2200
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002201 return true;
2202}
2203
2204bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2205{
2206 if (!context->getExtensions().disjointTimerQuery)
2207 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002208 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002209 return false;
2210 }
Geoff Lang2186c382016-10-14 10:54:54 -04002211 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2212}
2213
2214bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2215 GLuint id,
2216 GLenum pname,
2217 GLsizei bufSize,
2218 GLsizei *length,
2219 GLint *params)
2220{
2221 if (!context->getExtensions().disjointTimerQuery)
2222 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002223 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04002224 return false;
2225 }
2226
2227 if (!ValidateRobustEntryPoint(context, bufSize))
2228 {
2229 return false;
2230 }
2231
2232 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2233 {
2234 return false;
2235 }
2236
2237 if (!ValidateRobustBufferSize(context, bufSize, *length))
2238 {
2239 return false;
2240 }
2241
2242 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002243}
2244
2245bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2246{
2247 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002248 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002249 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002250 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002251 return false;
2252 }
Geoff Lang2186c382016-10-14 10:54:54 -04002253 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2254}
2255
2256bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2257 GLuint id,
2258 GLenum pname,
2259 GLsizei bufSize,
2260 GLsizei *length,
2261 GLuint *params)
2262{
2263 if (!context->getExtensions().disjointTimerQuery &&
2264 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2265 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002266 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002267 return false;
2268 }
2269
2270 if (!ValidateRobustEntryPoint(context, bufSize))
2271 {
2272 return false;
2273 }
2274
2275 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2276 {
2277 return false;
2278 }
2279
2280 if (!ValidateRobustBufferSize(context, bufSize, *length))
2281 {
2282 return false;
2283 }
2284
2285 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002286}
2287
2288bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2289{
2290 if (!context->getExtensions().disjointTimerQuery)
2291 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002292 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002293 return false;
2294 }
Geoff Lang2186c382016-10-14 10:54:54 -04002295 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2296}
2297
2298bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2299 GLuint id,
2300 GLenum pname,
2301 GLsizei bufSize,
2302 GLsizei *length,
2303 GLint64 *params)
2304{
2305 if (!context->getExtensions().disjointTimerQuery)
2306 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002307 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002308 return false;
2309 }
2310
2311 if (!ValidateRobustEntryPoint(context, bufSize))
2312 {
2313 return false;
2314 }
2315
2316 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2317 {
2318 return false;
2319 }
2320
2321 if (!ValidateRobustBufferSize(context, bufSize, *length))
2322 {
2323 return false;
2324 }
2325
2326 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002327}
2328
2329bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2330{
2331 if (!context->getExtensions().disjointTimerQuery)
2332 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002333 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002334 return false;
2335 }
Geoff Lang2186c382016-10-14 10:54:54 -04002336 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2337}
2338
2339bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2340 GLuint id,
2341 GLenum pname,
2342 GLsizei bufSize,
2343 GLsizei *length,
2344 GLuint64 *params)
2345{
2346 if (!context->getExtensions().disjointTimerQuery)
2347 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002348 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002349 return false;
2350 }
2351
2352 if (!ValidateRobustEntryPoint(context, bufSize))
2353 {
2354 return false;
2355 }
2356
2357 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2358 {
2359 return false;
2360 }
2361
2362 if (!ValidateRobustBufferSize(context, bufSize, *length))
2363 {
2364 return false;
2365 }
2366
2367 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002368}
2369
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002370bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002371 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002372 GLuint program,
2373 GLint location,
2374 GLsizei count)
2375{
2376 // Check for ES31 program uniform entry points
2377 if (context->getClientVersion() < Version(3, 1))
2378 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002379 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002380 return false;
2381 }
2382
2383 const LinkedUniform *uniform = nullptr;
2384 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002385 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2386 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002387}
2388
Frank Henigmana98a6472017-02-02 21:38:32 -05002389bool ValidateProgramUniform1iv(gl::Context *context,
2390 GLuint program,
2391 GLint location,
2392 GLsizei count,
2393 const GLint *value)
2394{
2395 // Check for ES31 program uniform entry points
2396 if (context->getClientVersion() < Version(3, 1))
2397 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002398 context->handleError(InvalidOperation());
Frank Henigmana98a6472017-02-02 21:38:32 -05002399 return false;
2400 }
2401
2402 const LinkedUniform *uniform = nullptr;
2403 gl::Program *programObject = GetValidProgram(context, program);
2404 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2405 ValidateUniform1ivValue(context, uniform->type, count, value);
2406}
2407
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002408bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002409 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002410 GLuint program,
2411 GLint location,
2412 GLsizei count,
2413 GLboolean transpose)
2414{
2415 // Check for ES31 program uniform entry points
2416 if (context->getClientVersion() < Version(3, 1))
2417 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002418 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002419 return false;
2420 }
2421
2422 const LinkedUniform *uniform = nullptr;
2423 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002424 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2425 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002426}
2427
Jamie Madillc1d770e2017-04-13 17:31:24 -04002428bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002429{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002430 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002431 gl::Program *programObject = context->getGLState().getProgram();
2432 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2433 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002434}
2435
Jamie Madillbe849e42017-05-02 15:49:00 -04002436bool ValidateUniform1iv(ValidationContext *context,
2437 GLint location,
2438 GLsizei count,
2439 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002440{
2441 const LinkedUniform *uniform = nullptr;
2442 gl::Program *programObject = context->getGLState().getProgram();
2443 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2444 ValidateUniform1ivValue(context, uniform->type, count, value);
2445}
2446
Jamie Madillc1d770e2017-04-13 17:31:24 -04002447bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002448 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002449 GLint location,
2450 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002451 GLboolean transpose)
2452{
Martin Radev1be913c2016-07-11 17:59:16 +03002453 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002454 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002455 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002456 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002457 }
2458
Jamie Madill62d31cb2015-09-11 13:25:51 -04002459 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002460 gl::Program *programObject = context->getGLState().getProgram();
2461 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2462 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002463}
2464
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002465bool ValidateStateQuery(ValidationContext *context,
2466 GLenum pname,
2467 GLenum *nativeType,
2468 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002469{
2470 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2471 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002472 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002473 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002474 }
2475
Jamie Madill0af26e12015-03-05 19:54:33 -05002476 const Caps &caps = context->getCaps();
2477
Jamie Madill893ab082014-05-16 16:56:10 -04002478 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2479 {
2480 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2481
Jamie Madill0af26e12015-03-05 19:54:33 -05002482 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002483 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002484 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002485 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002486 }
2487 }
2488
2489 switch (pname)
2490 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002491 case GL_TEXTURE_BINDING_2D:
2492 case GL_TEXTURE_BINDING_CUBE_MAP:
2493 case GL_TEXTURE_BINDING_3D:
2494 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002495 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002496 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002497 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2498 if (!context->getExtensions().textureRectangle)
2499 {
2500 context->handleError(InvalidEnum()
2501 << "ANGLE_texture_rectangle extension not present");
2502 return false;
2503 }
2504 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002505 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2506 if (!context->getExtensions().eglStreamConsumerExternal &&
2507 !context->getExtensions().eglImageExternal)
2508 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002509 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2510 "nor GL_OES_EGL_image_external "
2511 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002512 return false;
2513 }
2514 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002515
He Yunchaoced53ae2016-11-29 15:00:51 +08002516 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2517 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002518 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002519 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2520 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002521 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002522 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002523 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002524 }
2525
Jamie Madill51f40ec2016-06-15 14:06:00 -04002526 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2527 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002528
2529 if (framebuffer->getReadBufferState() == GL_NONE)
2530 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002531 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002532 return false;
2533 }
2534
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002535 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002536 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002537 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002538 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002539 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002540 }
2541 }
2542 break;
2543
He Yunchaoced53ae2016-11-29 15:00:51 +08002544 default:
2545 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002546 }
2547
2548 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002549 if (*numParams == 0)
2550 {
2551 return false;
2552 }
2553
2554 return true;
2555}
2556
2557bool ValidateRobustStateQuery(ValidationContext *context,
2558 GLenum pname,
2559 GLsizei bufSize,
2560 GLenum *nativeType,
2561 unsigned int *numParams)
2562{
2563 if (!ValidateRobustEntryPoint(context, bufSize))
2564 {
2565 return false;
2566 }
2567
2568 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2569 {
2570 return false;
2571 }
2572
2573 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002574 {
2575 return false;
2576 }
2577
2578 return true;
2579}
2580
Jamie Madillc29968b2016-01-20 11:17:23 -05002581bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2582 GLenum target,
2583 GLint level,
2584 GLenum internalformat,
2585 bool isSubImage,
2586 GLint xoffset,
2587 GLint yoffset,
2588 GLint zoffset,
2589 GLint x,
2590 GLint y,
2591 GLsizei width,
2592 GLsizei height,
2593 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002594 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002595{
Brandon Jones6cad5662017-06-14 13:25:13 -07002596 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002597 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002598 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2599 return false;
2600 }
2601
2602 if (width < 0 || height < 0)
2603 {
2604 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002605 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002606 }
2607
He Yunchaoced53ae2016-11-29 15:00:51 +08002608 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2609 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002610 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002611 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002612 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002613 }
2614
2615 if (border != 0)
2616 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002617 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002618 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002619 }
2620
2621 if (!ValidMipLevel(context, target, level))
2622 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002623 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002624 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002625 }
2626
Jamie Madill51f40ec2016-06-15 14:06:00 -04002627 const auto &state = context->getGLState();
2628 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002629 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002630 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002631 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002632 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002633 }
2634
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002635 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002636 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002637 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002638 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002639 }
2640
Martin Radev138064f2016-07-15 12:03:41 +03002641 if (readFramebuffer->getReadBufferState() == GL_NONE)
2642 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002643 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002644 return false;
2645 }
2646
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002647 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2648 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002649 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002650 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002651 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2652 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002653 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002654 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002655 return false;
2656 }
2657
Martin Radev04e2c3b2017-07-27 16:54:35 +03002658 // ANGLE_multiview spec, Revision 1:
2659 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2660 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2661 // is not NONE.
2662 if (source->getMultiviewLayout() != GL_NONE)
2663 {
2664 context->handleError(InvalidFramebufferOperation()
2665 << "The active read framebuffer object has multiview attachments.");
2666 return false;
2667 }
2668
Geoff Langaae65a42014-05-26 12:43:44 -04002669 const gl::Caps &caps = context->getCaps();
2670
Geoff Langaae65a42014-05-26 12:43:44 -04002671 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002672 switch (target)
2673 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002674 case GL_TEXTURE_2D:
2675 maxDimension = caps.max2DTextureSize;
2676 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002677
He Yunchaoced53ae2016-11-29 15:00:51 +08002678 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2679 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2680 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2681 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2682 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2683 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2684 maxDimension = caps.maxCubeMapTextureSize;
2685 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002686
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002687 case GL_TEXTURE_RECTANGLE_ANGLE:
2688 maxDimension = caps.maxRectangleTextureSize;
2689 break;
2690
He Yunchaoced53ae2016-11-29 15:00:51 +08002691 case GL_TEXTURE_2D_ARRAY:
2692 maxDimension = caps.max2DTextureSize;
2693 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002694
He Yunchaoced53ae2016-11-29 15:00:51 +08002695 case GL_TEXTURE_3D:
2696 maxDimension = caps.max3DTextureSize;
2697 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002698
He Yunchaoced53ae2016-11-29 15:00:51 +08002699 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002700 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002701 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002702 }
2703
Jamie Madillc29968b2016-01-20 11:17:23 -05002704 gl::Texture *texture =
2705 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002706 if (!texture)
2707 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002708 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002709 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002710 }
2711
Geoff Lang69cce582015-09-17 13:20:36 -04002712 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002713 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002714 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002715 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002716 }
2717
Geoff Langca271392017-04-05 12:30:00 -04002718 const gl::InternalFormat &formatInfo =
2719 gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002720
Geoff Lang966c9402017-04-18 12:38:27 -04002721 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002722 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002723 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002724 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002725 }
2726
2727 if (isSubImage)
2728 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002729 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2730 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2731 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002732 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002733 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002734 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002735 }
2736 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002737 else
2738 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002739 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002740 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002741 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002742 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002743 }
2744
Geoff Langeb66a6e2016-10-31 13:06:12 -04002745 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002746 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002747 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002748 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002749 }
2750
2751 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002752 if (static_cast<int>(width) > maxLevelDimension ||
2753 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002754 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002755 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002756 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002757 }
2758 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002759
Jamie Madill0c8abca2016-07-22 20:21:26 -04002760 if (textureFormatOut)
2761 {
2762 *textureFormatOut = texture->getFormat(target, level);
2763 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002764
2765 // Detect texture copying feedback loops for WebGL.
2766 if (context->getExtensions().webglCompatibility)
2767 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002768 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002769 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002770 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002771 return false;
2772 }
2773 }
2774
Jamie Madill560a8d82014-05-21 13:06:20 -04002775 return true;
2776}
2777
Jiajia Qind9671222016-11-29 16:30:31 +08002778bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002779{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002780 switch (mode)
2781 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002782 case GL_POINTS:
2783 case GL_LINES:
2784 case GL_LINE_LOOP:
2785 case GL_LINE_STRIP:
2786 case GL_TRIANGLES:
2787 case GL_TRIANGLE_STRIP:
2788 case GL_TRIANGLE_FAN:
2789 break;
2790 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002791 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002792 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002793 }
2794
Jamie Madill250d33f2014-06-06 17:09:03 -04002795 if (count < 0)
2796 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002797 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002798 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002799 }
2800
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002801 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002802
Jamie Madill250d33f2014-06-06 17:09:03 -04002803 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002804 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002805 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002806 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002807 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002808 }
2809
Jamie Madillcbcde722017-01-06 14:50:00 -05002810 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2811 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002812 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002813 const Extensions &extensions = context->getExtensions();
2814 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002815 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002816 const FramebufferAttachment *dsAttachment =
2817 framebuffer->getStencilOrDepthStencilAttachment();
2818 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002819 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002820 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002821
2822 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2823 bool differentWritemasks =
2824 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2825 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2826 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2827 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2828
2829 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002830 {
Martin Radevffe754b2017-07-31 10:38:07 +03002831 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002832 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002833 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2834 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002835 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002836 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002837 return false;
2838 }
Jamie Madillac528012014-06-20 13:21:23 -04002839 }
2840
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002841 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002842 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002843 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002844 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002845 }
2846
Geoff Lang7dd2e102014-11-10 15:19:26 -05002847 gl::Program *program = state.getProgram();
2848 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002849 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002850 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002851 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002852 }
2853
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002854 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002855 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002856 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002857 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002858 }
2859
Martin Radevffe754b2017-07-31 10:38:07 +03002860 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002861 {
Martin Radev7e69f762017-07-27 14:54:13 +03002862 const int programNumViews = program->getNumViews();
2863 const int framebufferNumViews = framebuffer->getNumViews();
2864 if (programNumViews != -1 && framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002865 {
2866 context->handleError(InvalidOperation() << "The number of views in the active program "
2867 "and draw framebuffer does not match.");
2868 return false;
2869 }
Martin Radev7e69f762017-07-27 14:54:13 +03002870
2871 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2872 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2873 framebufferNumViews > 1)
2874 {
2875 context->handleError(InvalidOperation()
2876 << "There is an active transform feedback object "
2877 "when the number of views in the active draw "
2878 "framebuffer is greater than 1.");
2879 return false;
2880 }
Martin Radevffe754b2017-07-31 10:38:07 +03002881
2882 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2883 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2884 {
2885 context->handleError(InvalidOperation() << "There is an active query for target "
2886 "GL_TIME_ELAPSED_EXT when the number of "
2887 "views in the active draw framebuffer is "
2888 "greater than 1.");
2889 return false;
2890 }
Martin Radev7cf61662017-07-26 17:10:53 +03002891 }
2892
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002893 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002894 for (unsigned int uniformBlockIndex = 0;
2895 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002896 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002897 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002898 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002899 const OffsetBindingPointer<Buffer> &uniformBuffer =
2900 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002901
Geoff Lang5d124a62015-09-15 13:03:27 -04002902 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002903 {
2904 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002905 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002906 InvalidOperation()
2907 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002908 return false;
2909 }
2910
Geoff Lang5d124a62015-09-15 13:03:27 -04002911 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002912 if (uniformBufferSize == 0)
2913 {
2914 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002915 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002916 }
2917
Jamie Madill62d31cb2015-09-11 13:25:51 -04002918 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002919 {
2920 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002921 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002922 InvalidOperation()
2923 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002924 return false;
2925 }
2926 }
2927
Geoff Lange0cff192017-05-30 13:04:56 -04002928 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002929 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002930 {
Geoff Lange0cff192017-05-30 13:04:56 -04002931 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002932 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2933 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002934 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002935 return false;
2936 }
Geoff Lange0cff192017-05-30 13:04:56 -04002937
Geoff Lang9ab5b822017-05-30 16:19:23 -04002938 // Detect that the vertex shader input types match the attribute types
2939 if (!ValidateVertexShaderAttributeTypeMatch(context))
2940 {
2941 return false;
2942 }
2943
Geoff Lange0cff192017-05-30 13:04:56 -04002944 // Detect that the color buffer types match the fragment shader output types
2945 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2946 {
2947 return false;
2948 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002949 }
2950
Jamie Madill250d33f2014-06-06 17:09:03 -04002951 // No-op if zero count
2952 return (count > 0);
2953}
2954
Jamie Madillc1d770e2017-04-13 17:31:24 -04002955bool ValidateDrawArraysCommon(ValidationContext *context,
2956 GLenum mode,
2957 GLint first,
2958 GLsizei count,
2959 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002960{
Jamie Madillfd716582014-06-06 17:09:04 -04002961 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002962 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002963 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002964 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002965 }
2966
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002967 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002968 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002969 if (curTransformFeedback && curTransformFeedback->isActive() &&
2970 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002971 {
2972 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002973 // that does not match the current transform feedback object's draw mode (if transform
2974 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002975 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002976 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002977 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002978 }
2979
Jiajia Qind9671222016-11-29 16:30:31 +08002980 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002981 {
2982 return false;
2983 }
2984
Corentin Wallez71168a02016-12-19 15:11:18 -08002985 // Check the computation of maxVertex doesn't overflow.
2986 // - first < 0 or count < 0 have been checked as an error condition
2987 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2988 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2989 ASSERT(count > 0 && first >= 0);
2990 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2991 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002992 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002993 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002994 return false;
2995 }
2996
Corentin Wallez71168a02016-12-19 15:11:18 -08002997 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002998 {
2999 return false;
3000 }
3001
3002 return true;
3003}
3004
He Yunchaoced53ae2016-11-29 15:00:51 +08003005bool ValidateDrawArraysInstanced(Context *context,
3006 GLenum mode,
3007 GLint first,
3008 GLsizei count,
3009 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003010{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003011 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
Geoff Lang87a93302014-09-16 13:29:43 -04003012}
3013
He Yunchaoced53ae2016-11-29 15:00:51 +08003014bool ValidateDrawArraysInstancedANGLE(Context *context,
3015 GLenum mode,
3016 GLint first,
3017 GLsizei count,
3018 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003019{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003020 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003021 {
3022 return false;
3023 }
3024
Corentin Wallez0dc97812017-06-22 14:38:44 -04003025 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003026}
3027
Jiajia Qind9671222016-11-29 16:30:31 +08003028bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003029{
Jamie Madill250d33f2014-06-06 17:09:03 -04003030 switch (type)
3031 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003032 case GL_UNSIGNED_BYTE:
3033 case GL_UNSIGNED_SHORT:
3034 break;
3035 case GL_UNSIGNED_INT:
3036 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3037 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003038 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08003039 return false;
3040 }
3041 break;
3042 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003043 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08003044 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003045 }
3046
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003047 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003048
3049 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003050 if (curTransformFeedback && curTransformFeedback->isActive() &&
3051 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003052 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003053 // It is an invalid operation to call DrawElements, DrawRangeElements or
3054 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003055 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003056 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003057 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003058 }
3059
Jiajia Qind9671222016-11-29 16:30:31 +08003060 return true;
3061}
3062
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003063bool ValidateDrawElementsCommon(ValidationContext *context,
3064 GLenum mode,
3065 GLsizei count,
3066 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003067 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003068 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08003069{
3070 if (!ValidateDrawElementsBase(context, type))
3071 return false;
3072
3073 const State &state = context->getGLState();
3074
Corentin Wallez170efbf2017-05-02 13:45:01 -04003075 if (!ValidateDrawBase(context, mode, count))
3076 {
3077 return false;
3078 }
3079
Jamie Madill250d33f2014-06-06 17:09:03 -04003080 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003081 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003082 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003083 context->handleError(InvalidOperation() << "Index buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -04003084 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003085 }
3086
He Yunchaoced53ae2016-11-29 15:00:51 +08003087 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003088 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003089
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003090 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3091
3092 if (context->getExtensions().webglCompatibility)
3093 {
3094 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3095 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3096 {
3097 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3098 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3099 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003100 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003101 return false;
3102 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003103
3104 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3105 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3106 // error is generated.
3107 if (reinterpret_cast<intptr_t>(indices) < 0)
3108 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003109 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003110 return false;
3111 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003112 }
3113
3114 if (context->getExtensions().webglCompatibility ||
3115 !context->getGLState().areClientArraysEnabled())
3116 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003117 if (!elementArrayBuffer && count > 0)
3118 {
3119 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3120 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3121 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003122 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003123 return false;
3124 }
3125 }
3126
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003127 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003128 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003129 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003130 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003131 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3132 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3133 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3134 constexpr uint64_t kMaxTypeSize = 8;
3135 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3136 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3137 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003138
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003139 uint64_t typeSize = typeBytes;
3140 uint64_t elementCount = static_cast<uint64_t>(count);
3141 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3142
3143 // Doing the multiplication here is overflow-safe
3144 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3145
3146 // The offset can be any value, check for overflows
3147 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3148 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003149 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003150 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003151 return false;
3152 }
3153
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003154 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3155 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003156 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003157 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003158 return false;
3159 }
3160 }
3161 else if (!indices)
3162 {
3163 // This is an application error that would normally result in a crash,
3164 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003165 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04003166 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003167 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003168 }
3169
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003170 // Use the parameter buffer to retrieve and cache the index range.
3171 // TODO: offer fast path, with disabled index validation.
3172 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
3173 const auto &params = context->getParams<HasIndexRange>();
3174 const auto &indexRangeOpt = params.getIndexRange();
3175 if (!indexRangeOpt.valid())
3176 {
3177 // Unexpected error.
3178 return false;
3179 }
3180
3181 // If we use an index greater than our maximum supported index range, return an error.
3182 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3183 // return an error if possible here.
3184 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
3185 {
3186 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
3187 return false;
3188 }
3189
3190 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
3191 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003192 {
3193 return false;
3194 }
3195
Corentin Wallezc1346fb2017-08-24 16:11:26 +00003196 // No op if there are no real indices in the index data (all are primitive restart).
3197 return (indexRangeOpt.value().vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003198}
3199
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003200bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
3201 GLenum mode,
3202 GLsizei count,
3203 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003204 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003205 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003206{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003207 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003208}
3209
Geoff Lang3edfe032015-09-04 16:38:24 -04003210bool ValidateDrawElementsInstancedANGLE(Context *context,
3211 GLenum mode,
3212 GLsizei count,
3213 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003214 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003215 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003216{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003217 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003218 {
3219 return false;
3220 }
3221
Corentin Wallez0dc97812017-06-22 14:38:44 -04003222 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003223}
3224
He Yunchaoced53ae2016-11-29 15:00:51 +08003225bool ValidateFramebufferTextureBase(Context *context,
3226 GLenum target,
3227 GLenum attachment,
3228 GLuint texture,
3229 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003230{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003231 if (!ValidFramebufferTarget(target))
3232 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003233 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003234 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003235 }
3236
3237 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003238 {
3239 return false;
3240 }
3241
Jamie Madill55ec3b12014-07-03 10:38:57 -04003242 if (texture != 0)
3243 {
3244 gl::Texture *tex = context->getTexture(texture);
3245
Jamie Madillbe849e42017-05-02 15:49:00 -04003246 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003247 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003248 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003249 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003250 }
3251
3252 if (level < 0)
3253 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003254 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003255 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003256 }
3257 }
3258
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003259 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003260 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003261
Jamie Madill84115c92015-04-23 15:00:07 -04003262 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003263 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003264 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003265 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003266 }
3267
3268 return true;
3269}
3270
Geoff Langb1196682014-07-23 13:47:29 -04003271bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003272{
3273 if (program == 0)
3274 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003275 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003276 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003277 }
3278
Dian Xiang769769a2015-09-09 15:20:08 -07003279 gl::Program *programObject = GetValidProgram(context, program);
3280 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003281 {
3282 return false;
3283 }
3284
Jamie Madill0063c512014-08-25 15:47:53 -04003285 if (!programObject || !programObject->isLinked())
3286 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003287 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003288 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003289 }
3290
Geoff Lang7dd2e102014-11-10 15:19:26 -05003291 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003292 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003293 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003294 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003295 }
3296
Jamie Madill0063c512014-08-25 15:47:53 -04003297 return true;
3298}
3299
Geoff Langf41d0ee2016-10-07 13:04:23 -04003300static bool ValidateSizedGetUniform(Context *context,
3301 GLuint program,
3302 GLint location,
3303 GLsizei bufSize,
3304 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003305{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003306 if (length)
3307 {
3308 *length = 0;
3309 }
3310
Jamie Madill78f41802014-08-25 15:47:55 -04003311 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003312 {
Jamie Madill78f41802014-08-25 15:47:55 -04003313 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003314 }
3315
Geoff Langf41d0ee2016-10-07 13:04:23 -04003316 if (bufSize < 0)
3317 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003318 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003319 return false;
3320 }
3321
Jamie Madilla502c742014-08-28 17:19:13 -04003322 gl::Program *programObject = context->getProgram(program);
3323 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003324
Jamie Madill78f41802014-08-25 15:47:55 -04003325 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003326 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003327 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003328 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003329 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003330 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003331 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003332 }
3333
Geoff Langf41d0ee2016-10-07 13:04:23 -04003334 if (length)
3335 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003336 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003337 }
3338
Jamie Madill0063c512014-08-25 15:47:53 -04003339 return true;
3340}
3341
He Yunchaoced53ae2016-11-29 15:00:51 +08003342bool ValidateGetnUniformfvEXT(Context *context,
3343 GLuint program,
3344 GLint location,
3345 GLsizei bufSize,
3346 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003347{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003348 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003349}
3350
He Yunchaoced53ae2016-11-29 15:00:51 +08003351bool ValidateGetnUniformivEXT(Context *context,
3352 GLuint program,
3353 GLint location,
3354 GLsizei bufSize,
3355 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003356{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003357 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3358}
3359
3360bool ValidateGetUniformfvRobustANGLE(Context *context,
3361 GLuint program,
3362 GLint location,
3363 GLsizei bufSize,
3364 GLsizei *length,
3365 GLfloat *params)
3366{
3367 if (!ValidateRobustEntryPoint(context, bufSize))
3368 {
3369 return false;
3370 }
3371
3372 // bufSize is validated in ValidateSizedGetUniform
3373 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3374}
3375
3376bool ValidateGetUniformivRobustANGLE(Context *context,
3377 GLuint program,
3378 GLint location,
3379 GLsizei bufSize,
3380 GLsizei *length,
3381 GLint *params)
3382{
3383 if (!ValidateRobustEntryPoint(context, bufSize))
3384 {
3385 return false;
3386 }
3387
3388 // bufSize is validated in ValidateSizedGetUniform
3389 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3390}
3391
3392bool ValidateGetUniformuivRobustANGLE(Context *context,
3393 GLuint program,
3394 GLint location,
3395 GLsizei bufSize,
3396 GLsizei *length,
3397 GLuint *params)
3398{
3399 if (!ValidateRobustEntryPoint(context, bufSize))
3400 {
3401 return false;
3402 }
3403
3404 if (context->getClientMajorVersion() < 3)
3405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003406 context->handleError(InvalidOperation() << "Entry point requires at least OpenGL ES 3.0.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003407 return false;
3408 }
3409
3410 // bufSize is validated in ValidateSizedGetUniform
3411 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003412}
3413
He Yunchaoced53ae2016-11-29 15:00:51 +08003414bool ValidateDiscardFramebufferBase(Context *context,
3415 GLenum target,
3416 GLsizei numAttachments,
3417 const GLenum *attachments,
3418 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003419{
3420 if (numAttachments < 0)
3421 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003422 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003423 return false;
3424 }
3425
3426 for (GLsizei i = 0; i < numAttachments; ++i)
3427 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003428 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003429 {
3430 if (defaultFramebuffer)
3431 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003432 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003433 return false;
3434 }
3435
3436 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3437 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003438 context->handleError(InvalidOperation() << "Requested color attachment is "
3439 "greater than the maximum supported "
3440 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003441 return false;
3442 }
3443 }
3444 else
3445 {
3446 switch (attachments[i])
3447 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003448 case GL_DEPTH_ATTACHMENT:
3449 case GL_STENCIL_ATTACHMENT:
3450 case GL_DEPTH_STENCIL_ATTACHMENT:
3451 if (defaultFramebuffer)
3452 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003453 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3454 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003455 return false;
3456 }
3457 break;
3458 case GL_COLOR:
3459 case GL_DEPTH:
3460 case GL_STENCIL:
3461 if (!defaultFramebuffer)
3462 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003463 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3464 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003465 return false;
3466 }
3467 break;
3468 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003469 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003470 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003471 }
3472 }
3473 }
3474
3475 return true;
3476}
3477
Austin Kinross6ee1e782015-05-29 17:05:37 -07003478bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3479{
3480 // Note that debug marker calls must not set error state
3481
3482 if (length < 0)
3483 {
3484 return false;
3485 }
3486
3487 if (marker == nullptr)
3488 {
3489 return false;
3490 }
3491
3492 return true;
3493}
3494
3495bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3496{
3497 // Note that debug marker calls must not set error state
3498
3499 if (length < 0)
3500 {
3501 return false;
3502 }
3503
3504 if (length > 0 && marker == nullptr)
3505 {
3506 return false;
3507 }
3508
3509 return true;
3510}
3511
Geoff Langdcab33b2015-07-21 13:03:16 -04003512bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003513 GLenum target,
3514 egl::Image *image)
3515{
Geoff Langa8406172015-07-21 16:53:39 -04003516 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3517 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003518 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003519 return false;
3520 }
3521
3522 switch (target)
3523 {
3524 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003525 if (!context->getExtensions().eglImage)
3526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003527 context->handleError(InvalidEnum()
3528 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003529 }
3530 break;
3531
3532 case GL_TEXTURE_EXTERNAL_OES:
3533 if (!context->getExtensions().eglImageExternal)
3534 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003535 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3536 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003537 }
Geoff Langa8406172015-07-21 16:53:39 -04003538 break;
3539
3540 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003541 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003542 return false;
3543 }
3544
Jamie Madill61e16b42017-06-19 11:13:23 -04003545 ASSERT(context->getCurrentDisplay());
3546 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003547 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003548 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003549 return false;
3550 }
3551
3552 if (image->getSamples() > 0)
3553 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003554 context->handleError(InvalidOperation()
3555 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003556 return false;
3557 }
3558
Geoff Langca271392017-04-05 12:30:00 -04003559 const TextureCaps &textureCaps =
3560 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003561 if (!textureCaps.texturable)
3562 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003563 context->handleError(InvalidOperation()
3564 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003565 return false;
3566 }
3567
Geoff Langdcab33b2015-07-21 13:03:16 -04003568 return true;
3569}
3570
3571bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003572 GLenum target,
3573 egl::Image *image)
3574{
Geoff Langa8406172015-07-21 16:53:39 -04003575 if (!context->getExtensions().eglImage)
3576 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003577 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003578 return false;
3579 }
3580
3581 switch (target)
3582 {
3583 case GL_RENDERBUFFER:
3584 break;
3585
3586 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003587 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003588 return false;
3589 }
3590
Jamie Madill61e16b42017-06-19 11:13:23 -04003591 ASSERT(context->getCurrentDisplay());
3592 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003593 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003594 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003595 return false;
3596 }
3597
Geoff Langca271392017-04-05 12:30:00 -04003598 const TextureCaps &textureCaps =
3599 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003600 if (!textureCaps.renderable)
3601 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003602 context->handleError(InvalidOperation()
3603 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003604 return false;
3605 }
3606
Geoff Langdcab33b2015-07-21 13:03:16 -04003607 return true;
3608}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003609
3610bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3611{
Geoff Lang36167ab2015-12-07 10:27:14 -05003612 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003613 {
3614 // The default VAO should always exist
3615 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003616 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003617 return false;
3618 }
3619
3620 return true;
3621}
3622
Geoff Langc5629752015-12-07 16:29:04 -05003623bool ValidateProgramBinaryBase(Context *context,
3624 GLuint program,
3625 GLenum binaryFormat,
3626 const void *binary,
3627 GLint length)
3628{
3629 Program *programObject = GetValidProgram(context, program);
3630 if (programObject == nullptr)
3631 {
3632 return false;
3633 }
3634
3635 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3636 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3637 programBinaryFormats.end())
3638 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003639 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003640 return false;
3641 }
3642
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003643 if (context->hasActiveTransformFeedback(program))
3644 {
3645 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003646 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3647 "is associated with an active transform "
3648 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003649 return false;
3650 }
3651
Geoff Langc5629752015-12-07 16:29:04 -05003652 return true;
3653}
3654
3655bool ValidateGetProgramBinaryBase(Context *context,
3656 GLuint program,
3657 GLsizei bufSize,
3658 GLsizei *length,
3659 GLenum *binaryFormat,
3660 void *binary)
3661{
3662 Program *programObject = GetValidProgram(context, program);
3663 if (programObject == nullptr)
3664 {
3665 return false;
3666 }
3667
3668 if (!programObject->isLinked())
3669 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003670 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003671 return false;
3672 }
3673
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003674 if (context->getCaps().programBinaryFormats.empty())
3675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003676 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003677 return false;
3678 }
3679
Geoff Langc5629752015-12-07 16:29:04 -05003680 return true;
3681}
Jamie Madillc29968b2016-01-20 11:17:23 -05003682
Jamie Madillc29968b2016-01-20 11:17:23 -05003683bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3684{
3685 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003686 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003687 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003688 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3689 return false;
3690 }
3691 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3692 {
3693 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003694 return false;
3695 }
3696
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003697 ASSERT(context->getGLState().getDrawFramebuffer());
3698 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003699 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3700
3701 // This should come first before the check for the default frame buffer
3702 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3703 // rather than INVALID_OPERATION
3704 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3705 {
3706 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3707
3708 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003709 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3710 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003711 {
3712 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003713 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3714 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3715 // 3.1 is still a bit ambiguous about the error, but future specs are
3716 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003717 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003718 return false;
3719 }
3720 else if (bufs[colorAttachment] >= maxColorAttachment)
3721 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003722 context->handleError(InvalidOperation()
3723 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003724 return false;
3725 }
3726 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3727 frameBufferId != 0)
3728 {
3729 // INVALID_OPERATION-GL is bound to buffer and ith argument
3730 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003731 context->handleError(InvalidOperation()
3732 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003733 return false;
3734 }
3735 }
3736
3737 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3738 // and n is not 1 or bufs is bound to value other than BACK and NONE
3739 if (frameBufferId == 0)
3740 {
3741 if (n != 1)
3742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003743 context->handleError(InvalidOperation()
3744 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003745 return false;
3746 }
3747
3748 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3749 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003750 context->handleError(
3751 InvalidOperation()
3752 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003753 return false;
3754 }
3755 }
3756
3757 return true;
3758}
3759
Geoff Lang496c02d2016-10-20 11:38:11 -07003760bool ValidateGetBufferPointervBase(Context *context,
3761 GLenum target,
3762 GLenum pname,
3763 GLsizei *length,
3764 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003765{
Geoff Lang496c02d2016-10-20 11:38:11 -07003766 if (length)
3767 {
3768 *length = 0;
3769 }
3770
3771 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3772 {
3773 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003774 InvalidOperation()
3775 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003776 return false;
3777 }
3778
Olli Etuaho4f667482016-03-30 15:56:35 +03003779 if (!ValidBufferTarget(context, target))
3780 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003781 context->handleError(InvalidEnum() << "Buffer target not valid: 0x" << std::hex
3782 << std::uppercase << target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003783 return false;
3784 }
3785
Geoff Lang496c02d2016-10-20 11:38:11 -07003786 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003787 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003788 case GL_BUFFER_MAP_POINTER:
3789 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003790
Geoff Lang496c02d2016-10-20 11:38:11 -07003791 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003792 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003793 return false;
3794 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003795
3796 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3797 // target bound to zero generate an INVALID_OPERATION error."
3798 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003799 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003800 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003801 context->handleError(InvalidOperation()
3802 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003803 return false;
3804 }
3805
Geoff Lang496c02d2016-10-20 11:38:11 -07003806 if (length)
3807 {
3808 *length = 1;
3809 }
3810
Olli Etuaho4f667482016-03-30 15:56:35 +03003811 return true;
3812}
3813
3814bool ValidateUnmapBufferBase(Context *context, GLenum target)
3815{
3816 if (!ValidBufferTarget(context, target))
3817 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003818 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003819 return false;
3820 }
3821
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003822 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003823
3824 if (buffer == nullptr || !buffer->isMapped())
3825 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003826 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003827 return false;
3828 }
3829
3830 return true;
3831}
3832
3833bool ValidateMapBufferRangeBase(Context *context,
3834 GLenum target,
3835 GLintptr offset,
3836 GLsizeiptr length,
3837 GLbitfield access)
3838{
3839 if (!ValidBufferTarget(context, target))
3840 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003841 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003842 return false;
3843 }
3844
Brandon Jones6cad5662017-06-14 13:25:13 -07003845 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003846 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003847 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3848 return false;
3849 }
3850
3851 if (length < 0)
3852 {
3853 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003854 return false;
3855 }
3856
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003857 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003858
3859 if (!buffer)
3860 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003861 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003862 return false;
3863 }
3864
3865 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003866 CheckedNumeric<size_t> checkedOffset(offset);
3867 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003868
Jamie Madille2e406c2016-06-02 13:04:10 -04003869 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003870 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003871 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003872 return false;
3873 }
3874
3875 // Check for invalid bits in the mask
3876 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3877 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3878 GL_MAP_UNSYNCHRONIZED_BIT;
3879
3880 if (access & ~(allAccessBits))
3881 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003882 context->handleError(InvalidValue()
3883 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003884 return false;
3885 }
3886
3887 if (length == 0)
3888 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003889 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003890 return false;
3891 }
3892
3893 if (buffer->isMapped())
3894 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003895 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003896 return false;
3897 }
3898
3899 // Check for invalid bit combinations
3900 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3901 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003902 context->handleError(InvalidOperation()
3903 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003904 return false;
3905 }
3906
3907 GLbitfield writeOnlyBits =
3908 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3909
3910 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3911 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003912 context->handleError(InvalidOperation()
3913 << "Invalid access bits when mapping buffer for reading: 0x"
3914 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003915 return false;
3916 }
3917
3918 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3919 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003920 context->handleError(
3921 InvalidOperation()
3922 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003923 return false;
3924 }
Geoff Lang79f71042017-08-14 16:43:43 -04003925
3926 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003927}
3928
3929bool ValidateFlushMappedBufferRangeBase(Context *context,
3930 GLenum target,
3931 GLintptr offset,
3932 GLsizeiptr length)
3933{
Brandon Jones6cad5662017-06-14 13:25:13 -07003934 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003935 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003936 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3937 return false;
3938 }
3939
3940 if (length < 0)
3941 {
3942 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003943 return false;
3944 }
3945
3946 if (!ValidBufferTarget(context, target))
3947 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003948 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003949 return false;
3950 }
3951
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003952 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003953
3954 if (buffer == nullptr)
3955 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003956 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003957 return false;
3958 }
3959
3960 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3961 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003962 context->handleError(InvalidOperation()
3963 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003964 return false;
3965 }
3966
3967 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003968 CheckedNumeric<size_t> checkedOffset(offset);
3969 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003970
Jamie Madille2e406c2016-06-02 13:04:10 -04003971 if (!checkedSize.IsValid() ||
3972 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003973 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003974 context->handleError(InvalidValue()
3975 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003976 return false;
3977 }
3978
3979 return true;
3980}
3981
Olli Etuaho41997e72016-03-10 13:38:39 +02003982bool ValidateGenOrDelete(Context *context, GLint n)
3983{
3984 if (n < 0)
3985 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003986 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003987 return false;
3988 }
3989 return true;
3990}
3991
Geoff Langff5b2d52016-09-07 11:32:23 -04003992bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3993{
3994 if (!context->getExtensions().robustClientMemory)
3995 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003996 context->handleError(InvalidOperation()
3997 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003998 return false;
3999 }
4000
4001 if (bufSize < 0)
4002 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004003 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004004 return false;
4005 }
4006
4007 return true;
4008}
4009
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004010bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4011{
4012 if (bufSize < numParams)
4013 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004014 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4015 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004016 return false;
4017 }
4018
4019 return true;
4020}
4021
Jamie Madillbe849e42017-05-02 15:49:00 -04004022bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
4023 GLenum target,
4024 GLenum attachment,
4025 GLenum pname,
4026 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004027{
Geoff Langff5b2d52016-09-07 11:32:23 -04004028 if (!ValidFramebufferTarget(target))
4029 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004030 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004031 return false;
4032 }
4033
4034 int clientVersion = context->getClientMajorVersion();
4035
4036 switch (pname)
4037 {
4038 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4039 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4040 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4041 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4042 break;
4043
Martin Radeve5285d22017-07-14 16:23:53 +03004044 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4045 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4046 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4047 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4048 if (clientVersion < 3 || !context->getExtensions().multiview)
4049 {
4050 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4051 return false;
4052 }
4053 break;
4054
Geoff Langff5b2d52016-09-07 11:32:23 -04004055 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4056 if (clientVersion < 3 && !context->getExtensions().sRGB)
4057 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004058 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004059 return false;
4060 }
4061 break;
4062
4063 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4064 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4065 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4066 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4067 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4068 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4069 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4070 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4071 if (clientVersion < 3)
4072 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004073 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004074 return false;
4075 }
4076 break;
4077
4078 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004079 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004080 return false;
4081 }
4082
4083 // Determine if the attachment is a valid enum
4084 switch (attachment)
4085 {
4086 case GL_BACK:
4087 case GL_FRONT:
4088 case GL_DEPTH:
4089 case GL_STENCIL:
4090 case GL_DEPTH_STENCIL_ATTACHMENT:
4091 if (clientVersion < 3)
4092 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004093 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004094 return false;
4095 }
4096 break;
4097
4098 case GL_DEPTH_ATTACHMENT:
4099 case GL_STENCIL_ATTACHMENT:
4100 break;
4101
4102 default:
4103 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4104 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4105 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004106 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004107 return false;
4108 }
4109 break;
4110 }
4111
4112 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4113 ASSERT(framebuffer);
4114
4115 if (framebuffer->id() == 0)
4116 {
4117 if (clientVersion < 3)
4118 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004119 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004120 return false;
4121 }
4122
4123 switch (attachment)
4124 {
4125 case GL_BACK:
4126 case GL_DEPTH:
4127 case GL_STENCIL:
4128 break;
4129
4130 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004131 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004132 return false;
4133 }
4134 }
4135 else
4136 {
4137 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4138 {
4139 // Valid attachment query
4140 }
4141 else
4142 {
4143 switch (attachment)
4144 {
4145 case GL_DEPTH_ATTACHMENT:
4146 case GL_STENCIL_ATTACHMENT:
4147 break;
4148
4149 case GL_DEPTH_STENCIL_ATTACHMENT:
4150 if (!framebuffer->hasValidDepthStencil())
4151 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004152 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004153 return false;
4154 }
4155 break;
4156
4157 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07004158 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004159 return false;
4160 }
4161 }
4162 }
4163
4164 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4165 if (attachmentObject)
4166 {
4167 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4168 attachmentObject->type() == GL_TEXTURE ||
4169 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4170
4171 switch (pname)
4172 {
4173 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4174 if (attachmentObject->type() != GL_RENDERBUFFER &&
4175 attachmentObject->type() != GL_TEXTURE)
4176 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004177 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004178 return false;
4179 }
4180 break;
4181
4182 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4183 if (attachmentObject->type() != GL_TEXTURE)
4184 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004185 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004186 return false;
4187 }
4188 break;
4189
4190 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4191 if (attachmentObject->type() != GL_TEXTURE)
4192 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004193 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004194 return false;
4195 }
4196 break;
4197
4198 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4199 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4200 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004201 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004202 return false;
4203 }
4204 break;
4205
4206 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4207 if (attachmentObject->type() != GL_TEXTURE)
4208 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004209 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004210 return false;
4211 }
4212 break;
4213
4214 default:
4215 break;
4216 }
4217 }
4218 else
4219 {
4220 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4221 // is NONE, then querying any other pname will generate INVALID_ENUM.
4222
4223 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4224 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4225 // INVALID_OPERATION for all other pnames
4226
4227 switch (pname)
4228 {
4229 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4230 break;
4231
4232 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4233 if (clientVersion < 3)
4234 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004235 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004236 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004237 return false;
4238 }
4239 break;
4240
4241 default:
4242 if (clientVersion < 3)
4243 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004244 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004245 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004246 return false;
4247 }
4248 else
4249 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004250 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004251 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004252 return false;
4253 }
4254 }
4255 }
4256
Martin Radeve5285d22017-07-14 16:23:53 +03004257 if (numParams)
4258 {
4259 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4260 {
4261 // Only when the viewport offsets are queried we can have a varying number of output
4262 // parameters.
4263 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4264 *numParams = numViews * 2;
4265 }
4266 else
4267 {
4268 // For all other queries we can have only one output parameter.
4269 *numParams = 1;
4270 }
4271 }
4272
Geoff Langff5b2d52016-09-07 11:32:23 -04004273 return true;
4274}
4275
4276bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4277 GLenum target,
4278 GLenum attachment,
4279 GLenum pname,
4280 GLsizei bufSize,
4281 GLsizei *numParams)
4282{
4283 if (!ValidateRobustEntryPoint(context, bufSize))
4284 {
4285 return false;
4286 }
4287
Jamie Madillbe849e42017-05-02 15:49:00 -04004288 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4289 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004290 {
4291 return false;
4292 }
4293
4294 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4295 {
4296 return false;
4297 }
4298
4299 return true;
4300}
4301
Geoff Langff5b2d52016-09-07 11:32:23 -04004302bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4303 GLenum target,
4304 GLenum pname,
4305 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004306 GLsizei *length,
4307 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004308{
4309 if (!ValidateRobustEntryPoint(context, bufSize))
4310 {
4311 return false;
4312 }
4313
Geoff Langebebe1c2016-10-14 12:01:31 -04004314 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004315 {
4316 return false;
4317 }
4318
Geoff Langebebe1c2016-10-14 12:01:31 -04004319 if (!ValidateRobustBufferSize(context, bufSize, *length))
4320 {
4321 return false;
4322 }
4323
4324 return true;
4325}
4326
4327bool ValidateGetBufferParameteri64v(ValidationContext *context,
4328 GLenum target,
4329 GLenum pname,
4330 GLint64 *params)
4331{
4332 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4333}
4334
4335bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4336 GLenum target,
4337 GLenum pname,
4338 GLsizei bufSize,
4339 GLsizei *length,
4340 GLint64 *params)
4341{
4342 if (!ValidateRobustEntryPoint(context, bufSize))
4343 {
4344 return false;
4345 }
4346
4347 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4348 {
4349 return false;
4350 }
4351
4352 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004353 {
4354 return false;
4355 }
4356
4357 return true;
4358}
4359
Jamie Madillbe849e42017-05-02 15:49:00 -04004360bool ValidateGetProgramivBase(ValidationContext *context,
4361 GLuint program,
4362 GLenum pname,
4363 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004364{
4365 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004366 if (numParams)
4367 {
4368 *numParams = 1;
4369 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004370
4371 Program *programObject = GetValidProgram(context, program);
4372 if (!programObject)
4373 {
4374 return false;
4375 }
4376
4377 switch (pname)
4378 {
4379 case GL_DELETE_STATUS:
4380 case GL_LINK_STATUS:
4381 case GL_VALIDATE_STATUS:
4382 case GL_INFO_LOG_LENGTH:
4383 case GL_ATTACHED_SHADERS:
4384 case GL_ACTIVE_ATTRIBUTES:
4385 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4386 case GL_ACTIVE_UNIFORMS:
4387 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4388 break;
4389
4390 case GL_PROGRAM_BINARY_LENGTH:
4391 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4392 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004393 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4394 "requires GL_OES_get_program_binary or "
4395 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004396 return false;
4397 }
4398 break;
4399
4400 case GL_ACTIVE_UNIFORM_BLOCKS:
4401 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4402 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4403 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4404 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4405 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4406 if (context->getClientMajorVersion() < 3)
4407 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004408 context->handleError(InvalidEnum() << "Querying requires at least ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004409 return false;
4410 }
4411 break;
4412
Yunchao He61afff12017-03-14 15:34:03 +08004413 case GL_PROGRAM_SEPARABLE:
4414 if (context->getClientVersion() < Version(3, 1))
4415 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004416 context->handleError(InvalidEnum() << "Querying requires at least ES 3.1.");
Yunchao He61afff12017-03-14 15:34:03 +08004417 return false;
4418 }
4419 break;
4420
Geoff Langff5b2d52016-09-07 11:32:23 -04004421 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004422 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004423 return false;
4424 }
4425
4426 return true;
4427}
4428
4429bool ValidateGetProgramivRobustANGLE(Context *context,
4430 GLuint program,
4431 GLenum pname,
4432 GLsizei bufSize,
4433 GLsizei *numParams)
4434{
4435 if (!ValidateRobustEntryPoint(context, bufSize))
4436 {
4437 return false;
4438 }
4439
Jamie Madillbe849e42017-05-02 15:49:00 -04004440 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004441 {
4442 return false;
4443 }
4444
4445 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4446 {
4447 return false;
4448 }
4449
4450 return true;
4451}
4452
Geoff Lang740d9022016-10-07 11:20:52 -04004453bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4454 GLenum target,
4455 GLenum pname,
4456 GLsizei bufSize,
4457 GLsizei *length,
4458 GLint *params)
4459{
4460 if (!ValidateRobustEntryPoint(context, bufSize))
4461 {
4462 return false;
4463 }
4464
4465 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4466 {
4467 return false;
4468 }
4469
4470 if (!ValidateRobustBufferSize(context, bufSize, *length))
4471 {
4472 return false;
4473 }
4474
4475 return true;
4476}
4477
Geoff Langd7d0ed32016-10-07 11:33:51 -04004478bool ValidateGetShaderivRobustANGLE(Context *context,
4479 GLuint shader,
4480 GLenum pname,
4481 GLsizei bufSize,
4482 GLsizei *length,
4483 GLint *params)
4484{
4485 if (!ValidateRobustEntryPoint(context, bufSize))
4486 {
4487 return false;
4488 }
4489
4490 if (!ValidateGetShaderivBase(context, shader, pname, length))
4491 {
4492 return false;
4493 }
4494
4495 if (!ValidateRobustBufferSize(context, bufSize, *length))
4496 {
4497 return false;
4498 }
4499
4500 return true;
4501}
4502
Geoff Langc1984ed2016-10-07 12:41:00 -04004503bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4504 GLenum target,
4505 GLenum pname,
4506 GLsizei bufSize,
4507 GLsizei *length,
4508 GLfloat *params)
4509{
4510 if (!ValidateRobustEntryPoint(context, bufSize))
4511 {
4512 return false;
4513 }
4514
4515 if (!ValidateGetTexParameterBase(context, target, pname, length))
4516 {
4517 return false;
4518 }
4519
4520 if (!ValidateRobustBufferSize(context, bufSize, *length))
4521 {
4522 return false;
4523 }
4524
4525 return true;
4526}
4527
Geoff Langc1984ed2016-10-07 12:41:00 -04004528bool ValidateGetTexParameterivRobustANGLE(Context *context,
4529 GLenum target,
4530 GLenum pname,
4531 GLsizei bufSize,
4532 GLsizei *length,
4533 GLint *params)
4534{
4535 if (!ValidateRobustEntryPoint(context, bufSize))
4536 {
4537 return false;
4538 }
4539
4540 if (!ValidateGetTexParameterBase(context, target, pname, length))
4541 {
4542 return false;
4543 }
4544
4545 if (!ValidateRobustBufferSize(context, bufSize, *length))
4546 {
4547 return false;
4548 }
4549
4550 return true;
4551}
4552
Geoff Langc1984ed2016-10-07 12:41:00 -04004553bool ValidateTexParameterfvRobustANGLE(Context *context,
4554 GLenum target,
4555 GLenum pname,
4556 GLsizei bufSize,
4557 const GLfloat *params)
4558{
4559 if (!ValidateRobustEntryPoint(context, bufSize))
4560 {
4561 return false;
4562 }
4563
4564 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4565}
4566
Geoff Langc1984ed2016-10-07 12:41:00 -04004567bool ValidateTexParameterivRobustANGLE(Context *context,
4568 GLenum target,
4569 GLenum pname,
4570 GLsizei bufSize,
4571 const GLint *params)
4572{
4573 if (!ValidateRobustEntryPoint(context, bufSize))
4574 {
4575 return false;
4576 }
4577
4578 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4579}
4580
4581bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4582{
4583 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4584}
4585
4586bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4587 GLuint sampler,
4588 GLenum pname,
4589 GLuint bufSize,
4590 GLsizei *length,
4591 GLfloat *params)
4592{
4593 if (!ValidateRobustEntryPoint(context, bufSize))
4594 {
4595 return false;
4596 }
4597
4598 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4599 {
4600 return false;
4601 }
4602
4603 if (!ValidateRobustBufferSize(context, bufSize, *length))
4604 {
4605 return false;
4606 }
4607
4608 return true;
4609}
4610
4611bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4612{
4613 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4614}
4615
4616bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4617 GLuint sampler,
4618 GLenum pname,
4619 GLuint bufSize,
4620 GLsizei *length,
4621 GLint *params)
4622{
4623 if (!ValidateRobustEntryPoint(context, bufSize))
4624 {
4625 return false;
4626 }
4627
4628 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4629 {
4630 return false;
4631 }
4632
4633 if (!ValidateRobustBufferSize(context, bufSize, *length))
4634 {
4635 return false;
4636 }
4637
4638 return true;
4639}
4640
4641bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4642{
4643 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4644}
4645
4646bool ValidateSamplerParameterfv(Context *context,
4647 GLuint sampler,
4648 GLenum pname,
4649 const GLfloat *params)
4650{
4651 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4652}
4653
4654bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4655 GLuint sampler,
4656 GLenum pname,
4657 GLsizei bufSize,
4658 const GLfloat *params)
4659{
4660 if (!ValidateRobustEntryPoint(context, bufSize))
4661 {
4662 return false;
4663 }
4664
4665 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4666}
4667
4668bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4669{
4670 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4671}
4672
4673bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4674{
4675 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4676}
4677
4678bool ValidateSamplerParameterivRobustANGLE(Context *context,
4679 GLuint sampler,
4680 GLenum pname,
4681 GLsizei bufSize,
4682 const GLint *params)
4683{
4684 if (!ValidateRobustEntryPoint(context, bufSize))
4685 {
4686 return false;
4687 }
4688
4689 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4690}
4691
Geoff Lang0b031062016-10-13 14:30:04 -04004692bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4693 GLuint index,
4694 GLenum pname,
4695 GLsizei bufSize,
4696 GLsizei *length,
4697 GLfloat *params)
4698{
4699 if (!ValidateRobustEntryPoint(context, bufSize))
4700 {
4701 return false;
4702 }
4703
4704 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4705 {
4706 return false;
4707 }
4708
4709 if (!ValidateRobustBufferSize(context, bufSize, *length))
4710 {
4711 return false;
4712 }
4713
4714 return true;
4715}
4716
Geoff Lang0b031062016-10-13 14:30:04 -04004717bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4718 GLuint index,
4719 GLenum pname,
4720 GLsizei bufSize,
4721 GLsizei *length,
4722 GLint *params)
4723{
4724 if (!ValidateRobustEntryPoint(context, bufSize))
4725 {
4726 return false;
4727 }
4728
4729 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4730 {
4731 return false;
4732 }
4733
4734 if (!ValidateRobustBufferSize(context, bufSize, *length))
4735 {
4736 return false;
4737 }
4738
4739 return true;
4740}
4741
Geoff Lang0b031062016-10-13 14:30:04 -04004742bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4743 GLuint index,
4744 GLenum pname,
4745 GLsizei bufSize,
4746 GLsizei *length,
4747 void **pointer)
4748{
4749 if (!ValidateRobustEntryPoint(context, bufSize))
4750 {
4751 return false;
4752 }
4753
4754 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4755 {
4756 return false;
4757 }
4758
4759 if (!ValidateRobustBufferSize(context, bufSize, *length))
4760 {
4761 return false;
4762 }
4763
4764 return true;
4765}
4766
4767bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
4768{
4769 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4770}
4771
4772bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4773 GLuint index,
4774 GLenum pname,
4775 GLsizei bufSize,
4776 GLsizei *length,
4777 GLint *params)
4778{
4779 if (!ValidateRobustEntryPoint(context, bufSize))
4780 {
4781 return false;
4782 }
4783
4784 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4785 {
4786 return false;
4787 }
4788
4789 if (!ValidateRobustBufferSize(context, bufSize, *length))
4790 {
4791 return false;
4792 }
4793
4794 return true;
4795}
4796
4797bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
4798{
4799 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4800}
4801
4802bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4803 GLuint index,
4804 GLenum pname,
4805 GLsizei bufSize,
4806 GLsizei *length,
4807 GLuint *params)
4808{
4809 if (!ValidateRobustEntryPoint(context, bufSize))
4810 {
4811 return false;
4812 }
4813
4814 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4815 {
4816 return false;
4817 }
4818
4819 if (!ValidateRobustBufferSize(context, bufSize, *length))
4820 {
4821 return false;
4822 }
4823
4824 return true;
4825}
4826
Geoff Lang6899b872016-10-14 11:30:13 -04004827bool ValidateGetActiveUniformBlockiv(Context *context,
4828 GLuint program,
4829 GLuint uniformBlockIndex,
4830 GLenum pname,
4831 GLint *params)
4832{
4833 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
4834}
4835
4836bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4837 GLuint program,
4838 GLuint uniformBlockIndex,
4839 GLenum pname,
4840 GLsizei bufSize,
4841 GLsizei *length,
4842 GLint *params)
4843{
4844 if (!ValidateRobustEntryPoint(context, bufSize))
4845 {
4846 return false;
4847 }
4848
4849 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4850 {
4851 return false;
4852 }
4853
4854 if (!ValidateRobustBufferSize(context, bufSize, *length))
4855 {
4856 return false;
4857 }
4858
4859 return true;
4860}
4861
Geoff Lang0a9661f2016-10-20 10:59:20 -07004862bool ValidateGetInternalFormativ(Context *context,
4863 GLenum target,
4864 GLenum internalformat,
4865 GLenum pname,
4866 GLsizei bufSize,
4867 GLint *params)
4868{
4869 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4870 nullptr);
4871}
4872
4873bool ValidateGetInternalFormativRobustANGLE(Context *context,
4874 GLenum target,
4875 GLenum internalformat,
4876 GLenum pname,
4877 GLsizei bufSize,
4878 GLsizei *length,
4879 GLint *params)
4880{
4881 if (!ValidateRobustEntryPoint(context, bufSize))
4882 {
4883 return false;
4884 }
4885
4886 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4887 {
4888 return false;
4889 }
4890
4891 if (!ValidateRobustBufferSize(context, bufSize, *length))
4892 {
4893 return false;
4894 }
4895
4896 return true;
4897}
4898
Shao80957d92017-02-20 21:25:59 +08004899bool ValidateVertexFormatBase(ValidationContext *context,
4900 GLuint attribIndex,
4901 GLint size,
4902 GLenum type,
4903 GLboolean pureInteger)
4904{
4905 const Caps &caps = context->getCaps();
4906 if (attribIndex >= caps.maxVertexAttributes)
4907 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004908 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004909 return false;
4910 }
4911
4912 if (size < 1 || size > 4)
4913 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004914 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004915 return false;
Shao80957d92017-02-20 21:25:59 +08004916 }
4917
4918 switch (type)
4919 {
4920 case GL_BYTE:
4921 case GL_UNSIGNED_BYTE:
4922 case GL_SHORT:
4923 case GL_UNSIGNED_SHORT:
4924 break;
4925
4926 case GL_INT:
4927 case GL_UNSIGNED_INT:
4928 if (context->getClientMajorVersion() < 3)
4929 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004930 context->handleError(InvalidEnum()
4931 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004932 return false;
4933 }
4934 break;
4935
4936 case GL_FIXED:
4937 case GL_FLOAT:
4938 if (pureInteger)
4939 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004940 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004941 return false;
4942 }
4943 break;
4944
4945 case GL_HALF_FLOAT:
4946 if (context->getClientMajorVersion() < 3)
4947 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004948 context->handleError(InvalidEnum()
4949 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004950 return false;
4951 }
4952 if (pureInteger)
4953 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004954 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004955 return false;
4956 }
4957 break;
4958
4959 case GL_INT_2_10_10_10_REV:
4960 case GL_UNSIGNED_INT_2_10_10_10_REV:
4961 if (context->getClientMajorVersion() < 3)
4962 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004963 context->handleError(InvalidEnum()
4964 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004965 return false;
4966 }
4967 if (pureInteger)
4968 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004969 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004970 return false;
4971 }
4972 if (size != 4)
4973 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004974 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4975 "UNSIGNED_INT_2_10_10_10_REV and "
4976 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004977 return false;
4978 }
4979 break;
4980
4981 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004982 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004983 return false;
4984 }
4985
4986 return true;
4987}
4988
Geoff Lang76e65652017-03-27 14:58:02 -04004989// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4990// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4991// specified clear value and the type of a buffer that is being cleared generates an
4992// INVALID_OPERATION error instead of producing undefined results
4993bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4994 GLint drawbuffer,
4995 const GLenum *validComponentTypes,
4996 size_t validComponentTypeCount)
4997{
4998 const FramebufferAttachment *attachment =
4999 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5000 if (attachment)
5001 {
5002 GLenum componentType = attachment->getFormat().info->componentType;
5003 const GLenum *end = validComponentTypes + validComponentTypeCount;
5004 if (std::find(validComponentTypes, end, componentType) == end)
5005 {
5006 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005007 InvalidOperation()
5008 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005009 return false;
5010 }
5011 }
5012
5013 return true;
5014}
5015
Corentin Wallezb2931602017-04-11 15:58:57 -04005016bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
5017 GLsizei imageSize,
5018 GLsizei dataSize)
5019{
5020 if (!ValidateRobustEntryPoint(context, dataSize))
5021 {
5022 return false;
5023 }
5024
5025 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
5026 if (pixelUnpackBuffer == nullptr)
5027 {
5028 if (dataSize < imageSize)
5029 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005030 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005031 }
5032 }
5033 return true;
5034}
5035
Jamie Madillbe849e42017-05-02 15:49:00 -04005036bool ValidateGetBufferParameterBase(ValidationContext *context,
5037 GLenum target,
5038 GLenum pname,
5039 bool pointerVersion,
5040 GLsizei *numParams)
5041{
5042 if (numParams)
5043 {
5044 *numParams = 0;
5045 }
5046
5047 if (!ValidBufferTarget(context, target))
5048 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005049 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005050 return false;
5051 }
5052
5053 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5054 if (!buffer)
5055 {
5056 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005057 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005058 return false;
5059 }
5060
5061 const Extensions &extensions = context->getExtensions();
5062
5063 switch (pname)
5064 {
5065 case GL_BUFFER_USAGE:
5066 case GL_BUFFER_SIZE:
5067 break;
5068
5069 case GL_BUFFER_ACCESS_OES:
5070 if (!extensions.mapBuffer)
5071 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005072 context->handleError(InvalidEnum()
5073 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005074 return false;
5075 }
5076 break;
5077
5078 case GL_BUFFER_MAPPED:
5079 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5080 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5081 !extensions.mapBufferRange)
5082 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005083 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5084 "GL_OES_mapbuffer or "
5085 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005086 return false;
5087 }
5088 break;
5089
5090 case GL_BUFFER_MAP_POINTER:
5091 if (!pointerVersion)
5092 {
5093 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005094 InvalidEnum()
5095 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005096 return false;
5097 }
5098 break;
5099
5100 case GL_BUFFER_ACCESS_FLAGS:
5101 case GL_BUFFER_MAP_OFFSET:
5102 case GL_BUFFER_MAP_LENGTH:
5103 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5104 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005105 context->handleError(InvalidEnum()
5106 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005107 return false;
5108 }
5109 break;
5110
5111 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005112 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005113 return false;
5114 }
5115
5116 // All buffer parameter queries return one value.
5117 if (numParams)
5118 {
5119 *numParams = 1;
5120 }
5121
5122 return true;
5123}
5124
5125bool ValidateGetRenderbufferParameterivBase(Context *context,
5126 GLenum target,
5127 GLenum pname,
5128 GLsizei *length)
5129{
5130 if (length)
5131 {
5132 *length = 0;
5133 }
5134
5135 if (target != GL_RENDERBUFFER)
5136 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005137 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005138 return false;
5139 }
5140
5141 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5142 if (renderbuffer == nullptr)
5143 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005144 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005145 return false;
5146 }
5147
5148 switch (pname)
5149 {
5150 case GL_RENDERBUFFER_WIDTH:
5151 case GL_RENDERBUFFER_HEIGHT:
5152 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5153 case GL_RENDERBUFFER_RED_SIZE:
5154 case GL_RENDERBUFFER_GREEN_SIZE:
5155 case GL_RENDERBUFFER_BLUE_SIZE:
5156 case GL_RENDERBUFFER_ALPHA_SIZE:
5157 case GL_RENDERBUFFER_DEPTH_SIZE:
5158 case GL_RENDERBUFFER_STENCIL_SIZE:
5159 break;
5160
5161 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5162 if (!context->getExtensions().framebufferMultisample)
5163 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005164 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005165 return false;
5166 }
5167 break;
5168
5169 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005170 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005171 return false;
5172 }
5173
5174 if (length)
5175 {
5176 *length = 1;
5177 }
5178 return true;
5179}
5180
5181bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5182{
5183 if (length)
5184 {
5185 *length = 0;
5186 }
5187
5188 if (GetValidShader(context, shader) == nullptr)
5189 {
5190 return false;
5191 }
5192
5193 switch (pname)
5194 {
5195 case GL_SHADER_TYPE:
5196 case GL_DELETE_STATUS:
5197 case GL_COMPILE_STATUS:
5198 case GL_INFO_LOG_LENGTH:
5199 case GL_SHADER_SOURCE_LENGTH:
5200 break;
5201
5202 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5203 if (!context->getExtensions().translatedShaderSource)
5204 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005205 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005206 return false;
5207 }
5208 break;
5209
5210 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005211 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005212 return false;
5213 }
5214
5215 if (length)
5216 {
5217 *length = 1;
5218 }
5219 return true;
5220}
5221
5222bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
5223{
5224 if (length)
5225 {
5226 *length = 0;
5227 }
5228
5229 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5230 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005231 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005232 return false;
5233 }
5234
5235 if (context->getTargetTexture(target) == nullptr)
5236 {
5237 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005238 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005239 return false;
5240 }
5241
5242 switch (pname)
5243 {
5244 case GL_TEXTURE_MAG_FILTER:
5245 case GL_TEXTURE_MIN_FILTER:
5246 case GL_TEXTURE_WRAP_S:
5247 case GL_TEXTURE_WRAP_T:
5248 break;
5249
5250 case GL_TEXTURE_USAGE_ANGLE:
5251 if (!context->getExtensions().textureUsage)
5252 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005253 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005254 return false;
5255 }
5256 break;
5257
5258 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5259 if (!context->getExtensions().textureFilterAnisotropic)
5260 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005261 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005262 return false;
5263 }
5264 break;
5265
5266 case GL_TEXTURE_IMMUTABLE_FORMAT:
5267 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5268 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005269 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005270 return false;
5271 }
5272 break;
5273
5274 case GL_TEXTURE_WRAP_R:
5275 case GL_TEXTURE_IMMUTABLE_LEVELS:
5276 case GL_TEXTURE_SWIZZLE_R:
5277 case GL_TEXTURE_SWIZZLE_G:
5278 case GL_TEXTURE_SWIZZLE_B:
5279 case GL_TEXTURE_SWIZZLE_A:
5280 case GL_TEXTURE_BASE_LEVEL:
5281 case GL_TEXTURE_MAX_LEVEL:
5282 case GL_TEXTURE_MIN_LOD:
5283 case GL_TEXTURE_MAX_LOD:
5284 case GL_TEXTURE_COMPARE_MODE:
5285 case GL_TEXTURE_COMPARE_FUNC:
5286 if (context->getClientMajorVersion() < 3)
5287 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005288 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005289 return false;
5290 }
5291 break;
5292
5293 case GL_TEXTURE_SRGB_DECODE_EXT:
5294 if (!context->getExtensions().textureSRGBDecode)
5295 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005296 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005297 return false;
5298 }
5299 break;
5300
5301 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005302 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005303 return false;
5304 }
5305
5306 if (length)
5307 {
5308 *length = 1;
5309 }
5310 return true;
5311}
5312
5313bool ValidateGetVertexAttribBase(Context *context,
5314 GLuint index,
5315 GLenum pname,
5316 GLsizei *length,
5317 bool pointer,
5318 bool pureIntegerEntryPoint)
5319{
5320 if (length)
5321 {
5322 *length = 0;
5323 }
5324
5325 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5326 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005327 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005328 return false;
5329 }
5330
5331 if (index >= context->getCaps().maxVertexAttributes)
5332 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005333 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005334 return false;
5335 }
5336
5337 if (pointer)
5338 {
5339 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5340 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005341 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005342 return false;
5343 }
5344 }
5345 else
5346 {
5347 switch (pname)
5348 {
5349 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5350 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5351 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5352 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5353 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5354 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5355 case GL_CURRENT_VERTEX_ATTRIB:
5356 break;
5357
5358 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5359 static_assert(
5360 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5361 "ANGLE extension enums not equal to GL enums.");
5362 if (context->getClientMajorVersion() < 3 &&
5363 !context->getExtensions().instancedArrays)
5364 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005365 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5366 "requires OpenGL ES 3.0 or "
5367 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005368 return false;
5369 }
5370 break;
5371
5372 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5373 if (context->getClientMajorVersion() < 3)
5374 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005375 context->handleError(
5376 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005377 return false;
5378 }
5379 break;
5380
5381 case GL_VERTEX_ATTRIB_BINDING:
5382 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5383 if (context->getClientVersion() < ES_3_1)
5384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005385 context->handleError(InvalidEnum()
5386 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005387 return false;
5388 }
5389 break;
5390
5391 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005392 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005393 return false;
5394 }
5395 }
5396
5397 if (length)
5398 {
5399 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5400 {
5401 *length = 4;
5402 }
5403 else
5404 {
5405 *length = 1;
5406 }
5407 }
5408
5409 return true;
5410}
5411
Jamie Madill4928b7c2017-06-20 12:57:39 -04005412bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005413 GLint x,
5414 GLint y,
5415 GLsizei width,
5416 GLsizei height,
5417 GLenum format,
5418 GLenum type,
5419 GLsizei bufSize,
5420 GLsizei *length,
5421 GLsizei *columns,
5422 GLsizei *rows,
5423 void *pixels)
5424{
5425 if (length != nullptr)
5426 {
5427 *length = 0;
5428 }
5429 if (rows != nullptr)
5430 {
5431 *rows = 0;
5432 }
5433 if (columns != nullptr)
5434 {
5435 *columns = 0;
5436 }
5437
5438 if (width < 0 || height < 0)
5439 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005440 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005441 return false;
5442 }
5443
5444 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5445
5446 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5447 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005448 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005449 return false;
5450 }
5451
5452 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5453 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005454 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005455 return false;
5456 }
5457
5458 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5459 ASSERT(framebuffer);
5460
5461 if (framebuffer->getReadBufferState() == GL_NONE)
5462 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005463 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005464 return false;
5465 }
5466
5467 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5468 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5469 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5470 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5471 // situation is an application error that would lead to a crash in ANGLE.
5472 if (readBuffer == nullptr)
5473 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005474 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005475 return false;
5476 }
5477
Martin Radev28031682017-07-28 14:47:56 +03005478 // ANGLE_multiview, Revision 1:
5479 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5480 // current read framebuffer is not NONE.
5481 if (readBuffer->getMultiviewLayout() != GL_NONE)
5482 {
5483 context->handleError(InvalidFramebufferOperation()
5484 << "Attempting to read from a multi-view framebuffer.");
5485 return false;
5486 }
5487
Geoff Lang280ba992017-04-18 16:30:58 -04005488 if (context->getExtensions().webglCompatibility)
5489 {
5490 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5491 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5492 // and type before validating the combination of format and type. However, the
5493 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5494 // verifies that GL_INVALID_OPERATION is generated.
5495 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5496 // dEQP/WebGL.
5497 if (!ValidReadPixelsFormatEnum(context, format))
5498 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005499 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005500 return false;
5501 }
5502
5503 if (!ValidReadPixelsTypeEnum(context, type))
5504 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005505 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005506 return false;
5507 }
5508 }
5509
Jamie Madill4928b7c2017-06-20 12:57:39 -04005510 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5511 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005512 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5513
5514 bool validFormatTypeCombination =
5515 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5516
5517 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5518 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005519 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005520 return false;
5521 }
5522
5523 // Check for pixel pack buffer related API errors
5524 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5525 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5526 {
5527 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005528 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005529 return false;
5530 }
5531
5532 // .. the data would be packed to the buffer object such that the memory writes required
5533 // would exceed the data store size.
5534 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5535 const gl::Extents size(width, height, 1);
5536 const auto &pack = context->getGLState().getPackState();
5537
5538 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5539 if (endByteOrErr.isError())
5540 {
5541 context->handleError(endByteOrErr.getError());
5542 return false;
5543 }
5544
5545 size_t endByte = endByteOrErr.getResult();
5546 if (bufSize >= 0)
5547 {
5548 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5549 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005550 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005551 return false;
5552 }
5553 }
5554
5555 if (pixelPackBuffer != nullptr)
5556 {
5557 CheckedNumeric<size_t> checkedEndByte(endByte);
5558 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5559 checkedEndByte += checkedOffset;
5560
5561 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5562 {
5563 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005564 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005565 return false;
5566 }
5567 }
5568
5569 if (pixelPackBuffer == nullptr && length != nullptr)
5570 {
5571 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5572 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005573 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005574 return false;
5575 }
5576
5577 *length = static_cast<GLsizei>(endByte);
5578 }
5579
5580 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5581 angle::CheckedNumeric<int> clippedExtent(length);
5582 if (start < 0)
5583 {
5584 // "subtract" the area that is less than 0
5585 clippedExtent += start;
5586 }
5587
5588 const int readExtent = start + length;
5589 if (readExtent > bufferSize)
5590 {
5591 // Subtract the region to the right of the read buffer
5592 clippedExtent -= (readExtent - bufferSize);
5593 }
5594
5595 if (!clippedExtent.IsValid())
5596 {
5597 return 0;
5598 }
5599
5600 return std::max(clippedExtent.ValueOrDie(), 0);
5601 };
5602
5603 if (columns != nullptr)
5604 {
5605 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5606 }
5607
5608 if (rows != nullptr)
5609 {
5610 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5611 }
5612
5613 return true;
5614}
5615
5616template <typename ParamType>
5617bool ValidateTexParameterBase(Context *context,
5618 GLenum target,
5619 GLenum pname,
5620 GLsizei bufSize,
5621 const ParamType *params)
5622{
5623 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5624 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005625 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005626 return false;
5627 }
5628
5629 if (context->getTargetTexture(target) == nullptr)
5630 {
5631 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005632 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005633 return false;
5634 }
5635
5636 const GLsizei minBufSize = 1;
5637 if (bufSize >= 0 && bufSize < minBufSize)
5638 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005639 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005640 return false;
5641 }
5642
5643 switch (pname)
5644 {
5645 case GL_TEXTURE_WRAP_R:
5646 case GL_TEXTURE_SWIZZLE_R:
5647 case GL_TEXTURE_SWIZZLE_G:
5648 case GL_TEXTURE_SWIZZLE_B:
5649 case GL_TEXTURE_SWIZZLE_A:
5650 case GL_TEXTURE_BASE_LEVEL:
5651 case GL_TEXTURE_MAX_LEVEL:
5652 case GL_TEXTURE_COMPARE_MODE:
5653 case GL_TEXTURE_COMPARE_FUNC:
5654 case GL_TEXTURE_MIN_LOD:
5655 case GL_TEXTURE_MAX_LOD:
5656 if (context->getClientMajorVersion() < 3)
5657 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005658 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005659 return false;
5660 }
5661 if (target == GL_TEXTURE_EXTERNAL_OES &&
5662 !context->getExtensions().eglImageExternalEssl3)
5663 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005664 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5665 "available without "
5666 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005667 return false;
5668 }
5669 break;
5670
5671 default:
5672 break;
5673 }
5674
JiangYizhou4cff8d62017-07-06 14:54:09 +08005675 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5676 {
5677 switch (pname)
5678 {
5679 case GL_TEXTURE_MIN_FILTER:
5680 case GL_TEXTURE_MAG_FILTER:
5681 case GL_TEXTURE_WRAP_S:
5682 case GL_TEXTURE_WRAP_T:
5683 case GL_TEXTURE_WRAP_R:
5684 case GL_TEXTURE_MIN_LOD:
5685 case GL_TEXTURE_MAX_LOD:
5686 case GL_TEXTURE_COMPARE_MODE:
5687 case GL_TEXTURE_COMPARE_FUNC:
5688 context->handleError(InvalidEnum()
5689 << "Invalid parameter for 2D multisampled textures.");
5690 return false;
5691 }
5692 }
5693
Jamie Madillbe849e42017-05-02 15:49:00 -04005694 switch (pname)
5695 {
5696 case GL_TEXTURE_WRAP_S:
5697 case GL_TEXTURE_WRAP_T:
5698 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005699 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005700 bool restrictedWrapModes =
5701 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5702 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5703 {
5704 return false;
5705 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005706 }
5707 break;
5708
5709 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005710 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005711 bool restrictedMinFilter =
5712 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5713 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5714 {
5715 return false;
5716 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005717 }
5718 break;
5719
5720 case GL_TEXTURE_MAG_FILTER:
5721 if (!ValidateTextureMagFilterValue(context, params))
5722 {
5723 return false;
5724 }
5725 break;
5726
5727 case GL_TEXTURE_USAGE_ANGLE:
5728 switch (ConvertToGLenum(params[0]))
5729 {
5730 case GL_NONE:
5731 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5732 break;
5733
5734 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005735 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005736 return false;
5737 }
5738 break;
5739
5740 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5741 if (!context->getExtensions().textureFilterAnisotropic)
5742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005743 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005744 return false;
5745 }
5746
5747 // we assume the parameter passed to this validation method is truncated, not rounded
5748 if (params[0] < 1)
5749 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005750 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005751 return false;
5752 }
5753 break;
5754
5755 case GL_TEXTURE_MIN_LOD:
5756 case GL_TEXTURE_MAX_LOD:
5757 // any value is permissible
5758 break;
5759
5760 case GL_TEXTURE_COMPARE_MODE:
5761 if (!ValidateTextureCompareModeValue(context, params))
5762 {
5763 return false;
5764 }
5765 break;
5766
5767 case GL_TEXTURE_COMPARE_FUNC:
5768 if (!ValidateTextureCompareFuncValue(context, params))
5769 {
5770 return false;
5771 }
5772 break;
5773
5774 case GL_TEXTURE_SWIZZLE_R:
5775 case GL_TEXTURE_SWIZZLE_G:
5776 case GL_TEXTURE_SWIZZLE_B:
5777 case GL_TEXTURE_SWIZZLE_A:
5778 switch (ConvertToGLenum(params[0]))
5779 {
5780 case GL_RED:
5781 case GL_GREEN:
5782 case GL_BLUE:
5783 case GL_ALPHA:
5784 case GL_ZERO:
5785 case GL_ONE:
5786 break;
5787
5788 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005789 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005790 return false;
5791 }
5792 break;
5793
5794 case GL_TEXTURE_BASE_LEVEL:
5795 if (params[0] < 0)
5796 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005797 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005798 return false;
5799 }
5800 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5801 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005802 context->handleError(InvalidOperation()
5803 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005804 return false;
5805 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005806 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5807 {
5808 context->handleError(InvalidOperation()
5809 << "Base level must be 0 for multisampled textures.");
5810 return false;
5811 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005812 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5813 {
5814 context->handleError(InvalidOperation()
5815 << "Base level must be 0 for rectangle textures.");
5816 return false;
5817 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005818 break;
5819
5820 case GL_TEXTURE_MAX_LEVEL:
5821 if (params[0] < 0)
5822 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005823 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005824 return false;
5825 }
5826 break;
5827
5828 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5829 if (context->getClientVersion() < Version(3, 1))
5830 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005831 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005832 return false;
5833 }
5834 switch (ConvertToGLenum(params[0]))
5835 {
5836 case GL_DEPTH_COMPONENT:
5837 case GL_STENCIL_INDEX:
5838 break;
5839
5840 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005841 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005842 return false;
5843 }
5844 break;
5845
5846 case GL_TEXTURE_SRGB_DECODE_EXT:
5847 if (!ValidateTextureSRGBDecodeValue(context, params))
5848 {
5849 return false;
5850 }
5851 break;
5852
5853 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005854 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005855 return false;
5856 }
5857
5858 return true;
5859}
5860
5861template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5862template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5863
Jamie Madillc29968b2016-01-20 11:17:23 -05005864} // namespace gl