blob: f3ee4938cfc540868f590c2c7c312e6f5bec7224 [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.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050073 context->handleError(InvalidOperation()
74 << "An enabled vertex array has no buffer.");
Corentin Wallezfd456442016-12-21 17:57:00 -050075 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050076 }
Corentin Wallezfd456442016-12-21 17:57:00 -050077 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040078 {
79 // This is an application error that would normally result in a crash,
80 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -050081 context->handleError(InvalidOperation()
82 << "An enabled vertex array has no buffer and no pointer.");
Jamie Madill1ca74672015-07-21 15:14:11 -040083 return false;
84 }
Corentin Wallezfd456442016-12-21 17:57:00 -050085 continue;
86 }
87
Corentin Wallez672f7f32017-06-15 17:42:17 -040088 // This needs to come after the check for client arrays as even unused attributes cannot use
89 // client-side arrays
90 if (!program->isAttribLocationActive(attributeIndex))
91 {
92 continue;
93 }
94
Corentin Wallezfd456442016-12-21 17:57:00 -050095 // If we're drawing zero vertices, we have enough data.
96 if (vertexCount <= 0 || primcount <= 0)
97 {
98 continue;
99 }
100
101 GLint maxVertexElement = 0;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300102 GLuint divisor = binding.getDivisor();
103 if (divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500104 {
105 maxVertexElement = maxVertex;
106 }
107 else
108 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300109 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500110 }
111
112 // We do manual overflow checks here instead of using safe_math.h because it was
113 // a bottleneck. Thanks to some properties of GL we know inequalities that can
114 // help us make the overflow checks faster.
115
116 // The max possible attribSize is 16 for a vector of 4 32 bit values.
117 constexpr uint64_t kMaxAttribSize = 16;
118 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
119 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
120
121 // We know attribStride is given as a GLsizei which is typedefed to int.
122 // We also know an upper bound for attribSize.
123 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800124 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500125 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
126 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
127
128 // Computing the max offset using uint64_t without attrib.offset is overflow
129 // safe. Note: Last vertex element does not take the full stride!
130 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
131 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
132
133 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800134 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
135 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500136 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500137 context->handleError(InvalidOperation() << "Integer overflow.");
Corentin Wallezfd456442016-12-21 17:57:00 -0500138 return false;
139 }
140 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
141
142 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
143 // We can return INVALID_OPERATION if our vertex attribute does not have
144 // enough backing data.
145 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
146 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500147 context->handleError(InvalidOperation()
148 << "Vertex buffer is not big enough for the draw call");
Corentin Wallezfd456442016-12-21 17:57:00 -0500149 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400150 }
151 }
152
153 return true;
154}
155
Geoff Lang280ba992017-04-18 16:30:58 -0400156bool ValidReadPixelsTypeEnum(ValidationContext *context, GLenum type)
157{
158 switch (type)
159 {
160 // Types referenced in Table 3.4 of the ES 2.0.25 spec
161 case GL_UNSIGNED_BYTE:
162 case GL_UNSIGNED_SHORT_4_4_4_4:
163 case GL_UNSIGNED_SHORT_5_5_5_1:
164 case GL_UNSIGNED_SHORT_5_6_5:
165 return context->getClientVersion() >= ES_2_0;
166
167 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
168 case GL_BYTE:
169 case GL_INT:
170 case GL_SHORT:
171 case GL_UNSIGNED_INT:
172 case GL_UNSIGNED_INT_10F_11F_11F_REV:
173 case GL_UNSIGNED_INT_24_8:
174 case GL_UNSIGNED_INT_2_10_10_10_REV:
175 case GL_UNSIGNED_INT_5_9_9_9_REV:
176 case GL_UNSIGNED_SHORT:
177 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
178 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
179 return context->getClientVersion() >= ES_3_0;
180
181 case GL_FLOAT:
182 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat;
183
184 case GL_HALF_FLOAT:
185 return context->getClientVersion() >= ES_3_0 ||
186 context->getExtensions().textureHalfFloat;
187
188 case GL_HALF_FLOAT_OES:
189 return context->getExtensions().colorBufferHalfFloat;
190
191 default:
192 return false;
193 }
194}
195
196bool ValidReadPixelsFormatEnum(ValidationContext *context, GLenum format)
197{
198 switch (format)
199 {
200 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
201 case GL_RGBA:
202 case GL_RGB:
203 case GL_ALPHA:
204 return context->getClientVersion() >= ES_2_0;
205
206 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
207 case GL_RG:
208 case GL_RED:
209 case GL_RGBA_INTEGER:
210 case GL_RGB_INTEGER:
211 case GL_RG_INTEGER:
212 case GL_RED_INTEGER:
213 return context->getClientVersion() >= ES_3_0;
214
215 case GL_SRGB_ALPHA_EXT:
216 case GL_SRGB_EXT:
217 return context->getExtensions().sRGB;
218
219 case GL_BGRA_EXT:
220 return context->getExtensions().readFormatBGRA;
221
222 default:
223 return false;
224 }
225}
226
Geoff Langf607c602016-09-21 11:46:48 -0400227bool ValidReadPixelsFormatType(ValidationContext *context,
228 GLenum framebufferComponentType,
229 GLenum format,
230 GLenum type)
231{
232 switch (framebufferComponentType)
233 {
234 case GL_UNSIGNED_NORMALIZED:
235 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
236 // ReadPixels with BGRA even if the extension is not present
237 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
238 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
239 type == GL_UNSIGNED_BYTE);
240
241 case GL_SIGNED_NORMALIZED:
242 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
243
244 case GL_INT:
245 return (format == GL_RGBA_INTEGER && type == GL_INT);
246
247 case GL_UNSIGNED_INT:
248 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
249
250 case GL_FLOAT:
251 return (format == GL_RGBA && type == GL_FLOAT);
252
253 default:
254 UNREACHABLE();
255 return false;
256 }
257}
258
Geoff Langc1984ed2016-10-07 12:41:00 -0400259template <typename ParamType>
260bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool isExternalTextureTarget)
261{
262 switch (ConvertToGLenum(params[0]))
263 {
264 case GL_CLAMP_TO_EDGE:
265 break;
266
267 case GL_REPEAT:
268 case GL_MIRRORED_REPEAT:
269 if (isExternalTextureTarget)
270 {
271 // OES_EGL_image_external specifies this error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500272 context->handleError(InvalidEnum()
273 << "external textures only support CLAMP_TO_EDGE wrap mode");
Geoff Langc1984ed2016-10-07 12:41:00 -0400274 return false;
275 }
276 break;
277
278 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500279 context->handleError(InvalidEnum() << "Unknown param value.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400280 return false;
281 }
282
283 return true;
284}
285
286template <typename ParamType>
287bool ValidateTextureMinFilterValue(Context *context,
288 ParamType *params,
289 bool isExternalTextureTarget)
290{
291 switch (ConvertToGLenum(params[0]))
292 {
293 case GL_NEAREST:
294 case GL_LINEAR:
295 break;
296
297 case GL_NEAREST_MIPMAP_NEAREST:
298 case GL_LINEAR_MIPMAP_NEAREST:
299 case GL_NEAREST_MIPMAP_LINEAR:
300 case GL_LINEAR_MIPMAP_LINEAR:
301 if (isExternalTextureTarget)
302 {
303 // OES_EGL_image_external specifies this error.
304 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500305 InvalidEnum() << "external textures only support NEAREST and LINEAR filtering");
Geoff Langc1984ed2016-10-07 12:41:00 -0400306 return false;
307 }
308 break;
309
310 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700311 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400312 return false;
313 }
314
315 return true;
316}
317
318template <typename ParamType>
319bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
320{
321 switch (ConvertToGLenum(params[0]))
322 {
323 case GL_NEAREST:
324 case GL_LINEAR:
325 break;
326
327 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700328 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400329 return false;
330 }
331
332 return true;
333}
334
335template <typename ParamType>
336bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
337{
338 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
339 switch (ConvertToGLenum(params[0]))
340 {
341 case GL_NONE:
342 case GL_COMPARE_REF_TO_TEXTURE:
343 break;
344
345 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500346 context->handleError(InvalidEnum() << "Unknown param value.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400347 return false;
348 }
349
350 return true;
351}
352
353template <typename ParamType>
354bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
355{
356 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
357 switch (ConvertToGLenum(params[0]))
358 {
359 case GL_LEQUAL:
360 case GL_GEQUAL:
361 case GL_LESS:
362 case GL_GREATER:
363 case GL_EQUAL:
364 case GL_NOTEQUAL:
365 case GL_ALWAYS:
366 case GL_NEVER:
367 break;
368
369 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500370 context->handleError(InvalidEnum() << "Unknown param value.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400371 return false;
372 }
373
374 return true;
375}
376
377template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700378bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
379{
380 if (!context->getExtensions().textureSRGBDecode)
381 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700382 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700383 return false;
384 }
385
386 switch (ConvertToGLenum(params[0]))
387 {
388 case GL_DECODE_EXT:
389 case GL_SKIP_DECODE_EXT:
390 break;
391
392 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500393 context->handleError(InvalidEnum() << "Unknown param value.");
Geoff Lang81c6b572016-10-19 14:07:52 -0700394 return false;
395 }
396
397 return true;
398}
399
400template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400401bool ValidateSamplerParameterBase(Context *context,
402 GLuint sampler,
403 GLenum pname,
404 GLsizei bufSize,
405 ParamType *params)
406{
407 if (context->getClientMajorVersion() < 3)
408 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500409 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400410 return false;
411 }
412
413 if (!context->isSampler(sampler))
414 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500415 context->handleError(InvalidOperation() << "Sampler is not valid.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400416 return false;
417 }
418
419 const GLsizei minBufSize = 1;
420 if (bufSize >= 0 && bufSize < minBufSize)
421 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500422 context->handleError(InvalidOperation() << "bufSize must be at least " << minBufSize);
Geoff Langc1984ed2016-10-07 12:41:00 -0400423 return false;
424 }
425
426 switch (pname)
427 {
428 case GL_TEXTURE_WRAP_S:
429 case GL_TEXTURE_WRAP_T:
430 case GL_TEXTURE_WRAP_R:
431 if (!ValidateTextureWrapModeValue(context, params, false))
432 {
433 return false;
434 }
435 break;
436
437 case GL_TEXTURE_MIN_FILTER:
438 if (!ValidateTextureMinFilterValue(context, params, false))
439 {
440 return false;
441 }
442 break;
443
444 case GL_TEXTURE_MAG_FILTER:
445 if (!ValidateTextureMagFilterValue(context, params))
446 {
447 return false;
448 }
449 break;
450
451 case GL_TEXTURE_MIN_LOD:
452 case GL_TEXTURE_MAX_LOD:
453 // any value is permissible
454 break;
455
456 case GL_TEXTURE_COMPARE_MODE:
457 if (!ValidateTextureCompareModeValue(context, params))
458 {
459 return false;
460 }
461 break;
462
463 case GL_TEXTURE_COMPARE_FUNC:
464 if (!ValidateTextureCompareFuncValue(context, params))
465 {
466 return false;
467 }
468 break;
469
Geoff Lang81c6b572016-10-19 14:07:52 -0700470 case GL_TEXTURE_SRGB_DECODE_EXT:
471 if (!ValidateTextureSRGBDecodeValue(context, params))
472 {
473 return false;
474 }
475 break;
476
Geoff Langc1984ed2016-10-07 12:41:00 -0400477 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700478 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langc1984ed2016-10-07 12:41:00 -0400479 return false;
480 }
481
482 return true;
483}
484
485bool ValidateGetSamplerParameterBase(Context *context,
486 GLuint sampler,
487 GLenum pname,
488 GLsizei *length)
489{
490 if (length)
491 {
492 *length = 0;
493 }
494
495 if (context->getClientMajorVersion() < 3)
496 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500497 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400498 return false;
499 }
500
501 if (!context->isSampler(sampler))
502 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500503 context->handleError(InvalidOperation() << "Sampler is not valid.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400504 return false;
505 }
506
507 switch (pname)
508 {
509 case GL_TEXTURE_WRAP_S:
510 case GL_TEXTURE_WRAP_T:
511 case GL_TEXTURE_WRAP_R:
512 case GL_TEXTURE_MIN_FILTER:
513 case GL_TEXTURE_MAG_FILTER:
514 case GL_TEXTURE_MIN_LOD:
515 case GL_TEXTURE_MAX_LOD:
516 case GL_TEXTURE_COMPARE_MODE:
517 case GL_TEXTURE_COMPARE_FUNC:
518 break;
519
Geoff Lang81c6b572016-10-19 14:07:52 -0700520 case GL_TEXTURE_SRGB_DECODE_EXT:
521 if (!context->getExtensions().textureSRGBDecode)
522 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500523 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Geoff Lang81c6b572016-10-19 14:07:52 -0700524 return false;
525 }
526 break;
527
Geoff Langc1984ed2016-10-07 12:41:00 -0400528 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700529 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langc1984ed2016-10-07 12:41:00 -0400530 return false;
531 }
532
533 if (length)
534 {
535 *length = 1;
536 }
537 return true;
538}
539
Geoff Lang6899b872016-10-14 11:30:13 -0400540bool ValidateGetActiveUniformBlockivBase(Context *context,
541 GLuint program,
542 GLuint uniformBlockIndex,
543 GLenum pname,
544 GLsizei *length)
545{
546 if (length)
547 {
548 *length = 0;
549 }
550
551 if (context->getClientMajorVersion() < 3)
552 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500553 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Lang6899b872016-10-14 11:30:13 -0400554 return false;
555 }
556
557 Program *programObject = GetValidProgram(context, program);
558 if (!programObject)
559 {
560 return false;
561 }
562
563 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
564 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500565 context->handleError(InvalidValue()
566 << "uniformBlockIndex exceeds active uniform block count.");
Geoff Lang6899b872016-10-14 11:30:13 -0400567 return false;
568 }
569
570 switch (pname)
571 {
572 case GL_UNIFORM_BLOCK_BINDING:
573 case GL_UNIFORM_BLOCK_DATA_SIZE:
574 case GL_UNIFORM_BLOCK_NAME_LENGTH:
575 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
576 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
577 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
578 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
579 break;
580
581 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700582 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang6899b872016-10-14 11:30:13 -0400583 return false;
584 }
585
586 if (length)
587 {
588 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
589 {
590 const UniformBlock &uniformBlock =
591 programObject->getUniformBlockByIndex(uniformBlockIndex);
jchen10eaef1e52017-06-13 10:44:11 +0800592 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
Geoff Lang6899b872016-10-14 11:30:13 -0400593 }
594 else
595 {
596 *length = 1;
597 }
598 }
599
600 return true;
601}
602
Geoff Lang0a9661f2016-10-20 10:59:20 -0700603bool ValidateGetInternalFormativBase(Context *context,
604 GLenum target,
605 GLenum internalformat,
606 GLenum pname,
607 GLsizei bufSize,
608 GLsizei *numParams)
609{
610 if (numParams)
611 {
612 *numParams = 0;
613 }
614
615 if (context->getClientMajorVersion() < 3)
616 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500617 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700618 return false;
619 }
620
621 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
622 if (!formatCaps.renderable)
623 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500624 context->handleError(InvalidEnum() << "Internal format is not renderable.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700625 return false;
626 }
627
628 switch (target)
629 {
630 case GL_RENDERBUFFER:
631 break;
632
JiangYizhoubddc46b2016-12-09 09:50:51 +0800633 case GL_TEXTURE_2D_MULTISAMPLE:
634 if (context->getClientVersion() < ES_3_1)
635 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500636 context->handleError(InvalidOperation()
637 << "Texture target requires at least OpenGL ES 3.1.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800638 return false;
639 }
640 break;
641
Geoff Lang0a9661f2016-10-20 10:59:20 -0700642 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500643 context->handleError(InvalidEnum() << "Invalid target.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700644 return false;
645 }
646
647 if (bufSize < 0)
648 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700649 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
Geoff Lang0a9661f2016-10-20 10:59:20 -0700650 return false;
651 }
652
653 GLsizei maxWriteParams = 0;
654 switch (pname)
655 {
656 case GL_NUM_SAMPLE_COUNTS:
657 maxWriteParams = 1;
658 break;
659
660 case GL_SAMPLES:
661 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
662 break;
663
664 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700665 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang0a9661f2016-10-20 10:59:20 -0700666 return false;
667 }
668
669 if (numParams)
670 {
671 // glGetInternalFormativ will not overflow bufSize
672 *numParams = std::min(bufSize, maxWriteParams);
673 }
674
675 return true;
676}
677
Jamie Madillc1d770e2017-04-13 17:31:24 -0400678bool ValidateUniformCommonBase(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500679 gl::Program *program,
680 GLint location,
681 GLsizei count,
682 const LinkedUniform **uniformOut)
683{
684 // TODO(Jiajia): Add image uniform check in future.
685 if (count < 0)
686 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700687 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500688 return false;
689 }
690
Brandon Jones6cad5662017-06-14 13:25:13 -0700691 if (!program)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500692 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700693 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
694 return false;
695 }
696
697 if (!program->isLinked())
698 {
699 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500700 return false;
701 }
702
703 if (location == -1)
704 {
705 // Silently ignore the uniform command
706 return false;
707 }
708
709 const auto &uniformLocations = program->getUniformLocations();
Jamie Madillbe849e42017-05-02 15:49:00 -0400710 size_t castedLocation = static_cast<size_t>(location);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500711 if (castedLocation >= uniformLocations.size())
712 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500713 context->handleError(InvalidOperation() << "Invalid uniform location");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500714 return false;
715 }
716
717 const auto &uniformLocation = uniformLocations[castedLocation];
718 if (uniformLocation.ignored)
719 {
720 // Silently ignore the uniform command
721 return false;
722 }
723
724 if (!uniformLocation.used)
725 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500726 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500727 return false;
728 }
729
730 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
731
732 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
733 if (!uniform.isArray() && count > 1)
734 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500735 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500736 return false;
737 }
738
739 *uniformOut = &uniform;
740 return true;
741}
742
Frank Henigman999b0fd2017-02-02 21:45:55 -0500743bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -0500744 GLenum uniformType,
745 GLsizei count,
746 const GLint *value)
747{
748 // Value type is GL_INT, because we only get here from glUniform1i{v}.
749 // It is compatible with INT or BOOL.
750 // Do these cheap tests first, for a little extra speed.
751 if (GL_INT == uniformType || GL_BOOL == uniformType)
752 {
753 return true;
754 }
755
756 if (IsSamplerType(uniformType))
757 {
Frank Henigman999b0fd2017-02-02 21:45:55 -0500758 // Check that the values are in range.
759 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
760 for (GLsizei i = 0; i < count; ++i)
761 {
762 if (value[i] < 0 || value[i] >= max)
763 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500764 context->handleError(InvalidValue() << "sampler uniform value out of range");
Frank Henigman999b0fd2017-02-02 21:45:55 -0500765 return false;
766 }
767 }
Frank Henigmana98a6472017-02-02 21:38:32 -0500768 return true;
769 }
770
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500771 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmana98a6472017-02-02 21:38:32 -0500772 return false;
773}
774
Jamie Madillc1d770e2017-04-13 17:31:24 -0400775bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500776{
777 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -0500778 // Do the cheaper test first, for a little extra speed.
779 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500780 {
781 return true;
782 }
783
Brandon Jones6cad5662017-06-14 13:25:13 -0700784 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeDoesNotMatchMethod);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500785 return false;
786}
787
Jamie Madillc1d770e2017-04-13 17:31:24 -0400788bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500789{
790 // Check that the value type is compatible with uniform type.
791 if (valueType == uniformType)
792 {
793 return true;
794 }
795
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500796 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500797 return false;
798}
799
Geoff Lange0cff192017-05-30 13:04:56 -0400800bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
801{
802 const Program *program = context->getGLState().getProgram();
803 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
804
805 const auto &programOutputTypes = program->getOutputVariableTypes();
806 for (size_t drawBufferIdx = 0; drawBufferIdx < programOutputTypes.size(); drawBufferIdx++)
807 {
808 GLenum outputType = programOutputTypes[drawBufferIdx];
809 GLenum inputType = framebuffer->getDrawbufferWriteType(drawBufferIdx);
810 if (outputType != GL_NONE && inputType != GL_NONE && inputType != outputType)
811 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500812 context->handleError(InvalidOperation() << "Fragment shader output type does not "
813 "match the bound framebuffer attachment "
814 "type.");
Geoff Lange0cff192017-05-30 13:04:56 -0400815 return false;
816 }
817 }
818
819 return true;
820}
821
Geoff Lang9ab5b822017-05-30 16:19:23 -0400822bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
823{
824 const Program *program = context->getGLState().getProgram();
825 const VertexArray *vao = context->getGLState().getVertexArray();
826
827 for (const auto &shaderAttribute : program->getAttributes())
828 {
Geoff Lang69df2422017-07-05 12:42:31 -0400829 // gl_VertexID and gl_InstanceID are active attributes but don't have a bound attribute.
830 if (shaderAttribute.isBuiltIn())
831 {
832 continue;
833 }
834
Geoff Lang9ab5b822017-05-30 16:19:23 -0400835 GLenum shaderInputType = VariableComponentType(shaderAttribute.type);
836
837 const auto &attrib = vao->getVertexAttribute(shaderAttribute.location);
838 const auto &currentValue =
839 context->getGLState().getVertexAttribCurrentValue(shaderAttribute.location);
840 GLenum vertexType = attrib.enabled ? GetVertexAttributeBaseType(attrib) : currentValue.Type;
841
842 if (shaderInputType != GL_NONE && vertexType != GL_NONE && shaderInputType != vertexType)
843 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500844 context->handleError(InvalidOperation() << "Vertex shader input type does not "
845 "match the type of the bound vertex "
846 "attribute.");
Geoff Lang9ab5b822017-05-30 16:19:23 -0400847 return false;
848 }
849 }
850
851 return true;
852}
853
Geoff Langf41a7152016-09-19 15:11:17 -0400854} // anonymous namespace
855
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500856bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400857{
Jamie Madilld7460c72014-01-21 16:38:14 -0500858 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400859 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800860 case GL_TEXTURE_2D:
861 case GL_TEXTURE_CUBE_MAP:
862 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400863
He Yunchaoced53ae2016-11-29 15:00:51 +0800864 case GL_TEXTURE_3D:
865 case GL_TEXTURE_2D_ARRAY:
866 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500867
He Yunchaoced53ae2016-11-29 15:00:51 +0800868 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800869 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400870
He Yunchaoced53ae2016-11-29 15:00:51 +0800871 default:
872 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500873 }
Jamie Madill35d15012013-10-07 10:46:37 -0400874}
875
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500876bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
877{
878 switch (target)
879 {
880 case GL_TEXTURE_2D:
881 case GL_TEXTURE_CUBE_MAP:
882 return true;
883
884 default:
885 return false;
886 }
887}
888
889bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
890{
891 switch (target)
892 {
893 case GL_TEXTURE_3D:
894 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300895 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500896
897 default:
898 return false;
899 }
900}
901
Ian Ewellbda75592016-04-18 17:25:54 -0400902// Most texture GL calls are not compatible with external textures, so we have a separate validation
903// function for use in the GL calls that do
904bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
905{
906 return (target == GL_TEXTURE_EXTERNAL_OES) &&
907 (context->getExtensions().eglImageExternal ||
908 context->getExtensions().eglStreamConsumerExternal);
909}
910
Shannon Woods4dfed832014-03-17 20:03:39 -0400911// This function differs from ValidTextureTarget in that the target must be
912// usable as the destination of a 2D operation-- so a cube face is valid, but
913// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400914// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500915bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400916{
917 switch (target)
918 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800919 case GL_TEXTURE_2D:
920 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
921 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
922 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
923 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
924 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
925 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
926 return true;
927 default:
928 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500929 }
930}
931
Jamie Madillbe849e42017-05-02 15:49:00 -0400932bool ValidateDrawElementsInstancedBase(ValidationContext *context,
933 GLenum mode,
934 GLsizei count,
935 GLenum type,
936 const GLvoid *indices,
937 GLsizei primcount)
938{
939 if (primcount < 0)
940 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500941 context->handleError(InvalidValue() << "primcount cannot be negative.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400942 return false;
943 }
944
945 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
946 {
947 return false;
948 }
949
950 // No-op zero primitive count
951 return (primcount > 0);
952}
953
954bool ValidateDrawArraysInstancedBase(Context *context,
955 GLenum mode,
956 GLint first,
957 GLsizei count,
958 GLsizei primcount)
959{
960 if (primcount < 0)
961 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500962 context->handleError(InvalidValue() << "primcount cannot be negative.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400963 return false;
964 }
965
966 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
967 {
968 return false;
969 }
970
971 // No-op if zero primitive count
972 return (primcount > 0);
973}
974
Corentin Wallez0dc97812017-06-22 14:38:44 -0400975bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400976{
977 // Verify there is at least one active attribute with a divisor of zero
978 const State &state = context->getGLState();
979
980 Program *program = state.getProgram();
981
982 const auto &attribs = state.getVertexArray()->getVertexAttributes();
983 const auto &bindings = state.getVertexArray()->getVertexBindings();
984 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
985 {
986 const VertexAttribute &attrib = attribs[attributeIndex];
987 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300988 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400989 {
990 return true;
991 }
992 }
993
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500994 context->handleError(InvalidOperation()
995 << "At least one attribute must have a divisor of zero.");
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;
1026 default:
1027 return false;
1028 }
1029}
1030
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001031bool ValidFramebufferTarget(GLenum target)
1032{
He Yunchaoced53ae2016-11-29 15:00:51 +08001033 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1034 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001035 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001036
1037 switch (target)
1038 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001039 case GL_FRAMEBUFFER:
1040 return true;
1041 case GL_READ_FRAMEBUFFER:
1042 return true;
1043 case GL_DRAW_FRAMEBUFFER:
1044 return true;
1045 default:
1046 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001047 }
1048}
1049
Jamie Madill29639852016-09-02 15:00:09 -04001050bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001051{
1052 switch (target)
1053 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001054 case GL_ARRAY_BUFFER:
1055 case GL_ELEMENT_ARRAY_BUFFER:
1056 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001057
He Yunchaoced53ae2016-11-29 15:00:51 +08001058 case GL_PIXEL_PACK_BUFFER:
1059 case GL_PIXEL_UNPACK_BUFFER:
1060 return (context->getExtensions().pixelBufferObject ||
1061 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001062
He Yunchaoced53ae2016-11-29 15:00:51 +08001063 case GL_COPY_READ_BUFFER:
1064 case GL_COPY_WRITE_BUFFER:
1065 case GL_TRANSFORM_FEEDBACK_BUFFER:
1066 case GL_UNIFORM_BUFFER:
1067 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001068
He Yunchaoced53ae2016-11-29 15:00:51 +08001069 case GL_ATOMIC_COUNTER_BUFFER:
1070 case GL_SHADER_STORAGE_BUFFER:
1071 case GL_DRAW_INDIRECT_BUFFER:
1072 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001073 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001074
He Yunchaoced53ae2016-11-29 15:00:51 +08001075 default:
1076 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001077 }
1078}
1079
Jamie Madillc29968b2016-01-20 11:17:23 -05001080bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001081{
Jamie Madillc29968b2016-01-20 11:17:23 -05001082 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001083 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001084 switch (target)
1085 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001086 case GL_TEXTURE_2D:
1087 maxDimension = caps.max2DTextureSize;
1088 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001089 case GL_TEXTURE_CUBE_MAP:
1090 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1091 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1092 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1093 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1094 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1095 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1096 maxDimension = caps.maxCubeMapTextureSize;
1097 break;
1098 case GL_TEXTURE_3D:
1099 maxDimension = caps.max3DTextureSize;
1100 break;
1101 case GL_TEXTURE_2D_ARRAY:
1102 maxDimension = caps.max2DTextureSize;
1103 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001104 case GL_TEXTURE_2D_MULTISAMPLE:
1105 maxDimension = caps.max2DTextureSize;
1106 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001107 default:
1108 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001109 }
1110
Brandon Jones6cad5662017-06-14 13:25:13 -07001111 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -04001112}
1113
Brandon Jones6cad5662017-06-14 13:25:13 -07001114bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001115 GLenum target,
1116 GLint level,
1117 GLsizei width,
1118 GLsizei height,
1119 GLsizei depth,
1120 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001121{
Brandon Jones6cad5662017-06-14 13:25:13 -07001122 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -04001123 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001124 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -04001125 return false;
1126 }
Austin Kinross08528e12015-10-07 16:24:40 -07001127 // TexSubImage parameters can be NPOT without textureNPOT extension,
1128 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001129 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001130 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001131 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001132 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001133 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001134 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -04001135 return false;
1136 }
1137
1138 if (!ValidMipLevel(context, target, level))
1139 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001140 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -04001141 return false;
1142 }
1143
1144 return true;
1145}
1146
Geoff Lang0d8b7242015-09-09 14:56:53 -04001147bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1148{
1149 // List of compressed format that require that the texture size is smaller than or a multiple of
1150 // the compressed block size.
1151 switch (internalFormat)
1152 {
1153 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1154 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1155 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1156 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langfff7a7d2017-06-02 10:39:17 -04001157 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
1158 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
1159 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
1160 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
Minmin Gonge3939b92015-12-01 15:36:51 -08001161 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001162 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1163 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1164 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1165 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1166 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
1167 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001168 return true;
1169
1170 default:
1171 return false;
1172 }
1173}
1174
Geoff Lang966c9402017-04-18 12:38:27 -04001175bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
1176{
1177 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
1178 (size % blockSize == 0);
1179}
1180
Jamie Madillc29968b2016-01-20 11:17:23 -05001181bool ValidCompressedImageSize(const ValidationContext *context,
1182 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -04001183 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -05001184 GLsizei width,
1185 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001186{
Geoff Langca271392017-04-05 12:30:00 -04001187 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -04001188 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001189 {
1190 return false;
1191 }
1192
Geoff Lang966c9402017-04-18 12:38:27 -04001193 if (width < 0 || height < 0)
1194 {
1195 return false;
1196 }
1197
1198 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1199 {
1200 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
1201 // block size for level 0 but WebGL disallows this.
1202 bool smallerThanBlockSizeAllowed =
1203 level > 0 || !context->getExtensions().webglCompatibility;
1204
1205 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
1206 smallerThanBlockSizeAllowed) ||
1207 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
1208 smallerThanBlockSizeAllowed))
1209 {
1210 return false;
1211 }
1212 }
1213
1214 return true;
1215}
1216
1217bool ValidCompressedSubImageSize(const ValidationContext *context,
1218 GLenum internalFormat,
1219 GLint xoffset,
1220 GLint yoffset,
1221 GLsizei width,
1222 GLsizei height,
1223 size_t textureWidth,
1224 size_t textureHeight)
1225{
1226 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
1227 if (!formatInfo.compressed)
1228 {
1229 return false;
1230 }
1231
Geoff Lang44ff5a72017-02-03 15:15:43 -05001232 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001233 {
1234 return false;
1235 }
1236
Geoff Lang0d8b7242015-09-09 14:56:53 -04001237 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1238 {
Geoff Lang44ff5a72017-02-03 15:15:43 -05001239 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -04001240 yoffset % formatInfo.compressedBlockHeight != 0)
1241 {
1242 return false;
1243 }
1244
1245 // Allowed to either have data that is a multiple of block size or is smaller than the block
1246 // size but fills the entire mip
1247 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
1248 static_cast<size_t>(width) == textureWidth &&
1249 static_cast<size_t>(height) == textureHeight;
1250 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
1251 (height % formatInfo.compressedBlockHeight) == 0;
1252 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -04001253 {
1254 return false;
1255 }
1256 }
1257
Geoff Langd4f180b2013-09-24 13:57:44 -04001258 return true;
1259}
1260
Geoff Langff5b2d52016-09-07 11:32:23 -04001261bool ValidImageDataSize(ValidationContext *context,
1262 GLenum textureTarget,
1263 GLsizei width,
1264 GLsizei height,
1265 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -04001266 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -04001267 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001268 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001269 GLsizei imageSize)
1270{
1271 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1272 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1273 {
1274 // Checks are not required
1275 return true;
1276 }
1277
1278 // ...the data would be unpacked from the buffer object such that the memory reads required
1279 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -04001280 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
1281 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -04001282 const gl::Extents size(width, height, depth);
1283 const auto &unpack = context->getGLState().getUnpackState();
1284
1285 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1286 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1287 if (endByteOrErr.isError())
1288 {
1289 context->handleError(endByteOrErr.getError());
1290 return false;
1291 }
1292
1293 GLuint endByte = endByteOrErr.getResult();
1294
1295 if (pixelUnpackBuffer)
1296 {
1297 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1298 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1299 checkedEndByte += checkedOffset;
1300
1301 if (!checkedEndByte.IsValid() ||
1302 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1303 {
1304 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001305 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04001306 return false;
1307 }
1308 }
1309 else
1310 {
1311 ASSERT(imageSize >= 0);
1312 if (pixels == nullptr && imageSize != 0)
1313 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001314 context->handleError(InvalidOperation()
1315 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001316 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001317 }
1318
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001319 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001320 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001321 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001322 return false;
1323 }
1324 }
1325
1326 return true;
1327}
1328
Geoff Lang37dde692014-01-31 16:34:54 -05001329bool ValidQueryType(const Context *context, GLenum queryType)
1330{
He Yunchaoced53ae2016-11-29 15:00:51 +08001331 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1332 "GL extension enums not equal.");
1333 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1334 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001335
1336 switch (queryType)
1337 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001338 case GL_ANY_SAMPLES_PASSED:
1339 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1340 return true;
1341 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1342 return (context->getClientMajorVersion() >= 3);
1343 case GL_TIME_ELAPSED_EXT:
1344 return context->getExtensions().disjointTimerQuery;
1345 case GL_COMMANDS_COMPLETED_CHROMIUM:
1346 return context->getExtensions().syncQuery;
1347 default:
1348 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001349 }
1350}
1351
Geoff Lang2d62ab72017-03-23 16:54:40 -04001352bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
1353 GLenum type,
1354 GLboolean normalized,
1355 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001356 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001357 bool pureInteger)
1358{
1359 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001360 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1361 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1362 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1363 // parameter exceeds 255.
1364 constexpr GLsizei kMaxWebGLStride = 255;
1365 if (stride > kMaxWebGLStride)
1366 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001367 context->handleError(InvalidValue()
1368 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001369 return false;
1370 }
1371
1372 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1373 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1374 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1375 // or an INVALID_OPERATION error is generated.
1376 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1377 size_t typeSize = GetVertexFormatTypeSize(internalType);
1378
1379 ASSERT(isPow2(typeSize) && typeSize > 0);
1380 size_t sizeMask = (typeSize - 1);
1381 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1382 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001383 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001384 return false;
1385 }
1386
1387 if ((stride & sizeMask) != 0)
1388 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001389 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001390 return false;
1391 }
1392
1393 return true;
1394}
1395
Jamie Madillef300b12016-10-07 15:12:09 -04001396Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001397{
He Yunchaoced53ae2016-11-29 15:00:51 +08001398 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1399 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1400 // or program object and INVALID_OPERATION if the provided name identifies an object
1401 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001402
Dian Xiang769769a2015-09-09 15:20:08 -07001403 Program *validProgram = context->getProgram(id);
1404
1405 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001406 {
Dian Xiang769769a2015-09-09 15:20:08 -07001407 if (context->getShader(id))
1408 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001409 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001410 }
1411 else
1412 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001413 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001414 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001415 }
Dian Xiang769769a2015-09-09 15:20:08 -07001416
1417 return validProgram;
1418}
1419
Jamie Madillef300b12016-10-07 15:12:09 -04001420Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001421{
1422 // See ValidProgram for spec details.
1423
1424 Shader *validShader = context->getShader(id);
1425
1426 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001427 {
Dian Xiang769769a2015-09-09 15:20:08 -07001428 if (context->getProgram(id))
1429 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001430 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001431 }
1432 else
1433 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001434 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001435 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001436 }
Dian Xiang769769a2015-09-09 15:20:08 -07001437
1438 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001439}
1440
Geoff Langb1196682014-07-23 13:47:29 -04001441bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001442{
1443 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1444 {
1445 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1446
Geoff Langaae65a42014-05-26 12:43:44 -04001447 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001448 {
Martin Radevd178aa42017-07-13 14:03:22 +03001449 context->handleError(
1450 InvalidOperation()
1451 << "attachment index cannot be greater or equal to MAX_COLOR_ATTACHMENTS.");
Geoff Langb1196682014-07-23 13:47:29 -04001452 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001453 }
1454 }
1455 else
1456 {
1457 switch (attachment)
1458 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001459 case GL_DEPTH_ATTACHMENT:
1460 case GL_STENCIL_ATTACHMENT:
1461 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001462
He Yunchaoced53ae2016-11-29 15:00:51 +08001463 case GL_DEPTH_STENCIL_ATTACHMENT:
1464 if (!context->getExtensions().webglCompatibility &&
1465 context->getClientMajorVersion() < 3)
1466 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001467 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001468 return false;
1469 }
1470 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001471
He Yunchaoced53ae2016-11-29 15:00:51 +08001472 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001473 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001474 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001475 }
1476 }
1477
1478 return true;
1479}
1480
Jamie Madille8fb6402017-02-14 17:56:40 -05001481bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001482 GLenum target,
1483 GLsizei samples,
1484 GLenum internalformat,
1485 GLsizei width,
1486 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001487{
1488 switch (target)
1489 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001490 case GL_RENDERBUFFER:
1491 break;
1492 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001493 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001494 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001495 }
1496
1497 if (width < 0 || height < 0 || samples < 0)
1498 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001499 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001500 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001501 }
1502
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001503 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1504 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1505
1506 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001507 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001508 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001509 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001510 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001511 }
1512
1513 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1514 // 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 -08001515 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001516 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1517 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001518 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001519 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001520 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001521 }
1522
Geoff Langaae65a42014-05-26 12:43:44 -04001523 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001524 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001525 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001526 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001527 }
1528
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001529 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001530 if (handle == 0)
1531 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001532 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001533 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001534 }
1535
1536 return true;
1537}
1538
He Yunchaoced53ae2016-11-29 15:00:51 +08001539bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1540 GLenum target,
1541 GLenum attachment,
1542 GLenum renderbuffertarget,
1543 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001544{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001545 if (!ValidFramebufferTarget(target))
1546 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001547 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001548 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001549 }
1550
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001551 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001552
Jamie Madill84115c92015-04-23 15:00:07 -04001553 ASSERT(framebuffer);
1554 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001555 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001556 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001557 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001558 }
1559
Jamie Madillb4472272014-07-03 10:38:55 -04001560 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001561 {
Jamie Madillb4472272014-07-03 10:38:55 -04001562 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001563 }
1564
Jamie Madillab9d82c2014-01-21 16:38:14 -05001565 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1566 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1567 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1568 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1569 if (renderbuffer != 0)
1570 {
1571 if (!context->getRenderbuffer(renderbuffer))
1572 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001573 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001574 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001575 }
1576 }
1577
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001578 return true;
1579}
1580
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001581bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001582 GLint srcX0,
1583 GLint srcY0,
1584 GLint srcX1,
1585 GLint srcY1,
1586 GLint dstX0,
1587 GLint dstY0,
1588 GLint dstX1,
1589 GLint dstY1,
1590 GLbitfield mask,
1591 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001592{
1593 switch (filter)
1594 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001595 case GL_NEAREST:
1596 break;
1597 case GL_LINEAR:
1598 break;
1599 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001600 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001601 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001602 }
1603
1604 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1605 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001606 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001607 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001608 }
1609
1610 if (mask == 0)
1611 {
1612 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1613 // buffers are copied.
1614 return false;
1615 }
1616
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001617 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1618 // color buffer, leaving only nearest being unfiltered from above
1619 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1620 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001621 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001622 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001623 }
1624
Jamie Madill51f40ec2016-06-15 14:06:00 -04001625 const auto &glState = context->getGLState();
1626 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1627 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001628
1629 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001630 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001631 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001632 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001633 }
1634
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001635 if (readFramebuffer->id() == drawFramebuffer->id())
1636 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001637 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001638 return false;
1639 }
1640
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001641 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001642 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001643 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001644 return false;
1645 }
1646
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001647 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001648 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001649 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001650 return false;
1651 }
1652
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001653 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001654 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001655 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001656 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001657 }
1658
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001659 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1660
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001661 if (mask & GL_COLOR_BUFFER_BIT)
1662 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001663 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001664 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001665
He Yunchao66a41a22016-12-15 16:45:05 +08001666 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001667 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001668 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001669
Geoff Langa15472a2015-08-11 11:48:03 -04001670 for (size_t drawbufferIdx = 0;
1671 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001672 {
Geoff Langa15472a2015-08-11 11:48:03 -04001673 const FramebufferAttachment *attachment =
1674 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1675 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001676 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001677 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001678
Geoff Langb2f3d052013-08-13 12:49:27 -04001679 // The GL ES 3.0.2 spec (pg 193) states that:
1680 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001681 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1682 // as well
1683 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1684 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001685 // Changes with EXT_color_buffer_float:
1686 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001687 GLenum readComponentType = readFormat.info->componentType;
1688 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001689 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001690 readComponentType == GL_SIGNED_NORMALIZED);
1691 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1692 drawComponentType == GL_SIGNED_NORMALIZED);
1693
1694 if (extensions.colorBufferFloat)
1695 {
1696 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1697 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1698
1699 if (readFixedOrFloat != drawFixedOrFloat)
1700 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001701 context->handleError(InvalidOperation()
1702 << "If the read buffer contains fixed-point or "
1703 "floating-point values, the draw buffer must "
1704 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001705 return false;
1706 }
1707 }
1708 else if (readFixedPoint != drawFixedPoint)
1709 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001710 context->handleError(InvalidOperation()
1711 << "If the read buffer contains fixed-point values, "
1712 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001713 return false;
1714 }
1715
1716 if (readComponentType == GL_UNSIGNED_INT &&
1717 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001719 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001720 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001721 }
1722
Jamie Madill6163c752015-12-07 16:32:59 -05001723 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001724 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001725 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001726 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001727 }
1728
Jamie Madilla3944d42016-07-22 22:13:26 -04001729 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001730 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001731 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001732 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001733 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001734 }
Geoff Lange4915782017-04-12 15:19:07 -04001735
1736 if (context->getExtensions().webglCompatibility &&
1737 *readColorBuffer == *attachment)
1738 {
1739 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001740 InvalidOperation()
1741 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001742 return false;
1743 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001744 }
1745 }
1746
Jamie Madilla3944d42016-07-22 22:13:26 -04001747 if ((readFormat.info->componentType == GL_INT ||
1748 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1749 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001750 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001751 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001752 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001753 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001754 }
He Yunchao66a41a22016-12-15 16:45:05 +08001755 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1756 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1757 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1758 // situation is an application error that would lead to a crash in ANGLE.
1759 else if (drawFramebuffer->hasEnabledDrawBuffer())
1760 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001761 context->handleError(
1762 InvalidOperation()
1763 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001764 return false;
1765 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001766 }
1767
He Yunchaoced53ae2016-11-29 15:00:51 +08001768 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001769 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1770 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001771 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001772 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001773 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001774 const gl::FramebufferAttachment *readBuffer =
1775 readFramebuffer->getAttachment(attachments[i]);
1776 const gl::FramebufferAttachment *drawBuffer =
1777 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001778
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001779 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001780 {
Kenneth Russell69382852017-07-21 16:38:44 -04001781 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001782 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001783 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001784 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001785 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001786
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001787 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001788 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001789 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001790 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001791 }
Geoff Lange4915782017-04-12 15:19:07 -04001792
1793 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1794 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001795 context->handleError(
1796 InvalidOperation()
1797 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001798 return false;
1799 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001800 }
He Yunchao66a41a22016-12-15 16:45:05 +08001801 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1802 else if (drawBuffer)
1803 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001804 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1805 "depth/stencil attachment of a "
1806 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001807 return false;
1808 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001809 }
1810 }
1811
Martin Radeva3ed4572017-07-27 18:29:37 +03001812 // ANGLE_multiview, Revision 1:
1813 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1814 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1815 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1816 {
1817 context->handleError(InvalidFramebufferOperation()
1818 << "Attempt to read from a multi-view framebuffer.");
1819 return false;
1820 }
1821 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1822 {
1823 context->handleError(InvalidFramebufferOperation()
1824 << "Attempt to write to a multi-view framebuffer.");
1825 return false;
1826 }
1827
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001828 return true;
1829}
1830
Jamie Madill4928b7c2017-06-20 12:57:39 -04001831bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001832 GLint x,
1833 GLint y,
1834 GLsizei width,
1835 GLsizei height,
1836 GLenum format,
1837 GLenum type,
1838 GLsizei bufSize,
1839 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001840 GLsizei *columns,
1841 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001842 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001843{
1844 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001845 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001846 return false;
1847 }
1848
Geoff Lang62fce5b2016-09-30 10:46:35 -04001849 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001850 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001851 {
Geoff Langb1196682014-07-23 13:47:29 -04001852 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001853 }
1854
Geoff Lang62fce5b2016-09-30 10:46:35 -04001855 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001856 {
Geoff Langb1196682014-07-23 13:47:29 -04001857 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001858 }
1859
Jamie Madillc29968b2016-01-20 11:17:23 -05001860 return true;
1861}
1862
1863bool ValidateReadnPixelsEXT(Context *context,
1864 GLint x,
1865 GLint y,
1866 GLsizei width,
1867 GLsizei height,
1868 GLenum format,
1869 GLenum type,
1870 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001871 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001872{
1873 if (bufSize < 0)
1874 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001875 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001876 return false;
1877 }
1878
Geoff Lang62fce5b2016-09-30 10:46:35 -04001879 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001880 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001881}
Jamie Madill26e91952014-03-05 15:01:27 -05001882
Jamie Madill4928b7c2017-06-20 12:57:39 -04001883bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001884 GLint x,
1885 GLint y,
1886 GLsizei width,
1887 GLsizei height,
1888 GLenum format,
1889 GLenum type,
1890 GLsizei bufSize,
1891 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001892 GLsizei *columns,
1893 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001894 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001895{
1896 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001897 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001898 return false;
1899 }
1900
Geoff Lange93daba2017-03-30 13:54:40 -04001901 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1902 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001903 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001904 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001905 }
1906
Geoff Lang62fce5b2016-09-30 10:46:35 -04001907 if (!ValidateRobustBufferSize(context, bufSize, *length))
1908 {
1909 return false;
1910 }
1911
1912 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001913}
1914
Olli Etuaho41997e72016-03-10 13:38:39 +02001915bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001916{
1917 if (!context->getExtensions().occlusionQueryBoolean &&
1918 !context->getExtensions().disjointTimerQuery)
1919 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001920 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001921 return false;
1922 }
1923
Olli Etuaho41997e72016-03-10 13:38:39 +02001924 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001925}
1926
Olli Etuaho41997e72016-03-10 13:38:39 +02001927bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001928{
1929 if (!context->getExtensions().occlusionQueryBoolean &&
1930 !context->getExtensions().disjointTimerQuery)
1931 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001932 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001933 return false;
1934 }
1935
Olli Etuaho41997e72016-03-10 13:38:39 +02001936 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001937}
1938
1939bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001940{
1941 if (!ValidQueryType(context, target))
1942 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001943 context->handleError(InvalidEnum() << "Invalid query target");
Geoff Langb1196682014-07-23 13:47:29 -04001944 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001945 }
1946
1947 if (id == 0)
1948 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001949 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001950 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001951 }
1952
1953 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1954 // of zero, if the active query object name for <target> is non-zero (for the
1955 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1956 // the active query for either target is non-zero), if <id> is the name of an
1957 // existing query object whose type does not match <target>, or if <id> is the
1958 // active query object name for any query type, the error INVALID_OPERATION is
1959 // generated.
1960
1961 // Ensure no other queries are active
1962 // NOTE: If other queries than occlusion are supported, we will need to check
1963 // separately that:
1964 // a) The query ID passed is not the current active query for any target/type
1965 // b) There are no active queries for the requested target (and in the case
1966 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1967 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001968
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001969 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001970 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001971 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001972 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001973 }
1974
1975 Query *queryObject = context->getQuery(id, true, target);
1976
1977 // check that name was obtained with glGenQueries
1978 if (!queryObject)
1979 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001980 context->handleError(InvalidOperation() << "Invalid query id");
Geoff Langb1196682014-07-23 13:47:29 -04001981 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001982 }
1983
1984 // check for type mismatch
1985 if (queryObject->getType() != target)
1986 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001987 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001988 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001989 }
1990
1991 return true;
1992}
1993
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001994bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1995{
1996 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001997 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001998 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001999 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002000 return false;
2001 }
2002
2003 return ValidateBeginQueryBase(context, target, id);
2004}
2005
2006bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002007{
2008 if (!ValidQueryType(context, target))
2009 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002010 context->handleError(InvalidEnum() << "Invalid query target");
Geoff Langb1196682014-07-23 13:47:29 -04002011 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002012 }
2013
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002014 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002015
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002016 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002017 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002018 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04002019 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002020 }
2021
Jamie Madill45c785d2014-05-13 14:09:34 -04002022 return true;
2023}
2024
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002025bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2026{
2027 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002028 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002029 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002030 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002031 return false;
2032 }
2033
2034 return ValidateEndQueryBase(context, target);
2035}
2036
2037bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2038{
2039 if (!context->getExtensions().disjointTimerQuery)
2040 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002041 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002042 return false;
2043 }
2044
2045 if (target != GL_TIMESTAMP_EXT)
2046 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002047 context->handleError(InvalidEnum() << "Invalid query target");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002048 return false;
2049 }
2050
2051 Query *queryObject = context->getQuery(id, true, target);
2052 if (queryObject == nullptr)
2053 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002054 context->handleError(InvalidOperation() << "Invalid query id");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002055 return false;
2056 }
2057
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002058 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002059 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002060 context->handleError(InvalidOperation() << "Query is active");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002061 return false;
2062 }
2063
2064 return true;
2065}
2066
Geoff Lang2186c382016-10-14 10:54:54 -04002067bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002068{
Geoff Lang2186c382016-10-14 10:54:54 -04002069 if (numParams)
2070 {
2071 *numParams = 0;
2072 }
2073
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002074 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2075 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002076 context->handleError(InvalidEnum() << "Invalid query type");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002077 return false;
2078 }
2079
2080 switch (pname)
2081 {
2082 case GL_CURRENT_QUERY_EXT:
2083 if (target == GL_TIMESTAMP_EXT)
2084 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002085 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002086 return false;
2087 }
2088 break;
2089 case GL_QUERY_COUNTER_BITS_EXT:
2090 if (!context->getExtensions().disjointTimerQuery ||
2091 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2092 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002093 context->handleError(InvalidEnum() << "Invalid pname");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002094 return false;
2095 }
2096 break;
2097 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002098 context->handleError(InvalidEnum() << "Invalid pname");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002099 return false;
2100 }
2101
Geoff Lang2186c382016-10-14 10:54:54 -04002102 if (numParams)
2103 {
2104 // All queries return only one value
2105 *numParams = 1;
2106 }
2107
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002108 return true;
2109}
2110
2111bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2112{
2113 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002114 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002115 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002116 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002117 return false;
2118 }
2119
Geoff Lang2186c382016-10-14 10:54:54 -04002120 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002121}
2122
Geoff Lang2186c382016-10-14 10:54:54 -04002123bool ValidateGetQueryivRobustANGLE(Context *context,
2124 GLenum target,
2125 GLenum pname,
2126 GLsizei bufSize,
2127 GLsizei *length,
2128 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002129{
Geoff Lang2186c382016-10-14 10:54:54 -04002130 if (!ValidateRobustEntryPoint(context, bufSize))
2131 {
2132 return false;
2133 }
2134
2135 if (!ValidateGetQueryivBase(context, target, pname, length))
2136 {
2137 return false;
2138 }
2139
2140 if (!ValidateRobustBufferSize(context, bufSize, *length))
2141 {
2142 return false;
2143 }
2144
2145 return true;
2146}
2147
2148bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2149{
2150 if (numParams)
2151 {
2152 *numParams = 0;
2153 }
2154
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002155 Query *queryObject = context->getQuery(id, false, GL_NONE);
2156
2157 if (!queryObject)
2158 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002159 context->handleError(InvalidOperation() << "Query does not exist");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002160 return false;
2161 }
2162
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002163 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002164 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002165 context->handleError(InvalidOperation() << "Query currently active");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002166 return false;
2167 }
2168
2169 switch (pname)
2170 {
2171 case GL_QUERY_RESULT_EXT:
2172 case GL_QUERY_RESULT_AVAILABLE_EXT:
2173 break;
2174
2175 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002176 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002177 return false;
2178 }
2179
Geoff Lang2186c382016-10-14 10:54:54 -04002180 if (numParams)
2181 {
2182 *numParams = 1;
2183 }
2184
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002185 return true;
2186}
2187
2188bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2189{
2190 if (!context->getExtensions().disjointTimerQuery)
2191 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002192 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002193 return false;
2194 }
Geoff Lang2186c382016-10-14 10:54:54 -04002195 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2196}
2197
2198bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2199 GLuint id,
2200 GLenum pname,
2201 GLsizei bufSize,
2202 GLsizei *length,
2203 GLint *params)
2204{
2205 if (!context->getExtensions().disjointTimerQuery)
2206 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002207 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04002208 return false;
2209 }
2210
2211 if (!ValidateRobustEntryPoint(context, bufSize))
2212 {
2213 return false;
2214 }
2215
2216 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2217 {
2218 return false;
2219 }
2220
2221 if (!ValidateRobustBufferSize(context, bufSize, *length))
2222 {
2223 return false;
2224 }
2225
2226 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002227}
2228
2229bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2230{
2231 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002232 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002233 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002234 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002235 return false;
2236 }
Geoff Lang2186c382016-10-14 10:54:54 -04002237 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2238}
2239
2240bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2241 GLuint id,
2242 GLenum pname,
2243 GLsizei bufSize,
2244 GLsizei *length,
2245 GLuint *params)
2246{
2247 if (!context->getExtensions().disjointTimerQuery &&
2248 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2249 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002250 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002251 return false;
2252 }
2253
2254 if (!ValidateRobustEntryPoint(context, bufSize))
2255 {
2256 return false;
2257 }
2258
2259 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2260 {
2261 return false;
2262 }
2263
2264 if (!ValidateRobustBufferSize(context, bufSize, *length))
2265 {
2266 return false;
2267 }
2268
2269 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002270}
2271
2272bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2273{
2274 if (!context->getExtensions().disjointTimerQuery)
2275 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002276 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002277 return false;
2278 }
Geoff Lang2186c382016-10-14 10:54:54 -04002279 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2280}
2281
2282bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2283 GLuint id,
2284 GLenum pname,
2285 GLsizei bufSize,
2286 GLsizei *length,
2287 GLint64 *params)
2288{
2289 if (!context->getExtensions().disjointTimerQuery)
2290 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002291 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002292 return false;
2293 }
2294
2295 if (!ValidateRobustEntryPoint(context, bufSize))
2296 {
2297 return false;
2298 }
2299
2300 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2301 {
2302 return false;
2303 }
2304
2305 if (!ValidateRobustBufferSize(context, bufSize, *length))
2306 {
2307 return false;
2308 }
2309
2310 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002311}
2312
2313bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2314{
2315 if (!context->getExtensions().disjointTimerQuery)
2316 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002317 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002318 return false;
2319 }
Geoff Lang2186c382016-10-14 10:54:54 -04002320 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2321}
2322
2323bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2324 GLuint id,
2325 GLenum pname,
2326 GLsizei bufSize,
2327 GLsizei *length,
2328 GLuint64 *params)
2329{
2330 if (!context->getExtensions().disjointTimerQuery)
2331 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002332 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002333 return false;
2334 }
2335
2336 if (!ValidateRobustEntryPoint(context, bufSize))
2337 {
2338 return false;
2339 }
2340
2341 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2342 {
2343 return false;
2344 }
2345
2346 if (!ValidateRobustBufferSize(context, bufSize, *length))
2347 {
2348 return false;
2349 }
2350
2351 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002352}
2353
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002354bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002355 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002356 GLuint program,
2357 GLint location,
2358 GLsizei count)
2359{
2360 // Check for ES31 program uniform entry points
2361 if (context->getClientVersion() < Version(3, 1))
2362 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002363 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002364 return false;
2365 }
2366
2367 const LinkedUniform *uniform = nullptr;
2368 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002369 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2370 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002371}
2372
Frank Henigmana98a6472017-02-02 21:38:32 -05002373bool ValidateProgramUniform1iv(gl::Context *context,
2374 GLuint program,
2375 GLint location,
2376 GLsizei count,
2377 const GLint *value)
2378{
2379 // Check for ES31 program uniform entry points
2380 if (context->getClientVersion() < Version(3, 1))
2381 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002382 context->handleError(InvalidOperation());
Frank Henigmana98a6472017-02-02 21:38:32 -05002383 return false;
2384 }
2385
2386 const LinkedUniform *uniform = nullptr;
2387 gl::Program *programObject = GetValidProgram(context, program);
2388 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2389 ValidateUniform1ivValue(context, uniform->type, count, value);
2390}
2391
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002392bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002393 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002394 GLuint program,
2395 GLint location,
2396 GLsizei count,
2397 GLboolean transpose)
2398{
2399 // Check for ES31 program uniform entry points
2400 if (context->getClientVersion() < Version(3, 1))
2401 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002402 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002403 return false;
2404 }
2405
2406 const LinkedUniform *uniform = nullptr;
2407 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002408 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2409 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002410}
2411
Jamie Madillc1d770e2017-04-13 17:31:24 -04002412bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002413{
2414 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002415 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002416 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002417 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002418 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002419 }
2420
Jamie Madill62d31cb2015-09-11 13:25:51 -04002421 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002422 gl::Program *programObject = context->getGLState().getProgram();
2423 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2424 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002425}
2426
Jamie Madillbe849e42017-05-02 15:49:00 -04002427bool ValidateUniform1iv(ValidationContext *context,
2428 GLint location,
2429 GLsizei count,
2430 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002431{
2432 const LinkedUniform *uniform = nullptr;
2433 gl::Program *programObject = context->getGLState().getProgram();
2434 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2435 ValidateUniform1ivValue(context, uniform->type, count, value);
2436}
2437
Jamie Madillc1d770e2017-04-13 17:31:24 -04002438bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002439 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002440 GLint location,
2441 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002442 GLboolean transpose)
2443{
2444 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002445 int rows = VariableRowCount(valueType);
2446 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002447 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002448 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002449 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002450 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002451 }
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;
2497 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2498 if (!context->getExtensions().eglStreamConsumerExternal &&
2499 !context->getExtensions().eglImageExternal)
2500 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002501 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2502 "nor GL_OES_EGL_image_external "
2503 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002504 return false;
2505 }
2506 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002507
He Yunchaoced53ae2016-11-29 15:00:51 +08002508 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2509 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002510 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002511 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2512 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002514 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002515 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002516 }
2517
Jamie Madill51f40ec2016-06-15 14:06:00 -04002518 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2519 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002520
2521 if (framebuffer->getReadBufferState() == GL_NONE)
2522 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002523 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Martin Radev138064f2016-07-15 12:03:41 +03002524 return false;
2525 }
2526
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002527 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002528 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002529 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002530 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002531 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002532 }
2533 }
2534 break;
2535
He Yunchaoced53ae2016-11-29 15:00:51 +08002536 default:
2537 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002538 }
2539
2540 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002541 if (*numParams == 0)
2542 {
2543 return false;
2544 }
2545
2546 return true;
2547}
2548
2549bool ValidateRobustStateQuery(ValidationContext *context,
2550 GLenum pname,
2551 GLsizei bufSize,
2552 GLenum *nativeType,
2553 unsigned int *numParams)
2554{
2555 if (!ValidateRobustEntryPoint(context, bufSize))
2556 {
2557 return false;
2558 }
2559
2560 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2561 {
2562 return false;
2563 }
2564
2565 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002566 {
2567 return false;
2568 }
2569
2570 return true;
2571}
2572
Jamie Madillc29968b2016-01-20 11:17:23 -05002573bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2574 GLenum target,
2575 GLint level,
2576 GLenum internalformat,
2577 bool isSubImage,
2578 GLint xoffset,
2579 GLint yoffset,
2580 GLint zoffset,
2581 GLint x,
2582 GLint y,
2583 GLsizei width,
2584 GLsizei height,
2585 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002586 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002587{
Brandon Jones6cad5662017-06-14 13:25:13 -07002588 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002589 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002590 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2591 return false;
2592 }
2593
2594 if (width < 0 || height < 0)
2595 {
2596 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002597 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002598 }
2599
He Yunchaoced53ae2016-11-29 15:00:51 +08002600 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2601 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002602 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002603 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002604 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002605 }
2606
2607 if (border != 0)
2608 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002609 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002610 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002611 }
2612
2613 if (!ValidMipLevel(context, target, level))
2614 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002615 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002616 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002617 }
2618
Jamie Madill51f40ec2016-06-15 14:06:00 -04002619 const auto &state = context->getGLState();
2620 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002621 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002622 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002623 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002624 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002625 }
2626
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002627 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002628 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002629 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002630 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002631 }
2632
Martin Radev138064f2016-07-15 12:03:41 +03002633 if (readFramebuffer->getReadBufferState() == GL_NONE)
2634 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002635 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Martin Radev138064f2016-07-15 12:03:41 +03002636 return false;
2637 }
2638
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002639 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2640 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002641 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002642 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002643 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2644 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002645 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002646 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002647 return false;
2648 }
2649
Martin Radev04e2c3b2017-07-27 16:54:35 +03002650 // ANGLE_multiview spec, Revision 1:
2651 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2652 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2653 // is not NONE.
2654 if (source->getMultiviewLayout() != GL_NONE)
2655 {
2656 context->handleError(InvalidFramebufferOperation()
2657 << "The active read framebuffer object has multiview attachments.");
2658 return false;
2659 }
2660
Geoff Langaae65a42014-05-26 12:43:44 -04002661 const gl::Caps &caps = context->getCaps();
2662
Geoff Langaae65a42014-05-26 12:43:44 -04002663 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002664 switch (target)
2665 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002666 case GL_TEXTURE_2D:
2667 maxDimension = caps.max2DTextureSize;
2668 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002669
He Yunchaoced53ae2016-11-29 15:00:51 +08002670 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2671 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2672 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2673 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2674 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2675 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2676 maxDimension = caps.maxCubeMapTextureSize;
2677 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002678
He Yunchaoced53ae2016-11-29 15:00:51 +08002679 case GL_TEXTURE_2D_ARRAY:
2680 maxDimension = caps.max2DTextureSize;
2681 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002682
He Yunchaoced53ae2016-11-29 15:00:51 +08002683 case GL_TEXTURE_3D:
2684 maxDimension = caps.max3DTextureSize;
2685 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002686
He Yunchaoced53ae2016-11-29 15:00:51 +08002687 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002688 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002689 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002690 }
2691
Jamie Madillc29968b2016-01-20 11:17:23 -05002692 gl::Texture *texture =
2693 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002694 if (!texture)
2695 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002696 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002697 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002698 }
2699
Geoff Lang69cce582015-09-17 13:20:36 -04002700 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002701 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002702 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002703 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002704 }
2705
Geoff Langca271392017-04-05 12:30:00 -04002706 const gl::InternalFormat &formatInfo =
2707 gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002708
Geoff Lang966c9402017-04-18 12:38:27 -04002709 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002710 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002711 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002712 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002713 }
2714
2715 if (isSubImage)
2716 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002717 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2718 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2719 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002720 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002721 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002722 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002723 }
2724 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002725 else
2726 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002727 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002728 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002729 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002730 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002731 }
2732
Geoff Langeb66a6e2016-10-31 13:06:12 -04002733 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002734 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002735 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002736 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002737 }
2738
2739 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002740 if (static_cast<int>(width) > maxLevelDimension ||
2741 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002742 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002743 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002744 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002745 }
2746 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002747
Jamie Madill0c8abca2016-07-22 20:21:26 -04002748 if (textureFormatOut)
2749 {
2750 *textureFormatOut = texture->getFormat(target, level);
2751 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002752
2753 // Detect texture copying feedback loops for WebGL.
2754 if (context->getExtensions().webglCompatibility)
2755 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002756 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002757 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002758 context->handleError(InvalidOperation() << "Texture copying feedback loop formed "
2759 "between Framebuffer and specified "
2760 "Texture level.");
Jamie Madillf695a3a2017-01-11 17:36:35 -05002761 return false;
2762 }
2763 }
2764
Jamie Madill560a8d82014-05-21 13:06:20 -04002765 return true;
2766}
2767
Jiajia Qind9671222016-11-29 16:30:31 +08002768bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002769{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002770 switch (mode)
2771 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002772 case GL_POINTS:
2773 case GL_LINES:
2774 case GL_LINE_LOOP:
2775 case GL_LINE_STRIP:
2776 case GL_TRIANGLES:
2777 case GL_TRIANGLE_STRIP:
2778 case GL_TRIANGLE_FAN:
2779 break;
2780 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002781 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002782 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002783 }
2784
Jamie Madill250d33f2014-06-06 17:09:03 -04002785 if (count < 0)
2786 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002787 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002788 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002789 }
2790
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002791 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002792
Jamie Madill250d33f2014-06-06 17:09:03 -04002793 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002794 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002795 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002796 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002797 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002798 }
2799
Jamie Madillcbcde722017-01-06 14:50:00 -05002800 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2801 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002802 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002803 const Extensions &extensions = context->getExtensions();
2804 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002805 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002806 const FramebufferAttachment *dsAttachment =
2807 framebuffer->getStencilOrDepthStencilAttachment();
2808 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002809 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002810 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002811
2812 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2813 bool differentWritemasks =
2814 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2815 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2816 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2817 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2818
2819 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002820 {
Martin Radevffe754b2017-07-31 10:38:07 +03002821 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002822 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002823 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2824 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002825 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002826 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002827 return false;
2828 }
Jamie Madillac528012014-06-20 13:21:23 -04002829 }
2830
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002831 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002832 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002833 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002834 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002835 }
2836
Geoff Lang7dd2e102014-11-10 15:19:26 -05002837 gl::Program *program = state.getProgram();
2838 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002839 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002840 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002841 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002842 }
2843
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002844 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002845 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002846 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002847 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002848 }
2849
Martin Radevffe754b2017-07-31 10:38:07 +03002850 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002851 {
Martin Radev7e69f762017-07-27 14:54:13 +03002852 const int programNumViews = program->getNumViews();
2853 const int framebufferNumViews = framebuffer->getNumViews();
2854 if (programNumViews != -1 && framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002855 {
2856 context->handleError(InvalidOperation() << "The number of views in the active program "
2857 "and draw framebuffer does not match.");
2858 return false;
2859 }
Martin Radev7e69f762017-07-27 14:54:13 +03002860
2861 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2862 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2863 framebufferNumViews > 1)
2864 {
2865 context->handleError(InvalidOperation()
2866 << "There is an active transform feedback object "
2867 "when the number of views in the active draw "
2868 "framebuffer is greater than 1.");
2869 return false;
2870 }
Martin Radevffe754b2017-07-31 10:38:07 +03002871
2872 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2873 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2874 {
2875 context->handleError(InvalidOperation() << "There is an active query for target "
2876 "GL_TIME_ELAPSED_EXT when the number of "
2877 "views in the active draw framebuffer is "
2878 "greater than 1.");
2879 return false;
2880 }
Martin Radev7cf61662017-07-26 17:10:53 +03002881 }
2882
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002883 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002884 for (unsigned int uniformBlockIndex = 0;
2885 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002886 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002887 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002888 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002889 const OffsetBindingPointer<Buffer> &uniformBuffer =
2890 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002891
Geoff Lang5d124a62015-09-15 13:03:27 -04002892 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002893 {
2894 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002895 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002896 InvalidOperation()
2897 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002898 return false;
2899 }
2900
Geoff Lang5d124a62015-09-15 13:03:27 -04002901 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002902 if (uniformBufferSize == 0)
2903 {
2904 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002905 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002906 }
2907
Jamie Madill62d31cb2015-09-11 13:25:51 -04002908 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002909 {
2910 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002911 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002912 InvalidOperation()
2913 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002914 return false;
2915 }
2916 }
2917
Geoff Lange0cff192017-05-30 13:04:56 -04002918 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002919 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002920 {
Geoff Lange0cff192017-05-30 13:04:56 -04002921 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002922 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2923 {
2924 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002925 InvalidOperation()
2926 << "Rendering feedback loop formed between Framebuffer and active Texture.");
Jamie Madilla4595b82017-01-11 17:36:34 -05002927 return false;
2928 }
Geoff Lange0cff192017-05-30 13:04:56 -04002929
Geoff Lang9ab5b822017-05-30 16:19:23 -04002930 // Detect that the vertex shader input types match the attribute types
2931 if (!ValidateVertexShaderAttributeTypeMatch(context))
2932 {
2933 return false;
2934 }
2935
Geoff Lange0cff192017-05-30 13:04:56 -04002936 // Detect that the color buffer types match the fragment shader output types
2937 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2938 {
2939 return false;
2940 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002941 }
2942
Jamie Madill250d33f2014-06-06 17:09:03 -04002943 // No-op if zero count
2944 return (count > 0);
2945}
2946
Jamie Madillc1d770e2017-04-13 17:31:24 -04002947bool ValidateDrawArraysCommon(ValidationContext *context,
2948 GLenum mode,
2949 GLint first,
2950 GLsizei count,
2951 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002952{
Jamie Madillfd716582014-06-06 17:09:04 -04002953 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002954 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002955 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002956 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002957 }
2958
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002959 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002960 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002961 if (curTransformFeedback && curTransformFeedback->isActive() &&
2962 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002963 {
2964 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002965 // that does not match the current transform feedback object's draw mode (if transform
2966 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002967 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002968 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002969 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002970 }
2971
Jiajia Qind9671222016-11-29 16:30:31 +08002972 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002973 {
2974 return false;
2975 }
2976
Corentin Wallez71168a02016-12-19 15:11:18 -08002977 // Check the computation of maxVertex doesn't overflow.
2978 // - first < 0 or count < 0 have been checked as an error condition
2979 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2980 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2981 ASSERT(count > 0 && first >= 0);
2982 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2983 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002984 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002985 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002986 return false;
2987 }
2988
Corentin Wallez71168a02016-12-19 15:11:18 -08002989 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002990 {
2991 return false;
2992 }
2993
2994 return true;
2995}
2996
He Yunchaoced53ae2016-11-29 15:00:51 +08002997bool ValidateDrawArraysInstanced(Context *context,
2998 GLenum mode,
2999 GLint first,
3000 GLsizei count,
3001 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003002{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003003 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
Geoff Lang87a93302014-09-16 13:29:43 -04003004}
3005
He Yunchaoced53ae2016-11-29 15:00:51 +08003006bool ValidateDrawArraysInstancedANGLE(Context *context,
3007 GLenum mode,
3008 GLint first,
3009 GLsizei count,
3010 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003011{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003012 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003013 {
3014 return false;
3015 }
3016
Corentin Wallez0dc97812017-06-22 14:38:44 -04003017 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003018}
3019
Jiajia Qind9671222016-11-29 16:30:31 +08003020bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003021{
Jamie Madill250d33f2014-06-06 17:09:03 -04003022 switch (type)
3023 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003024 case GL_UNSIGNED_BYTE:
3025 case GL_UNSIGNED_SHORT:
3026 break;
3027 case GL_UNSIGNED_INT:
3028 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3029 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003030 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08003031 return false;
3032 }
3033 break;
3034 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003035 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08003036 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003037 }
3038
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003039 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003040
3041 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003042 if (curTransformFeedback && curTransformFeedback->isActive() &&
3043 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003044 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003045 // It is an invalid operation to call DrawElements, DrawRangeElements or
3046 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003047 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003048 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003049 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003050 }
3051
Jiajia Qind9671222016-11-29 16:30:31 +08003052 return true;
3053}
3054
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003055bool ValidateDrawElementsCommon(ValidationContext *context,
3056 GLenum mode,
3057 GLsizei count,
3058 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003059 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003060 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08003061{
3062 if (!ValidateDrawElementsBase(context, type))
3063 return false;
3064
3065 const State &state = context->getGLState();
3066
Corentin Wallez170efbf2017-05-02 13:45:01 -04003067 if (!ValidateDrawBase(context, mode, count))
3068 {
3069 return false;
3070 }
3071
Jamie Madill250d33f2014-06-06 17:09:03 -04003072 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003073 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003074 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003075 context->handleError(InvalidOperation() << "Index buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -04003076 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003077 }
3078
He Yunchaoced53ae2016-11-29 15:00:51 +08003079 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003080 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003081
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003082 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3083
3084 if (context->getExtensions().webglCompatibility)
3085 {
3086 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3087 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3088 {
3089 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3090 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3091 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003092 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003093 return false;
3094 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003095
3096 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3097 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3098 // error is generated.
3099 if (reinterpret_cast<intptr_t>(indices) < 0)
3100 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003101 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003102 return false;
3103 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003104 }
3105
3106 if (context->getExtensions().webglCompatibility ||
3107 !context->getGLState().areClientArraysEnabled())
3108 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003109 if (!elementArrayBuffer && count > 0)
3110 {
3111 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3112 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3113 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003114 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003115 return false;
3116 }
3117 }
3118
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003119 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003120 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003121 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003122 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003123 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3124 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3125 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3126 constexpr uint64_t kMaxTypeSize = 8;
3127 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3128 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3129 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003130
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003131 uint64_t typeSize = typeBytes;
3132 uint64_t elementCount = static_cast<uint64_t>(count);
3133 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3134
3135 // Doing the multiplication here is overflow-safe
3136 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3137
3138 // The offset can be any value, check for overflows
3139 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3140 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003141 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003142 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003143 return false;
3144 }
3145
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003146 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3147 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003148 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003149 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003150 return false;
3151 }
3152 }
3153 else if (!indices)
3154 {
3155 // This is an application error that would normally result in a crash,
3156 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003157 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04003158 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003159 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003160 }
3161
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003162 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill2b976812014-08-25 15:47:49 -04003163 // TODO: offer fast path, with disabled index validation.
3164 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003165 const auto &params = context->getParams<HasIndexRange>();
3166 const auto &indexRangeOpt = params.getIndexRange();
3167 if (!indexRangeOpt.valid())
Jamie Madill2b976812014-08-25 15:47:49 -04003168 {
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003169 // Unexpected error.
3170 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003171 }
3172
Jamie Madille79b1e12015-11-04 16:36:37 -05003173 // If we use an index greater than our maximum supported index range, return an error.
3174 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3175 // return an error if possible here.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003176 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
Jamie Madille79b1e12015-11-04 16:36:37 -05003177 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003178 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
Jamie Madille79b1e12015-11-04 16:36:37 -05003179 return false;
3180 }
3181
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003182 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
3183 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003184 {
3185 return false;
3186 }
3187
Geoff Lang3edfe032015-09-04 16:38:24 -04003188 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003189 return (indexRangeOpt.value().vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003190}
3191
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003192bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
3193 GLenum mode,
3194 GLsizei count,
3195 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003196 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003197 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003198{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003199 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003200}
3201
Geoff Lang3edfe032015-09-04 16:38:24 -04003202bool ValidateDrawElementsInstancedANGLE(Context *context,
3203 GLenum mode,
3204 GLsizei count,
3205 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003206 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003207 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003208{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003209 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003210 {
3211 return false;
3212 }
3213
Corentin Wallez0dc97812017-06-22 14:38:44 -04003214 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003215}
3216
He Yunchaoced53ae2016-11-29 15:00:51 +08003217bool ValidateFramebufferTextureBase(Context *context,
3218 GLenum target,
3219 GLenum attachment,
3220 GLuint texture,
3221 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003222{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003223 if (!ValidFramebufferTarget(target))
3224 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003225 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003226 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003227 }
3228
3229 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003230 {
3231 return false;
3232 }
3233
Jamie Madill55ec3b12014-07-03 10:38:57 -04003234 if (texture != 0)
3235 {
3236 gl::Texture *tex = context->getTexture(texture);
3237
Jamie Madillbe849e42017-05-02 15:49:00 -04003238 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003239 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003240 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003241 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003242 }
3243
3244 if (level < 0)
3245 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003246 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003247 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003248 }
3249 }
3250
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003251 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003252 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003253
Jamie Madill84115c92015-04-23 15:00:07 -04003254 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003255 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003256 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003257 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003258 }
3259
3260 return true;
3261}
3262
Geoff Langb1196682014-07-23 13:47:29 -04003263bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003264{
3265 if (program == 0)
3266 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003267 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003268 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003269 }
3270
Dian Xiang769769a2015-09-09 15:20:08 -07003271 gl::Program *programObject = GetValidProgram(context, program);
3272 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003273 {
3274 return false;
3275 }
3276
Jamie Madill0063c512014-08-25 15:47:53 -04003277 if (!programObject || !programObject->isLinked())
3278 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003279 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003280 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003281 }
3282
Geoff Lang7dd2e102014-11-10 15:19:26 -05003283 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003284 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003285 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003286 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003287 }
3288
Jamie Madill0063c512014-08-25 15:47:53 -04003289 return true;
3290}
3291
Geoff Langf41d0ee2016-10-07 13:04:23 -04003292static bool ValidateSizedGetUniform(Context *context,
3293 GLuint program,
3294 GLint location,
3295 GLsizei bufSize,
3296 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003297{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003298 if (length)
3299 {
3300 *length = 0;
3301 }
3302
Jamie Madill78f41802014-08-25 15:47:55 -04003303 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003304 {
Jamie Madill78f41802014-08-25 15:47:55 -04003305 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003306 }
3307
Geoff Langf41d0ee2016-10-07 13:04:23 -04003308 if (bufSize < 0)
3309 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003310 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003311 return false;
3312 }
3313
Jamie Madilla502c742014-08-28 17:19:13 -04003314 gl::Program *programObject = context->getProgram(program);
3315 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003316
Jamie Madill78f41802014-08-25 15:47:55 -04003317 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003318 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003319 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003320 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003321 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003322 context->handleError(InvalidOperation()
3323 << "bufSize of at least " << requiredBytes << " is required.");
Geoff Langb1196682014-07-23 13:47:29 -04003324 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003325 }
3326
Geoff Langf41d0ee2016-10-07 13:04:23 -04003327 if (length)
3328 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003329 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003330 }
3331
Jamie Madill0063c512014-08-25 15:47:53 -04003332 return true;
3333}
3334
He Yunchaoced53ae2016-11-29 15:00:51 +08003335bool ValidateGetnUniformfvEXT(Context *context,
3336 GLuint program,
3337 GLint location,
3338 GLsizei bufSize,
3339 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003340{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003341 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003342}
3343
He Yunchaoced53ae2016-11-29 15:00:51 +08003344bool ValidateGetnUniformivEXT(Context *context,
3345 GLuint program,
3346 GLint location,
3347 GLsizei bufSize,
3348 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003349{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003350 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3351}
3352
3353bool ValidateGetUniformfvRobustANGLE(Context *context,
3354 GLuint program,
3355 GLint location,
3356 GLsizei bufSize,
3357 GLsizei *length,
3358 GLfloat *params)
3359{
3360 if (!ValidateRobustEntryPoint(context, bufSize))
3361 {
3362 return false;
3363 }
3364
3365 // bufSize is validated in ValidateSizedGetUniform
3366 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3367}
3368
3369bool ValidateGetUniformivRobustANGLE(Context *context,
3370 GLuint program,
3371 GLint location,
3372 GLsizei bufSize,
3373 GLsizei *length,
3374 GLint *params)
3375{
3376 if (!ValidateRobustEntryPoint(context, bufSize))
3377 {
3378 return false;
3379 }
3380
3381 // bufSize is validated in ValidateSizedGetUniform
3382 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3383}
3384
3385bool ValidateGetUniformuivRobustANGLE(Context *context,
3386 GLuint program,
3387 GLint location,
3388 GLsizei bufSize,
3389 GLsizei *length,
3390 GLuint *params)
3391{
3392 if (!ValidateRobustEntryPoint(context, bufSize))
3393 {
3394 return false;
3395 }
3396
3397 if (context->getClientMajorVersion() < 3)
3398 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003399 context->handleError(InvalidOperation() << "Entry point requires at least OpenGL ES 3.0.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003400 return false;
3401 }
3402
3403 // bufSize is validated in ValidateSizedGetUniform
3404 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003405}
3406
He Yunchaoced53ae2016-11-29 15:00:51 +08003407bool ValidateDiscardFramebufferBase(Context *context,
3408 GLenum target,
3409 GLsizei numAttachments,
3410 const GLenum *attachments,
3411 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003412{
3413 if (numAttachments < 0)
3414 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003415 context->handleError(InvalidValue() << "numAttachments must not be less than zero");
Austin Kinross08332632015-05-05 13:35:47 -07003416 return false;
3417 }
3418
3419 for (GLsizei i = 0; i < numAttachments; ++i)
3420 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003421 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003422 {
3423 if (defaultFramebuffer)
3424 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003425 context->handleError(InvalidEnum()
3426 << "Invalid attachment when the default framebuffer is bound");
Austin Kinross08332632015-05-05 13:35:47 -07003427 return false;
3428 }
3429
3430 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3431 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003432 context->handleError(InvalidOperation() << "Requested color attachment is "
3433 "greater than the maximum supported "
3434 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003435 return false;
3436 }
3437 }
3438 else
3439 {
3440 switch (attachments[i])
3441 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003442 case GL_DEPTH_ATTACHMENT:
3443 case GL_STENCIL_ATTACHMENT:
3444 case GL_DEPTH_STENCIL_ATTACHMENT:
3445 if (defaultFramebuffer)
3446 {
3447 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003448 InvalidEnum()
3449 << "Invalid attachment when the default framebuffer is bound");
He Yunchaoced53ae2016-11-29 15:00:51 +08003450 return false;
3451 }
3452 break;
3453 case GL_COLOR:
3454 case GL_DEPTH:
3455 case GL_STENCIL:
3456 if (!defaultFramebuffer)
3457 {
3458 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003459 InvalidEnum()
3460 << "Invalid attachment when the default framebuffer is not bound");
He Yunchaoced53ae2016-11-29 15:00:51 +08003461 return false;
3462 }
3463 break;
3464 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003465 context->handleError(InvalidEnum() << "Invalid attachment");
Austin Kinross08332632015-05-05 13:35:47 -07003466 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003467 }
3468 }
3469 }
3470
3471 return true;
3472}
3473
Austin Kinross6ee1e782015-05-29 17:05:37 -07003474bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3475{
3476 // Note that debug marker calls must not set error state
3477
3478 if (length < 0)
3479 {
3480 return false;
3481 }
3482
3483 if (marker == nullptr)
3484 {
3485 return false;
3486 }
3487
3488 return true;
3489}
3490
3491bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3492{
3493 // Note that debug marker calls must not set error state
3494
3495 if (length < 0)
3496 {
3497 return false;
3498 }
3499
3500 if (length > 0 && marker == nullptr)
3501 {
3502 return false;
3503 }
3504
3505 return true;
3506}
3507
Geoff Langdcab33b2015-07-21 13:03:16 -04003508bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003509 GLenum target,
3510 egl::Image *image)
3511{
Geoff Langa8406172015-07-21 16:53:39 -04003512 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003514 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003515 return false;
3516 }
3517
3518 switch (target)
3519 {
3520 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003521 if (!context->getExtensions().eglImage)
3522 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003523 context->handleError(InvalidEnum()
3524 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003525 }
3526 break;
3527
3528 case GL_TEXTURE_EXTERNAL_OES:
3529 if (!context->getExtensions().eglImageExternal)
3530 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003531 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3532 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003533 }
Geoff Langa8406172015-07-21 16:53:39 -04003534 break;
3535
3536 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003537 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003538 return false;
3539 }
3540
Jamie Madill61e16b42017-06-19 11:13:23 -04003541 ASSERT(context->getCurrentDisplay());
3542 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003543 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003544 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003545 return false;
3546 }
3547
3548 if (image->getSamples() > 0)
3549 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003550 context->handleError(InvalidOperation()
3551 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003552 return false;
3553 }
3554
Geoff Langca271392017-04-05 12:30:00 -04003555 const TextureCaps &textureCaps =
3556 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003557 if (!textureCaps.texturable)
3558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003559 context->handleError(InvalidOperation()
3560 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003561 return false;
3562 }
3563
Geoff Langdcab33b2015-07-21 13:03:16 -04003564 return true;
3565}
3566
3567bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003568 GLenum target,
3569 egl::Image *image)
3570{
Geoff Langa8406172015-07-21 16:53:39 -04003571 if (!context->getExtensions().eglImage)
3572 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003573 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003574 return false;
3575 }
3576
3577 switch (target)
3578 {
3579 case GL_RENDERBUFFER:
3580 break;
3581
3582 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003583 context->handleError(InvalidEnum() << "invalid renderbuffer target.");
Geoff Langa8406172015-07-21 16:53:39 -04003584 return false;
3585 }
3586
Jamie Madill61e16b42017-06-19 11:13:23 -04003587 ASSERT(context->getCurrentDisplay());
3588 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003589 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003590 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003591 return false;
3592 }
3593
Geoff Langca271392017-04-05 12:30:00 -04003594 const TextureCaps &textureCaps =
3595 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003596 if (!textureCaps.renderable)
3597 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003598 context->handleError(InvalidOperation()
3599 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003600 return false;
3601 }
3602
Geoff Langdcab33b2015-07-21 13:03:16 -04003603 return true;
3604}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003605
3606bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3607{
Geoff Lang36167ab2015-12-07 10:27:14 -05003608 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003609 {
3610 // The default VAO should always exist
3611 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003612 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003613 return false;
3614 }
3615
3616 return true;
3617}
3618
Geoff Langc5629752015-12-07 16:29:04 -05003619bool ValidateProgramBinaryBase(Context *context,
3620 GLuint program,
3621 GLenum binaryFormat,
3622 const void *binary,
3623 GLint length)
3624{
3625 Program *programObject = GetValidProgram(context, program);
3626 if (programObject == nullptr)
3627 {
3628 return false;
3629 }
3630
3631 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3632 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3633 programBinaryFormats.end())
3634 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003635 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003636 return false;
3637 }
3638
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003639 if (context->hasActiveTransformFeedback(program))
3640 {
3641 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003642 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3643 "is associated with an active transform "
3644 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003645 return false;
3646 }
3647
Geoff Langc5629752015-12-07 16:29:04 -05003648 return true;
3649}
3650
3651bool ValidateGetProgramBinaryBase(Context *context,
3652 GLuint program,
3653 GLsizei bufSize,
3654 GLsizei *length,
3655 GLenum *binaryFormat,
3656 void *binary)
3657{
3658 Program *programObject = GetValidProgram(context, program);
3659 if (programObject == nullptr)
3660 {
3661 return false;
3662 }
3663
3664 if (!programObject->isLinked())
3665 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003666 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003667 return false;
3668 }
3669
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003670 if (context->getCaps().programBinaryFormats.empty())
3671 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003672 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003673 return false;
3674 }
3675
Geoff Langc5629752015-12-07 16:29:04 -05003676 return true;
3677}
Jamie Madillc29968b2016-01-20 11:17:23 -05003678
Jamie Madillc29968b2016-01-20 11:17:23 -05003679bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3680{
3681 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3682 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3683 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003684 context->handleError(InvalidValue()
3685 << "n must be non-negative and no greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003686 return false;
3687 }
3688
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003689 ASSERT(context->getGLState().getDrawFramebuffer());
3690 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003691 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3692
3693 // This should come first before the check for the default frame buffer
3694 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3695 // rather than INVALID_OPERATION
3696 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3697 {
3698 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3699
3700 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003701 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3702 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003703 {
3704 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003705 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3706 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3707 // 3.1 is still a bit ambiguous about the error, but future specs are
3708 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003709 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003710 return false;
3711 }
3712 else if (bufs[colorAttachment] >= maxColorAttachment)
3713 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003714 context->handleError(InvalidOperation()
3715 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003716 return false;
3717 }
3718 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3719 frameBufferId != 0)
3720 {
3721 // INVALID_OPERATION-GL is bound to buffer and ith argument
3722 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003723 context->handleError(InvalidOperation()
3724 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003725 return false;
3726 }
3727 }
3728
3729 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3730 // and n is not 1 or bufs is bound to value other than BACK and NONE
3731 if (frameBufferId == 0)
3732 {
3733 if (n != 1)
3734 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003735 context->handleError(InvalidOperation()
3736 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003737 return false;
3738 }
3739
3740 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3741 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003742 context->handleError(
3743 InvalidOperation()
3744 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003745 return false;
3746 }
3747 }
3748
3749 return true;
3750}
3751
Geoff Lang496c02d2016-10-20 11:38:11 -07003752bool ValidateGetBufferPointervBase(Context *context,
3753 GLenum target,
3754 GLenum pname,
3755 GLsizei *length,
3756 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003757{
Geoff Lang496c02d2016-10-20 11:38:11 -07003758 if (length)
3759 {
3760 *length = 0;
3761 }
3762
3763 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3764 {
3765 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003766 InvalidOperation()
3767 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003768 return false;
3769 }
3770
Olli Etuaho4f667482016-03-30 15:56:35 +03003771 if (!ValidBufferTarget(context, target))
3772 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003773 context->handleError(InvalidEnum() << "Buffer target not valid: 0x" << std::hex
3774 << std::uppercase << target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003775 return false;
3776 }
3777
Geoff Lang496c02d2016-10-20 11:38:11 -07003778 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003779 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003780 case GL_BUFFER_MAP_POINTER:
3781 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003782
Geoff Lang496c02d2016-10-20 11:38:11 -07003783 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003784 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003785 return false;
3786 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003787
3788 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3789 // target bound to zero generate an INVALID_OPERATION error."
3790 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003791 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003792 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003793 context->handleError(InvalidOperation()
3794 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003795 return false;
3796 }
3797
Geoff Lang496c02d2016-10-20 11:38:11 -07003798 if (length)
3799 {
3800 *length = 1;
3801 }
3802
Olli Etuaho4f667482016-03-30 15:56:35 +03003803 return true;
3804}
3805
3806bool ValidateUnmapBufferBase(Context *context, GLenum target)
3807{
3808 if (!ValidBufferTarget(context, target))
3809 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003810 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003811 return false;
3812 }
3813
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003814 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003815
3816 if (buffer == nullptr || !buffer->isMapped())
3817 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003818 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003819 return false;
3820 }
3821
3822 return true;
3823}
3824
3825bool ValidateMapBufferRangeBase(Context *context,
3826 GLenum target,
3827 GLintptr offset,
3828 GLsizeiptr length,
3829 GLbitfield access)
3830{
3831 if (!ValidBufferTarget(context, target))
3832 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003833 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003834 return false;
3835 }
3836
Brandon Jones6cad5662017-06-14 13:25:13 -07003837 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003838 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003839 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3840 return false;
3841 }
3842
3843 if (length < 0)
3844 {
3845 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003846 return false;
3847 }
3848
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003849 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003850
3851 if (!buffer)
3852 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003853 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003854 return false;
3855 }
3856
3857 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003858 CheckedNumeric<size_t> checkedOffset(offset);
3859 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003860
Jamie Madille2e406c2016-06-02 13:04:10 -04003861 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003862 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003863 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003864 return false;
3865 }
3866
3867 // Check for invalid bits in the mask
3868 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3869 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3870 GL_MAP_UNSYNCHRONIZED_BIT;
3871
3872 if (access & ~(allAccessBits))
3873 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003874 context->handleError(InvalidValue()
3875 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003876 return false;
3877 }
3878
3879 if (length == 0)
3880 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003881 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003882 return false;
3883 }
3884
3885 if (buffer->isMapped())
3886 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003887 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003888 return false;
3889 }
3890
3891 // Check for invalid bit combinations
3892 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3893 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003894 context->handleError(InvalidOperation()
3895 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003896 return false;
3897 }
3898
3899 GLbitfield writeOnlyBits =
3900 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3901
3902 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3903 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003904 context->handleError(InvalidOperation()
3905 << "Invalid access bits when mapping buffer for reading: 0x"
3906 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003907 return false;
3908 }
3909
3910 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3911 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003912 context->handleError(
3913 InvalidOperation()
3914 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003915 return false;
3916 }
3917 return true;
3918}
3919
3920bool ValidateFlushMappedBufferRangeBase(Context *context,
3921 GLenum target,
3922 GLintptr offset,
3923 GLsizeiptr length)
3924{
Brandon Jones6cad5662017-06-14 13:25:13 -07003925 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003926 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003927 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3928 return false;
3929 }
3930
3931 if (length < 0)
3932 {
3933 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003934 return false;
3935 }
3936
3937 if (!ValidBufferTarget(context, target))
3938 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003939 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003940 return false;
3941 }
3942
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003943 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003944
3945 if (buffer == nullptr)
3946 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003947 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003948 return false;
3949 }
3950
3951 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3952 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003953 context->handleError(InvalidOperation()
3954 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003955 return false;
3956 }
3957
3958 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003959 CheckedNumeric<size_t> checkedOffset(offset);
3960 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003961
Jamie Madille2e406c2016-06-02 13:04:10 -04003962 if (!checkedSize.IsValid() ||
3963 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003964 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003965 context->handleError(InvalidValue()
3966 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003967 return false;
3968 }
3969
3970 return true;
3971}
3972
Olli Etuaho41997e72016-03-10 13:38:39 +02003973bool ValidateGenOrDelete(Context *context, GLint n)
3974{
3975 if (n < 0)
3976 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003977 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003978 return false;
3979 }
3980 return true;
3981}
3982
Geoff Langff5b2d52016-09-07 11:32:23 -04003983bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3984{
3985 if (!context->getExtensions().robustClientMemory)
3986 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003987 context->handleError(InvalidOperation()
3988 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003989 return false;
3990 }
3991
3992 if (bufSize < 0)
3993 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003994 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003995 return false;
3996 }
3997
3998 return true;
3999}
4000
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004001bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4002{
4003 if (bufSize < numParams)
4004 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004005 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4006 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004007 return false;
4008 }
4009
4010 return true;
4011}
4012
Jamie Madillbe849e42017-05-02 15:49:00 -04004013bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
4014 GLenum target,
4015 GLenum attachment,
4016 GLenum pname,
4017 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004018{
Geoff Langff5b2d52016-09-07 11:32:23 -04004019 if (!ValidFramebufferTarget(target))
4020 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004021 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004022 return false;
4023 }
4024
4025 int clientVersion = context->getClientMajorVersion();
4026
4027 switch (pname)
4028 {
4029 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4030 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4031 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4032 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4033 break;
4034
Martin Radeve5285d22017-07-14 16:23:53 +03004035 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4036 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4037 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4038 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4039 if (clientVersion < 3 || !context->getExtensions().multiview)
4040 {
4041 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4042 return false;
4043 }
4044 break;
4045
Geoff Langff5b2d52016-09-07 11:32:23 -04004046 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4047 if (clientVersion < 3 && !context->getExtensions().sRGB)
4048 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004049 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004050 return false;
4051 }
4052 break;
4053
4054 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4055 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4056 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4057 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4058 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4059 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4060 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4061 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4062 if (clientVersion < 3)
4063 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004064 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004065 return false;
4066 }
4067 break;
4068
4069 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004070 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004071 return false;
4072 }
4073
4074 // Determine if the attachment is a valid enum
4075 switch (attachment)
4076 {
4077 case GL_BACK:
4078 case GL_FRONT:
4079 case GL_DEPTH:
4080 case GL_STENCIL:
4081 case GL_DEPTH_STENCIL_ATTACHMENT:
4082 if (clientVersion < 3)
4083 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004084 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004085 return false;
4086 }
4087 break;
4088
4089 case GL_DEPTH_ATTACHMENT:
4090 case GL_STENCIL_ATTACHMENT:
4091 break;
4092
4093 default:
4094 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4095 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4096 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004097 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004098 return false;
4099 }
4100 break;
4101 }
4102
4103 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4104 ASSERT(framebuffer);
4105
4106 if (framebuffer->id() == 0)
4107 {
4108 if (clientVersion < 3)
4109 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004110 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004111 return false;
4112 }
4113
4114 switch (attachment)
4115 {
4116 case GL_BACK:
4117 case GL_DEPTH:
4118 case GL_STENCIL:
4119 break;
4120
4121 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004122 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FramebufferInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004123 return false;
4124 }
4125 }
4126 else
4127 {
4128 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4129 {
4130 // Valid attachment query
4131 }
4132 else
4133 {
4134 switch (attachment)
4135 {
4136 case GL_DEPTH_ATTACHMENT:
4137 case GL_STENCIL_ATTACHMENT:
4138 break;
4139
4140 case GL_DEPTH_STENCIL_ATTACHMENT:
4141 if (!framebuffer->hasValidDepthStencil())
4142 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004143 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004144 return false;
4145 }
4146 break;
4147
4148 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004149 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FramebufferInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004150 return false;
4151 }
4152 }
4153 }
4154
4155 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4156 if (attachmentObject)
4157 {
4158 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4159 attachmentObject->type() == GL_TEXTURE ||
4160 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4161
4162 switch (pname)
4163 {
4164 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4165 if (attachmentObject->type() != GL_RENDERBUFFER &&
4166 attachmentObject->type() != GL_TEXTURE)
4167 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004168 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004169 return false;
4170 }
4171 break;
4172
4173 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4174 if (attachmentObject->type() != GL_TEXTURE)
4175 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004176 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004177 return false;
4178 }
4179 break;
4180
4181 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4182 if (attachmentObject->type() != GL_TEXTURE)
4183 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004184 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004185 return false;
4186 }
4187 break;
4188
4189 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4190 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4191 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004192 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FramebufferInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004193 return false;
4194 }
4195 break;
4196
4197 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4198 if (attachmentObject->type() != GL_TEXTURE)
4199 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004200 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004201 return false;
4202 }
4203 break;
4204
4205 default:
4206 break;
4207 }
4208 }
4209 else
4210 {
4211 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4212 // is NONE, then querying any other pname will generate INVALID_ENUM.
4213
4214 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4215 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4216 // INVALID_OPERATION for all other pnames
4217
4218 switch (pname)
4219 {
4220 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4221 break;
4222
4223 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4224 if (clientVersion < 3)
4225 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004226 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
4227 InvalidRenderbufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004228 return false;
4229 }
4230 break;
4231
4232 default:
4233 if (clientVersion < 3)
4234 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004235 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
4236 InvalidRenderbufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004237 return false;
4238 }
4239 else
4240 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004241 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
4242 InvalidRenderbufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004243 return false;
4244 }
4245 }
4246 }
4247
Martin Radeve5285d22017-07-14 16:23:53 +03004248 if (numParams)
4249 {
4250 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4251 {
4252 // Only when the viewport offsets are queried we can have a varying number of output
4253 // parameters.
4254 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4255 *numParams = numViews * 2;
4256 }
4257 else
4258 {
4259 // For all other queries we can have only one output parameter.
4260 *numParams = 1;
4261 }
4262 }
4263
Geoff Langff5b2d52016-09-07 11:32:23 -04004264 return true;
4265}
4266
4267bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4268 GLenum target,
4269 GLenum attachment,
4270 GLenum pname,
4271 GLsizei bufSize,
4272 GLsizei *numParams)
4273{
4274 if (!ValidateRobustEntryPoint(context, bufSize))
4275 {
4276 return false;
4277 }
4278
Jamie Madillbe849e42017-05-02 15:49:00 -04004279 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4280 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004281 {
4282 return false;
4283 }
4284
4285 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4286 {
4287 return false;
4288 }
4289
4290 return true;
4291}
4292
Geoff Langff5b2d52016-09-07 11:32:23 -04004293bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4294 GLenum target,
4295 GLenum pname,
4296 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004297 GLsizei *length,
4298 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004299{
4300 if (!ValidateRobustEntryPoint(context, bufSize))
4301 {
4302 return false;
4303 }
4304
Geoff Langebebe1c2016-10-14 12:01:31 -04004305 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004306 {
4307 return false;
4308 }
4309
Geoff Langebebe1c2016-10-14 12:01:31 -04004310 if (!ValidateRobustBufferSize(context, bufSize, *length))
4311 {
4312 return false;
4313 }
4314
4315 return true;
4316}
4317
4318bool ValidateGetBufferParameteri64v(ValidationContext *context,
4319 GLenum target,
4320 GLenum pname,
4321 GLint64 *params)
4322{
4323 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4324}
4325
4326bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4327 GLenum target,
4328 GLenum pname,
4329 GLsizei bufSize,
4330 GLsizei *length,
4331 GLint64 *params)
4332{
4333 if (!ValidateRobustEntryPoint(context, bufSize))
4334 {
4335 return false;
4336 }
4337
4338 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4339 {
4340 return false;
4341 }
4342
4343 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004344 {
4345 return false;
4346 }
4347
4348 return true;
4349}
4350
Jamie Madillbe849e42017-05-02 15:49:00 -04004351bool ValidateGetProgramivBase(ValidationContext *context,
4352 GLuint program,
4353 GLenum pname,
4354 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004355{
4356 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004357 if (numParams)
4358 {
4359 *numParams = 1;
4360 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004361
4362 Program *programObject = GetValidProgram(context, program);
4363 if (!programObject)
4364 {
4365 return false;
4366 }
4367
4368 switch (pname)
4369 {
4370 case GL_DELETE_STATUS:
4371 case GL_LINK_STATUS:
4372 case GL_VALIDATE_STATUS:
4373 case GL_INFO_LOG_LENGTH:
4374 case GL_ATTACHED_SHADERS:
4375 case GL_ACTIVE_ATTRIBUTES:
4376 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4377 case GL_ACTIVE_UNIFORMS:
4378 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4379 break;
4380
4381 case GL_PROGRAM_BINARY_LENGTH:
4382 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4383 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004384 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4385 "requires GL_OES_get_program_binary or "
4386 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004387 return false;
4388 }
4389 break;
4390
4391 case GL_ACTIVE_UNIFORM_BLOCKS:
4392 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4393 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4394 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4395 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4396 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4397 if (context->getClientMajorVersion() < 3)
4398 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004399 context->handleError(InvalidEnum() << "Querying requires at least ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004400 return false;
4401 }
4402 break;
4403
Yunchao He61afff12017-03-14 15:34:03 +08004404 case GL_PROGRAM_SEPARABLE:
4405 if (context->getClientVersion() < Version(3, 1))
4406 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004407 context->handleError(InvalidEnum() << "Querying requires at least ES 3.1.");
Yunchao He61afff12017-03-14 15:34:03 +08004408 return false;
4409 }
4410 break;
4411
Geoff Langff5b2d52016-09-07 11:32:23 -04004412 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004413 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004414 return false;
4415 }
4416
4417 return true;
4418}
4419
4420bool ValidateGetProgramivRobustANGLE(Context *context,
4421 GLuint program,
4422 GLenum pname,
4423 GLsizei bufSize,
4424 GLsizei *numParams)
4425{
4426 if (!ValidateRobustEntryPoint(context, bufSize))
4427 {
4428 return false;
4429 }
4430
Jamie Madillbe849e42017-05-02 15:49:00 -04004431 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004432 {
4433 return false;
4434 }
4435
4436 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4437 {
4438 return false;
4439 }
4440
4441 return true;
4442}
4443
Geoff Lang740d9022016-10-07 11:20:52 -04004444bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4445 GLenum target,
4446 GLenum pname,
4447 GLsizei bufSize,
4448 GLsizei *length,
4449 GLint *params)
4450{
4451 if (!ValidateRobustEntryPoint(context, bufSize))
4452 {
4453 return false;
4454 }
4455
4456 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4457 {
4458 return false;
4459 }
4460
4461 if (!ValidateRobustBufferSize(context, bufSize, *length))
4462 {
4463 return false;
4464 }
4465
4466 return true;
4467}
4468
Geoff Langd7d0ed32016-10-07 11:33:51 -04004469bool ValidateGetShaderivRobustANGLE(Context *context,
4470 GLuint shader,
4471 GLenum pname,
4472 GLsizei bufSize,
4473 GLsizei *length,
4474 GLint *params)
4475{
4476 if (!ValidateRobustEntryPoint(context, bufSize))
4477 {
4478 return false;
4479 }
4480
4481 if (!ValidateGetShaderivBase(context, shader, pname, length))
4482 {
4483 return false;
4484 }
4485
4486 if (!ValidateRobustBufferSize(context, bufSize, *length))
4487 {
4488 return false;
4489 }
4490
4491 return true;
4492}
4493
Geoff Langc1984ed2016-10-07 12:41:00 -04004494bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4495 GLenum target,
4496 GLenum pname,
4497 GLsizei bufSize,
4498 GLsizei *length,
4499 GLfloat *params)
4500{
4501 if (!ValidateRobustEntryPoint(context, bufSize))
4502 {
4503 return false;
4504 }
4505
4506 if (!ValidateGetTexParameterBase(context, target, pname, length))
4507 {
4508 return false;
4509 }
4510
4511 if (!ValidateRobustBufferSize(context, bufSize, *length))
4512 {
4513 return false;
4514 }
4515
4516 return true;
4517}
4518
Geoff Langc1984ed2016-10-07 12:41:00 -04004519bool ValidateGetTexParameterivRobustANGLE(Context *context,
4520 GLenum target,
4521 GLenum pname,
4522 GLsizei bufSize,
4523 GLsizei *length,
4524 GLint *params)
4525{
4526 if (!ValidateRobustEntryPoint(context, bufSize))
4527 {
4528 return false;
4529 }
4530
4531 if (!ValidateGetTexParameterBase(context, target, pname, length))
4532 {
4533 return false;
4534 }
4535
4536 if (!ValidateRobustBufferSize(context, bufSize, *length))
4537 {
4538 return false;
4539 }
4540
4541 return true;
4542}
4543
Geoff Langc1984ed2016-10-07 12:41:00 -04004544bool ValidateTexParameterfvRobustANGLE(Context *context,
4545 GLenum target,
4546 GLenum pname,
4547 GLsizei bufSize,
4548 const GLfloat *params)
4549{
4550 if (!ValidateRobustEntryPoint(context, bufSize))
4551 {
4552 return false;
4553 }
4554
4555 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4556}
4557
Geoff Langc1984ed2016-10-07 12:41:00 -04004558bool ValidateTexParameterivRobustANGLE(Context *context,
4559 GLenum target,
4560 GLenum pname,
4561 GLsizei bufSize,
4562 const GLint *params)
4563{
4564 if (!ValidateRobustEntryPoint(context, bufSize))
4565 {
4566 return false;
4567 }
4568
4569 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4570}
4571
4572bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4573{
4574 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4575}
4576
4577bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4578 GLuint sampler,
4579 GLenum pname,
4580 GLuint bufSize,
4581 GLsizei *length,
4582 GLfloat *params)
4583{
4584 if (!ValidateRobustEntryPoint(context, bufSize))
4585 {
4586 return false;
4587 }
4588
4589 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4590 {
4591 return false;
4592 }
4593
4594 if (!ValidateRobustBufferSize(context, bufSize, *length))
4595 {
4596 return false;
4597 }
4598
4599 return true;
4600}
4601
4602bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4603{
4604 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4605}
4606
4607bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4608 GLuint sampler,
4609 GLenum pname,
4610 GLuint bufSize,
4611 GLsizei *length,
4612 GLint *params)
4613{
4614 if (!ValidateRobustEntryPoint(context, bufSize))
4615 {
4616 return false;
4617 }
4618
4619 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4620 {
4621 return false;
4622 }
4623
4624 if (!ValidateRobustBufferSize(context, bufSize, *length))
4625 {
4626 return false;
4627 }
4628
4629 return true;
4630}
4631
4632bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4633{
4634 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4635}
4636
4637bool ValidateSamplerParameterfv(Context *context,
4638 GLuint sampler,
4639 GLenum pname,
4640 const GLfloat *params)
4641{
4642 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4643}
4644
4645bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4646 GLuint sampler,
4647 GLenum pname,
4648 GLsizei bufSize,
4649 const GLfloat *params)
4650{
4651 if (!ValidateRobustEntryPoint(context, bufSize))
4652 {
4653 return false;
4654 }
4655
4656 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4657}
4658
4659bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4660{
4661 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4662}
4663
4664bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4665{
4666 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4667}
4668
4669bool ValidateSamplerParameterivRobustANGLE(Context *context,
4670 GLuint sampler,
4671 GLenum pname,
4672 GLsizei bufSize,
4673 const GLint *params)
4674{
4675 if (!ValidateRobustEntryPoint(context, bufSize))
4676 {
4677 return false;
4678 }
4679
4680 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4681}
4682
Geoff Lang0b031062016-10-13 14:30:04 -04004683bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4684 GLuint index,
4685 GLenum pname,
4686 GLsizei bufSize,
4687 GLsizei *length,
4688 GLfloat *params)
4689{
4690 if (!ValidateRobustEntryPoint(context, bufSize))
4691 {
4692 return false;
4693 }
4694
4695 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4696 {
4697 return false;
4698 }
4699
4700 if (!ValidateRobustBufferSize(context, bufSize, *length))
4701 {
4702 return false;
4703 }
4704
4705 return true;
4706}
4707
Geoff Lang0b031062016-10-13 14:30:04 -04004708bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4709 GLuint index,
4710 GLenum pname,
4711 GLsizei bufSize,
4712 GLsizei *length,
4713 GLint *params)
4714{
4715 if (!ValidateRobustEntryPoint(context, bufSize))
4716 {
4717 return false;
4718 }
4719
4720 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4721 {
4722 return false;
4723 }
4724
4725 if (!ValidateRobustBufferSize(context, bufSize, *length))
4726 {
4727 return false;
4728 }
4729
4730 return true;
4731}
4732
Geoff Lang0b031062016-10-13 14:30:04 -04004733bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4734 GLuint index,
4735 GLenum pname,
4736 GLsizei bufSize,
4737 GLsizei *length,
4738 void **pointer)
4739{
4740 if (!ValidateRobustEntryPoint(context, bufSize))
4741 {
4742 return false;
4743 }
4744
4745 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4746 {
4747 return false;
4748 }
4749
4750 if (!ValidateRobustBufferSize(context, bufSize, *length))
4751 {
4752 return false;
4753 }
4754
4755 return true;
4756}
4757
4758bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
4759{
4760 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4761}
4762
4763bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4764 GLuint index,
4765 GLenum pname,
4766 GLsizei bufSize,
4767 GLsizei *length,
4768 GLint *params)
4769{
4770 if (!ValidateRobustEntryPoint(context, bufSize))
4771 {
4772 return false;
4773 }
4774
4775 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4776 {
4777 return false;
4778 }
4779
4780 if (!ValidateRobustBufferSize(context, bufSize, *length))
4781 {
4782 return false;
4783 }
4784
4785 return true;
4786}
4787
4788bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
4789{
4790 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4791}
4792
4793bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4794 GLuint index,
4795 GLenum pname,
4796 GLsizei bufSize,
4797 GLsizei *length,
4798 GLuint *params)
4799{
4800 if (!ValidateRobustEntryPoint(context, bufSize))
4801 {
4802 return false;
4803 }
4804
4805 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4806 {
4807 return false;
4808 }
4809
4810 if (!ValidateRobustBufferSize(context, bufSize, *length))
4811 {
4812 return false;
4813 }
4814
4815 return true;
4816}
4817
Geoff Lang6899b872016-10-14 11:30:13 -04004818bool ValidateGetActiveUniformBlockiv(Context *context,
4819 GLuint program,
4820 GLuint uniformBlockIndex,
4821 GLenum pname,
4822 GLint *params)
4823{
4824 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
4825}
4826
4827bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4828 GLuint program,
4829 GLuint uniformBlockIndex,
4830 GLenum pname,
4831 GLsizei bufSize,
4832 GLsizei *length,
4833 GLint *params)
4834{
4835 if (!ValidateRobustEntryPoint(context, bufSize))
4836 {
4837 return false;
4838 }
4839
4840 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4841 {
4842 return false;
4843 }
4844
4845 if (!ValidateRobustBufferSize(context, bufSize, *length))
4846 {
4847 return false;
4848 }
4849
4850 return true;
4851}
4852
Geoff Lang0a9661f2016-10-20 10:59:20 -07004853bool ValidateGetInternalFormativ(Context *context,
4854 GLenum target,
4855 GLenum internalformat,
4856 GLenum pname,
4857 GLsizei bufSize,
4858 GLint *params)
4859{
4860 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4861 nullptr);
4862}
4863
4864bool ValidateGetInternalFormativRobustANGLE(Context *context,
4865 GLenum target,
4866 GLenum internalformat,
4867 GLenum pname,
4868 GLsizei bufSize,
4869 GLsizei *length,
4870 GLint *params)
4871{
4872 if (!ValidateRobustEntryPoint(context, bufSize))
4873 {
4874 return false;
4875 }
4876
4877 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4878 {
4879 return false;
4880 }
4881
4882 if (!ValidateRobustBufferSize(context, bufSize, *length))
4883 {
4884 return false;
4885 }
4886
4887 return true;
4888}
4889
Shao80957d92017-02-20 21:25:59 +08004890bool ValidateVertexFormatBase(ValidationContext *context,
4891 GLuint attribIndex,
4892 GLint size,
4893 GLenum type,
4894 GLboolean pureInteger)
4895{
4896 const Caps &caps = context->getCaps();
4897 if (attribIndex >= caps.maxVertexAttributes)
4898 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004899 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Shao80957d92017-02-20 21:25:59 +08004900 return false;
4901 }
4902
4903 if (size < 1 || size > 4)
4904 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004905 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004906 return false;
Shao80957d92017-02-20 21:25:59 +08004907 }
4908
4909 switch (type)
4910 {
4911 case GL_BYTE:
4912 case GL_UNSIGNED_BYTE:
4913 case GL_SHORT:
4914 case GL_UNSIGNED_SHORT:
4915 break;
4916
4917 case GL_INT:
4918 case GL_UNSIGNED_INT:
4919 if (context->getClientMajorVersion() < 3)
4920 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004921 context->handleError(InvalidEnum()
4922 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004923 return false;
4924 }
4925 break;
4926
4927 case GL_FIXED:
4928 case GL_FLOAT:
4929 if (pureInteger)
4930 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004931 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004932 return false;
4933 }
4934 break;
4935
4936 case GL_HALF_FLOAT:
4937 if (context->getClientMajorVersion() < 3)
4938 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004939 context->handleError(InvalidEnum()
4940 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004941 return false;
4942 }
4943 if (pureInteger)
4944 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004945 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004946 return false;
4947 }
4948 break;
4949
4950 case GL_INT_2_10_10_10_REV:
4951 case GL_UNSIGNED_INT_2_10_10_10_REV:
4952 if (context->getClientMajorVersion() < 3)
4953 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004954 context->handleError(InvalidEnum()
4955 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004956 return false;
4957 }
4958 if (pureInteger)
4959 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004960 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004961 return false;
4962 }
4963 if (size != 4)
4964 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004965 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4966 "UNSIGNED_INT_2_10_10_10_REV and "
4967 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004968 return false;
4969 }
4970 break;
4971
4972 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004973 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004974 return false;
4975 }
4976
4977 return true;
4978}
4979
Geoff Lang76e65652017-03-27 14:58:02 -04004980// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4981// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4982// specified clear value and the type of a buffer that is being cleared generates an
4983// INVALID_OPERATION error instead of producing undefined results
4984bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4985 GLint drawbuffer,
4986 const GLenum *validComponentTypes,
4987 size_t validComponentTypeCount)
4988{
4989 const FramebufferAttachment *attachment =
4990 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4991 if (attachment)
4992 {
4993 GLenum componentType = attachment->getFormat().info->componentType;
4994 const GLenum *end = validComponentTypes + validComponentTypeCount;
4995 if (std::find(validComponentTypes, end, componentType) == end)
4996 {
4997 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004998 InvalidOperation()
4999 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005000 return false;
5001 }
5002 }
5003
5004 return true;
5005}
5006
Corentin Wallezb2931602017-04-11 15:58:57 -04005007bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
5008 GLsizei imageSize,
5009 GLsizei dataSize)
5010{
5011 if (!ValidateRobustEntryPoint(context, dataSize))
5012 {
5013 return false;
5014 }
5015
5016 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
5017 if (pixelUnpackBuffer == nullptr)
5018 {
5019 if (dataSize < imageSize)
5020 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005021 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005022 }
5023 }
5024 return true;
5025}
5026
Jamie Madillbe849e42017-05-02 15:49:00 -04005027bool ValidateGetBufferParameterBase(ValidationContext *context,
5028 GLenum target,
5029 GLenum pname,
5030 bool pointerVersion,
5031 GLsizei *numParams)
5032{
5033 if (numParams)
5034 {
5035 *numParams = 0;
5036 }
5037
5038 if (!ValidBufferTarget(context, target))
5039 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005040 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005041 return false;
5042 }
5043
5044 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5045 if (!buffer)
5046 {
5047 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005048 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005049 return false;
5050 }
5051
5052 const Extensions &extensions = context->getExtensions();
5053
5054 switch (pname)
5055 {
5056 case GL_BUFFER_USAGE:
5057 case GL_BUFFER_SIZE:
5058 break;
5059
5060 case GL_BUFFER_ACCESS_OES:
5061 if (!extensions.mapBuffer)
5062 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005063 context->handleError(InvalidEnum()
5064 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005065 return false;
5066 }
5067 break;
5068
5069 case GL_BUFFER_MAPPED:
5070 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5071 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5072 !extensions.mapBufferRange)
5073 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005074 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5075 "GL_OES_mapbuffer or "
5076 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005077 return false;
5078 }
5079 break;
5080
5081 case GL_BUFFER_MAP_POINTER:
5082 if (!pointerVersion)
5083 {
5084 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005085 InvalidEnum()
5086 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005087 return false;
5088 }
5089 break;
5090
5091 case GL_BUFFER_ACCESS_FLAGS:
5092 case GL_BUFFER_MAP_OFFSET:
5093 case GL_BUFFER_MAP_LENGTH:
5094 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5095 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005096 context->handleError(InvalidEnum()
5097 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005098 return false;
5099 }
5100 break;
5101
5102 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005103 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005104 return false;
5105 }
5106
5107 // All buffer parameter queries return one value.
5108 if (numParams)
5109 {
5110 *numParams = 1;
5111 }
5112
5113 return true;
5114}
5115
5116bool ValidateGetRenderbufferParameterivBase(Context *context,
5117 GLenum target,
5118 GLenum pname,
5119 GLsizei *length)
5120{
5121 if (length)
5122 {
5123 *length = 0;
5124 }
5125
5126 if (target != GL_RENDERBUFFER)
5127 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005128 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005129 return false;
5130 }
5131
5132 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5133 if (renderbuffer == nullptr)
5134 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005135 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005136 return false;
5137 }
5138
5139 switch (pname)
5140 {
5141 case GL_RENDERBUFFER_WIDTH:
5142 case GL_RENDERBUFFER_HEIGHT:
5143 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5144 case GL_RENDERBUFFER_RED_SIZE:
5145 case GL_RENDERBUFFER_GREEN_SIZE:
5146 case GL_RENDERBUFFER_BLUE_SIZE:
5147 case GL_RENDERBUFFER_ALPHA_SIZE:
5148 case GL_RENDERBUFFER_DEPTH_SIZE:
5149 case GL_RENDERBUFFER_STENCIL_SIZE:
5150 break;
5151
5152 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5153 if (!context->getExtensions().framebufferMultisample)
5154 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005155 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005156 return false;
5157 }
5158 break;
5159
5160 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005161 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005162 return false;
5163 }
5164
5165 if (length)
5166 {
5167 *length = 1;
5168 }
5169 return true;
5170}
5171
5172bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5173{
5174 if (length)
5175 {
5176 *length = 0;
5177 }
5178
5179 if (GetValidShader(context, shader) == nullptr)
5180 {
5181 return false;
5182 }
5183
5184 switch (pname)
5185 {
5186 case GL_SHADER_TYPE:
5187 case GL_DELETE_STATUS:
5188 case GL_COMPILE_STATUS:
5189 case GL_INFO_LOG_LENGTH:
5190 case GL_SHADER_SOURCE_LENGTH:
5191 break;
5192
5193 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5194 if (!context->getExtensions().translatedShaderSource)
5195 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005196 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005197 return false;
5198 }
5199 break;
5200
5201 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005202 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005203 return false;
5204 }
5205
5206 if (length)
5207 {
5208 *length = 1;
5209 }
5210 return true;
5211}
5212
5213bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
5214{
5215 if (length)
5216 {
5217 *length = 0;
5218 }
5219
5220 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5221 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005222 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005223 return false;
5224 }
5225
5226 if (context->getTargetTexture(target) == nullptr)
5227 {
5228 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005229 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005230 return false;
5231 }
5232
5233 switch (pname)
5234 {
5235 case GL_TEXTURE_MAG_FILTER:
5236 case GL_TEXTURE_MIN_FILTER:
5237 case GL_TEXTURE_WRAP_S:
5238 case GL_TEXTURE_WRAP_T:
5239 break;
5240
5241 case GL_TEXTURE_USAGE_ANGLE:
5242 if (!context->getExtensions().textureUsage)
5243 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005244 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005245 return false;
5246 }
5247 break;
5248
5249 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5250 if (!context->getExtensions().textureFilterAnisotropic)
5251 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005252 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005253 return false;
5254 }
5255 break;
5256
5257 case GL_TEXTURE_IMMUTABLE_FORMAT:
5258 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5259 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005260 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005261 return false;
5262 }
5263 break;
5264
5265 case GL_TEXTURE_WRAP_R:
5266 case GL_TEXTURE_IMMUTABLE_LEVELS:
5267 case GL_TEXTURE_SWIZZLE_R:
5268 case GL_TEXTURE_SWIZZLE_G:
5269 case GL_TEXTURE_SWIZZLE_B:
5270 case GL_TEXTURE_SWIZZLE_A:
5271 case GL_TEXTURE_BASE_LEVEL:
5272 case GL_TEXTURE_MAX_LEVEL:
5273 case GL_TEXTURE_MIN_LOD:
5274 case GL_TEXTURE_MAX_LOD:
5275 case GL_TEXTURE_COMPARE_MODE:
5276 case GL_TEXTURE_COMPARE_FUNC:
5277 if (context->getClientMajorVersion() < 3)
5278 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005279 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005280 return false;
5281 }
5282 break;
5283
5284 case GL_TEXTURE_SRGB_DECODE_EXT:
5285 if (!context->getExtensions().textureSRGBDecode)
5286 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005287 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005288 return false;
5289 }
5290 break;
5291
5292 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005293 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005294 return false;
5295 }
5296
5297 if (length)
5298 {
5299 *length = 1;
5300 }
5301 return true;
5302}
5303
5304bool ValidateGetVertexAttribBase(Context *context,
5305 GLuint index,
5306 GLenum pname,
5307 GLsizei *length,
5308 bool pointer,
5309 bool pureIntegerEntryPoint)
5310{
5311 if (length)
5312 {
5313 *length = 0;
5314 }
5315
5316 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005318 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005319 return false;
5320 }
5321
5322 if (index >= context->getCaps().maxVertexAttributes)
5323 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005324 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Jamie Madillbe849e42017-05-02 15:49:00 -04005325 return false;
5326 }
5327
5328 if (pointer)
5329 {
5330 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5331 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005332 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005333 return false;
5334 }
5335 }
5336 else
5337 {
5338 switch (pname)
5339 {
5340 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5341 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5342 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5343 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5344 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5345 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5346 case GL_CURRENT_VERTEX_ATTRIB:
5347 break;
5348
5349 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5350 static_assert(
5351 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5352 "ANGLE extension enums not equal to GL enums.");
5353 if (context->getClientMajorVersion() < 3 &&
5354 !context->getExtensions().instancedArrays)
5355 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005356 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5357 "requires OpenGL ES 3.0 or "
5358 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005359 return false;
5360 }
5361 break;
5362
5363 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5364 if (context->getClientMajorVersion() < 3)
5365 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005366 context->handleError(
5367 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005368 return false;
5369 }
5370 break;
5371
5372 case GL_VERTEX_ATTRIB_BINDING:
5373 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5374 if (context->getClientVersion() < ES_3_1)
5375 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005376 context->handleError(InvalidEnum()
5377 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005378 return false;
5379 }
5380 break;
5381
5382 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005383 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005384 return false;
5385 }
5386 }
5387
5388 if (length)
5389 {
5390 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5391 {
5392 *length = 4;
5393 }
5394 else
5395 {
5396 *length = 1;
5397 }
5398 }
5399
5400 return true;
5401}
5402
Jamie Madill4928b7c2017-06-20 12:57:39 -04005403bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005404 GLint x,
5405 GLint y,
5406 GLsizei width,
5407 GLsizei height,
5408 GLenum format,
5409 GLenum type,
5410 GLsizei bufSize,
5411 GLsizei *length,
5412 GLsizei *columns,
5413 GLsizei *rows,
5414 void *pixels)
5415{
5416 if (length != nullptr)
5417 {
5418 *length = 0;
5419 }
5420 if (rows != nullptr)
5421 {
5422 *rows = 0;
5423 }
5424 if (columns != nullptr)
5425 {
5426 *columns = 0;
5427 }
5428
5429 if (width < 0 || height < 0)
5430 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005431 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005432 return false;
5433 }
5434
5435 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5436
5437 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5438 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005439 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005440 return false;
5441 }
5442
5443 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5444 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005445 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005446 return false;
5447 }
5448
5449 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5450 ASSERT(framebuffer);
5451
5452 if (framebuffer->getReadBufferState() == GL_NONE)
5453 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005454 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Jamie Madillbe849e42017-05-02 15:49:00 -04005455 return false;
5456 }
5457
5458 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5459 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5460 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5461 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5462 // situation is an application error that would lead to a crash in ANGLE.
5463 if (readBuffer == nullptr)
5464 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005465 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005466 return false;
5467 }
5468
Martin Radev28031682017-07-28 14:47:56 +03005469 // ANGLE_multiview, Revision 1:
5470 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5471 // current read framebuffer is not NONE.
5472 if (readBuffer->getMultiviewLayout() != GL_NONE)
5473 {
5474 context->handleError(InvalidFramebufferOperation()
5475 << "Attempting to read from a multi-view framebuffer.");
5476 return false;
5477 }
5478
Geoff Lang280ba992017-04-18 16:30:58 -04005479 if (context->getExtensions().webglCompatibility)
5480 {
5481 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5482 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5483 // and type before validating the combination of format and type. However, the
5484 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5485 // verifies that GL_INVALID_OPERATION is generated.
5486 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5487 // dEQP/WebGL.
5488 if (!ValidReadPixelsFormatEnum(context, format))
5489 {
5490 context->handleError(InvalidEnum() << "Invalid read format.");
5491 return false;
5492 }
5493
5494 if (!ValidReadPixelsTypeEnum(context, type))
5495 {
5496 context->handleError(InvalidEnum() << "Invalid read type.");
5497 return false;
5498 }
5499 }
5500
Jamie Madill4928b7c2017-06-20 12:57:39 -04005501 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5502 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005503 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5504
5505 bool validFormatTypeCombination =
5506 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5507
5508 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5509 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005510 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005511 return false;
5512 }
5513
5514 // Check for pixel pack buffer related API errors
5515 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5516 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5517 {
5518 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005519 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005520 return false;
5521 }
5522
5523 // .. the data would be packed to the buffer object such that the memory writes required
5524 // would exceed the data store size.
5525 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5526 const gl::Extents size(width, height, 1);
5527 const auto &pack = context->getGLState().getPackState();
5528
5529 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5530 if (endByteOrErr.isError())
5531 {
5532 context->handleError(endByteOrErr.getError());
5533 return false;
5534 }
5535
5536 size_t endByte = endByteOrErr.getResult();
5537 if (bufSize >= 0)
5538 {
5539 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5540 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005541 context->handleError(InvalidOperation()
5542 << "bufSize must be at least " << endByte << " bytes.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005543 return false;
5544 }
5545 }
5546
5547 if (pixelPackBuffer != nullptr)
5548 {
5549 CheckedNumeric<size_t> checkedEndByte(endByte);
5550 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5551 checkedEndByte += checkedOffset;
5552
5553 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5554 {
5555 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005556 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005557 return false;
5558 }
5559 }
5560
5561 if (pixelPackBuffer == nullptr && length != nullptr)
5562 {
5563 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5564 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005565 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005566 return false;
5567 }
5568
5569 *length = static_cast<GLsizei>(endByte);
5570 }
5571
5572 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5573 angle::CheckedNumeric<int> clippedExtent(length);
5574 if (start < 0)
5575 {
5576 // "subtract" the area that is less than 0
5577 clippedExtent += start;
5578 }
5579
5580 const int readExtent = start + length;
5581 if (readExtent > bufferSize)
5582 {
5583 // Subtract the region to the right of the read buffer
5584 clippedExtent -= (readExtent - bufferSize);
5585 }
5586
5587 if (!clippedExtent.IsValid())
5588 {
5589 return 0;
5590 }
5591
5592 return std::max(clippedExtent.ValueOrDie(), 0);
5593 };
5594
5595 if (columns != nullptr)
5596 {
5597 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5598 }
5599
5600 if (rows != nullptr)
5601 {
5602 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5603 }
5604
5605 return true;
5606}
5607
5608template <typename ParamType>
5609bool ValidateTexParameterBase(Context *context,
5610 GLenum target,
5611 GLenum pname,
5612 GLsizei bufSize,
5613 const ParamType *params)
5614{
5615 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5616 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005617 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005618 return false;
5619 }
5620
5621 if (context->getTargetTexture(target) == nullptr)
5622 {
5623 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005624 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005625 return false;
5626 }
5627
5628 const GLsizei minBufSize = 1;
5629 if (bufSize >= 0 && bufSize < minBufSize)
5630 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005631 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005632 return false;
5633 }
5634
5635 switch (pname)
5636 {
5637 case GL_TEXTURE_WRAP_R:
5638 case GL_TEXTURE_SWIZZLE_R:
5639 case GL_TEXTURE_SWIZZLE_G:
5640 case GL_TEXTURE_SWIZZLE_B:
5641 case GL_TEXTURE_SWIZZLE_A:
5642 case GL_TEXTURE_BASE_LEVEL:
5643 case GL_TEXTURE_MAX_LEVEL:
5644 case GL_TEXTURE_COMPARE_MODE:
5645 case GL_TEXTURE_COMPARE_FUNC:
5646 case GL_TEXTURE_MIN_LOD:
5647 case GL_TEXTURE_MAX_LOD:
5648 if (context->getClientMajorVersion() < 3)
5649 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005650 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005651 return false;
5652 }
5653 if (target == GL_TEXTURE_EXTERNAL_OES &&
5654 !context->getExtensions().eglImageExternalEssl3)
5655 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005656 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5657 "available without "
5658 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005659 return false;
5660 }
5661 break;
5662
5663 default:
5664 break;
5665 }
5666
JiangYizhou4cff8d62017-07-06 14:54:09 +08005667 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5668 {
5669 switch (pname)
5670 {
5671 case GL_TEXTURE_MIN_FILTER:
5672 case GL_TEXTURE_MAG_FILTER:
5673 case GL_TEXTURE_WRAP_S:
5674 case GL_TEXTURE_WRAP_T:
5675 case GL_TEXTURE_WRAP_R:
5676 case GL_TEXTURE_MIN_LOD:
5677 case GL_TEXTURE_MAX_LOD:
5678 case GL_TEXTURE_COMPARE_MODE:
5679 case GL_TEXTURE_COMPARE_FUNC:
5680 context->handleError(InvalidEnum()
5681 << "Invalid parameter for 2D multisampled textures.");
5682 return false;
5683 }
5684 }
5685
Jamie Madillbe849e42017-05-02 15:49:00 -04005686 switch (pname)
5687 {
5688 case GL_TEXTURE_WRAP_S:
5689 case GL_TEXTURE_WRAP_T:
5690 case GL_TEXTURE_WRAP_R:
5691 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
5692 {
5693 return false;
5694 }
5695 break;
5696
5697 case GL_TEXTURE_MIN_FILTER:
5698 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
5699 {
5700 return false;
5701 }
5702 break;
5703
5704 case GL_TEXTURE_MAG_FILTER:
5705 if (!ValidateTextureMagFilterValue(context, params))
5706 {
5707 return false;
5708 }
5709 break;
5710
5711 case GL_TEXTURE_USAGE_ANGLE:
5712 switch (ConvertToGLenum(params[0]))
5713 {
5714 case GL_NONE:
5715 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5716 break;
5717
5718 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005719 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005720 return false;
5721 }
5722 break;
5723
5724 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5725 if (!context->getExtensions().textureFilterAnisotropic)
5726 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005727 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005728 return false;
5729 }
5730
5731 // we assume the parameter passed to this validation method is truncated, not rounded
5732 if (params[0] < 1)
5733 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005734 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005735 return false;
5736 }
5737 break;
5738
5739 case GL_TEXTURE_MIN_LOD:
5740 case GL_TEXTURE_MAX_LOD:
5741 // any value is permissible
5742 break;
5743
5744 case GL_TEXTURE_COMPARE_MODE:
5745 if (!ValidateTextureCompareModeValue(context, params))
5746 {
5747 return false;
5748 }
5749 break;
5750
5751 case GL_TEXTURE_COMPARE_FUNC:
5752 if (!ValidateTextureCompareFuncValue(context, params))
5753 {
5754 return false;
5755 }
5756 break;
5757
5758 case GL_TEXTURE_SWIZZLE_R:
5759 case GL_TEXTURE_SWIZZLE_G:
5760 case GL_TEXTURE_SWIZZLE_B:
5761 case GL_TEXTURE_SWIZZLE_A:
5762 switch (ConvertToGLenum(params[0]))
5763 {
5764 case GL_RED:
5765 case GL_GREEN:
5766 case GL_BLUE:
5767 case GL_ALPHA:
5768 case GL_ZERO:
5769 case GL_ONE:
5770 break;
5771
5772 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005773 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005774 return false;
5775 }
5776 break;
5777
5778 case GL_TEXTURE_BASE_LEVEL:
5779 if (params[0] < 0)
5780 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005781 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005782 return false;
5783 }
5784 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5785 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005786 context->handleError(InvalidOperation()
5787 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005788 return false;
5789 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005790 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5791 {
5792 context->handleError(InvalidOperation()
5793 << "Base level must be 0 for multisampled textures.");
5794 return false;
5795 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005796 break;
5797
5798 case GL_TEXTURE_MAX_LEVEL:
5799 if (params[0] < 0)
5800 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005801 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005802 return false;
5803 }
5804 break;
5805
5806 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5807 if (context->getClientVersion() < Version(3, 1))
5808 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005809 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005810 return false;
5811 }
5812 switch (ConvertToGLenum(params[0]))
5813 {
5814 case GL_DEPTH_COMPONENT:
5815 case GL_STENCIL_INDEX:
5816 break;
5817
5818 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005819 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005820 return false;
5821 }
5822 break;
5823
5824 case GL_TEXTURE_SRGB_DECODE_EXT:
5825 if (!ValidateTextureSRGBDecodeValue(context, params))
5826 {
5827 return false;
5828 }
5829 break;
5830
5831 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005832 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005833 return false;
5834 }
5835
5836 return true;
5837}
5838
5839template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5840template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5841
Jamie Madillc29968b2016-01-20 11:17:23 -05005842} // namespace gl