blob: 206762aa1b91c6ff072b858cd2c6d9d90bad5fd1 [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
1812 return true;
1813}
1814
Jamie Madill4928b7c2017-06-20 12:57:39 -04001815bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001816 GLint x,
1817 GLint y,
1818 GLsizei width,
1819 GLsizei height,
1820 GLenum format,
1821 GLenum type,
1822 GLsizei bufSize,
1823 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001824 GLsizei *columns,
1825 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001826 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001827{
1828 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001829 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001830 return false;
1831 }
1832
Geoff Lang62fce5b2016-09-30 10:46:35 -04001833 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001834 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001835 {
Geoff Langb1196682014-07-23 13:47:29 -04001836 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001837 }
1838
Geoff Lang62fce5b2016-09-30 10:46:35 -04001839 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001840 {
Geoff Langb1196682014-07-23 13:47:29 -04001841 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001842 }
1843
Jamie Madillc29968b2016-01-20 11:17:23 -05001844 return true;
1845}
1846
1847bool ValidateReadnPixelsEXT(Context *context,
1848 GLint x,
1849 GLint y,
1850 GLsizei width,
1851 GLsizei height,
1852 GLenum format,
1853 GLenum type,
1854 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001855 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001856{
1857 if (bufSize < 0)
1858 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001859 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001860 return false;
1861 }
1862
Geoff Lang62fce5b2016-09-30 10:46:35 -04001863 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001864 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001865}
Jamie Madill26e91952014-03-05 15:01:27 -05001866
Jamie Madill4928b7c2017-06-20 12:57:39 -04001867bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001868 GLint x,
1869 GLint y,
1870 GLsizei width,
1871 GLsizei height,
1872 GLenum format,
1873 GLenum type,
1874 GLsizei bufSize,
1875 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001876 GLsizei *columns,
1877 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001878 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001879{
1880 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001881 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001882 return false;
1883 }
1884
Geoff Lange93daba2017-03-30 13:54:40 -04001885 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1886 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001887 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001888 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001889 }
1890
Geoff Lang62fce5b2016-09-30 10:46:35 -04001891 if (!ValidateRobustBufferSize(context, bufSize, *length))
1892 {
1893 return false;
1894 }
1895
1896 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001897}
1898
Olli Etuaho41997e72016-03-10 13:38:39 +02001899bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001900{
1901 if (!context->getExtensions().occlusionQueryBoolean &&
1902 !context->getExtensions().disjointTimerQuery)
1903 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001904 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001905 return false;
1906 }
1907
Olli Etuaho41997e72016-03-10 13:38:39 +02001908 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001909}
1910
Olli Etuaho41997e72016-03-10 13:38:39 +02001911bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001912{
1913 if (!context->getExtensions().occlusionQueryBoolean &&
1914 !context->getExtensions().disjointTimerQuery)
1915 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001916 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001917 return false;
1918 }
1919
Olli Etuaho41997e72016-03-10 13:38:39 +02001920 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001921}
1922
1923bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001924{
1925 if (!ValidQueryType(context, target))
1926 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001927 context->handleError(InvalidEnum() << "Invalid query target");
Geoff Langb1196682014-07-23 13:47:29 -04001928 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001929 }
1930
1931 if (id == 0)
1932 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001933 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001934 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001935 }
1936
1937 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1938 // of zero, if the active query object name for <target> is non-zero (for the
1939 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1940 // the active query for either target is non-zero), if <id> is the name of an
1941 // existing query object whose type does not match <target>, or if <id> is the
1942 // active query object name for any query type, the error INVALID_OPERATION is
1943 // generated.
1944
1945 // Ensure no other queries are active
1946 // NOTE: If other queries than occlusion are supported, we will need to check
1947 // separately that:
1948 // a) The query ID passed is not the current active query for any target/type
1949 // b) There are no active queries for the requested target (and in the case
1950 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1951 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001952
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001953 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001954 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001955 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001956 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001957 }
1958
1959 Query *queryObject = context->getQuery(id, true, target);
1960
1961 // check that name was obtained with glGenQueries
1962 if (!queryObject)
1963 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001964 context->handleError(InvalidOperation() << "Invalid query id");
Geoff Langb1196682014-07-23 13:47:29 -04001965 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001966 }
1967
1968 // check for type mismatch
1969 if (queryObject->getType() != target)
1970 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001971 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001972 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001973 }
1974
1975 return true;
1976}
1977
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001978bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1979{
1980 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001981 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001982 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001983 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001984 return false;
1985 }
1986
1987 return ValidateBeginQueryBase(context, target, id);
1988}
1989
1990bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001991{
1992 if (!ValidQueryType(context, target))
1993 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001994 context->handleError(InvalidEnum() << "Invalid query target");
Geoff Langb1196682014-07-23 13:47:29 -04001995 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001996 }
1997
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001998 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001999
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002000 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002001 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002002 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04002003 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002004 }
2005
Jamie Madill45c785d2014-05-13 14:09:34 -04002006 return true;
2007}
2008
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002009bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2010{
2011 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002012 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002013 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002014 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002015 return false;
2016 }
2017
2018 return ValidateEndQueryBase(context, target);
2019}
2020
2021bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2022{
2023 if (!context->getExtensions().disjointTimerQuery)
2024 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002025 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002026 return false;
2027 }
2028
2029 if (target != GL_TIMESTAMP_EXT)
2030 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002031 context->handleError(InvalidEnum() << "Invalid query target");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002032 return false;
2033 }
2034
2035 Query *queryObject = context->getQuery(id, true, target);
2036 if (queryObject == nullptr)
2037 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002038 context->handleError(InvalidOperation() << "Invalid query id");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002039 return false;
2040 }
2041
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002042 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002043 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002044 context->handleError(InvalidOperation() << "Query is active");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002045 return false;
2046 }
2047
2048 return true;
2049}
2050
Geoff Lang2186c382016-10-14 10:54:54 -04002051bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002052{
Geoff Lang2186c382016-10-14 10:54:54 -04002053 if (numParams)
2054 {
2055 *numParams = 0;
2056 }
2057
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002058 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2059 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002060 context->handleError(InvalidEnum() << "Invalid query type");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002061 return false;
2062 }
2063
2064 switch (pname)
2065 {
2066 case GL_CURRENT_QUERY_EXT:
2067 if (target == GL_TIMESTAMP_EXT)
2068 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002069 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002070 return false;
2071 }
2072 break;
2073 case GL_QUERY_COUNTER_BITS_EXT:
2074 if (!context->getExtensions().disjointTimerQuery ||
2075 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2076 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002077 context->handleError(InvalidEnum() << "Invalid pname");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002078 return false;
2079 }
2080 break;
2081 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002082 context->handleError(InvalidEnum() << "Invalid pname");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002083 return false;
2084 }
2085
Geoff Lang2186c382016-10-14 10:54:54 -04002086 if (numParams)
2087 {
2088 // All queries return only one value
2089 *numParams = 1;
2090 }
2091
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002092 return true;
2093}
2094
2095bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2096{
2097 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002098 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002099 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002100 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002101 return false;
2102 }
2103
Geoff Lang2186c382016-10-14 10:54:54 -04002104 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002105}
2106
Geoff Lang2186c382016-10-14 10:54:54 -04002107bool ValidateGetQueryivRobustANGLE(Context *context,
2108 GLenum target,
2109 GLenum pname,
2110 GLsizei bufSize,
2111 GLsizei *length,
2112 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002113{
Geoff Lang2186c382016-10-14 10:54:54 -04002114 if (!ValidateRobustEntryPoint(context, bufSize))
2115 {
2116 return false;
2117 }
2118
2119 if (!ValidateGetQueryivBase(context, target, pname, length))
2120 {
2121 return false;
2122 }
2123
2124 if (!ValidateRobustBufferSize(context, bufSize, *length))
2125 {
2126 return false;
2127 }
2128
2129 return true;
2130}
2131
2132bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2133{
2134 if (numParams)
2135 {
2136 *numParams = 0;
2137 }
2138
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002139 Query *queryObject = context->getQuery(id, false, GL_NONE);
2140
2141 if (!queryObject)
2142 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002143 context->handleError(InvalidOperation() << "Query does not exist");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002144 return false;
2145 }
2146
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002147 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002148 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002149 context->handleError(InvalidOperation() << "Query currently active");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002150 return false;
2151 }
2152
2153 switch (pname)
2154 {
2155 case GL_QUERY_RESULT_EXT:
2156 case GL_QUERY_RESULT_AVAILABLE_EXT:
2157 break;
2158
2159 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002160 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002161 return false;
2162 }
2163
Geoff Lang2186c382016-10-14 10:54:54 -04002164 if (numParams)
2165 {
2166 *numParams = 1;
2167 }
2168
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002169 return true;
2170}
2171
2172bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2173{
2174 if (!context->getExtensions().disjointTimerQuery)
2175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002176 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002177 return false;
2178 }
Geoff Lang2186c382016-10-14 10:54:54 -04002179 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2180}
2181
2182bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2183 GLuint id,
2184 GLenum pname,
2185 GLsizei bufSize,
2186 GLsizei *length,
2187 GLint *params)
2188{
2189 if (!context->getExtensions().disjointTimerQuery)
2190 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002191 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04002192 return false;
2193 }
2194
2195 if (!ValidateRobustEntryPoint(context, bufSize))
2196 {
2197 return false;
2198 }
2199
2200 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2201 {
2202 return false;
2203 }
2204
2205 if (!ValidateRobustBufferSize(context, bufSize, *length))
2206 {
2207 return false;
2208 }
2209
2210 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002211}
2212
2213bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2214{
2215 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002216 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002217 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002218 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002219 return false;
2220 }
Geoff Lang2186c382016-10-14 10:54:54 -04002221 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2222}
2223
2224bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2225 GLuint id,
2226 GLenum pname,
2227 GLsizei bufSize,
2228 GLsizei *length,
2229 GLuint *params)
2230{
2231 if (!context->getExtensions().disjointTimerQuery &&
2232 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2233 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002234 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002235 return false;
2236 }
2237
2238 if (!ValidateRobustEntryPoint(context, bufSize))
2239 {
2240 return false;
2241 }
2242
2243 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2244 {
2245 return false;
2246 }
2247
2248 if (!ValidateRobustBufferSize(context, bufSize, *length))
2249 {
2250 return false;
2251 }
2252
2253 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002254}
2255
2256bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2257{
2258 if (!context->getExtensions().disjointTimerQuery)
2259 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002260 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002261 return false;
2262 }
Geoff Lang2186c382016-10-14 10:54:54 -04002263 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2264}
2265
2266bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2267 GLuint id,
2268 GLenum pname,
2269 GLsizei bufSize,
2270 GLsizei *length,
2271 GLint64 *params)
2272{
2273 if (!context->getExtensions().disjointTimerQuery)
2274 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002275 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002276 return false;
2277 }
2278
2279 if (!ValidateRobustEntryPoint(context, bufSize))
2280 {
2281 return false;
2282 }
2283
2284 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2285 {
2286 return false;
2287 }
2288
2289 if (!ValidateRobustBufferSize(context, bufSize, *length))
2290 {
2291 return false;
2292 }
2293
2294 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002295}
2296
2297bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2298{
2299 if (!context->getExtensions().disjointTimerQuery)
2300 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002301 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002302 return false;
2303 }
Geoff Lang2186c382016-10-14 10:54:54 -04002304 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2305}
2306
2307bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2308 GLuint id,
2309 GLenum pname,
2310 GLsizei bufSize,
2311 GLsizei *length,
2312 GLuint64 *params)
2313{
2314 if (!context->getExtensions().disjointTimerQuery)
2315 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002316 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002317 return false;
2318 }
2319
2320 if (!ValidateRobustEntryPoint(context, bufSize))
2321 {
2322 return false;
2323 }
2324
2325 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2326 {
2327 return false;
2328 }
2329
2330 if (!ValidateRobustBufferSize(context, bufSize, *length))
2331 {
2332 return false;
2333 }
2334
2335 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002336}
2337
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002338bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002339 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002340 GLuint program,
2341 GLint location,
2342 GLsizei count)
2343{
2344 // Check for ES31 program uniform entry points
2345 if (context->getClientVersion() < Version(3, 1))
2346 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002347 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002348 return false;
2349 }
2350
2351 const LinkedUniform *uniform = nullptr;
2352 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002353 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2354 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002355}
2356
Frank Henigmana98a6472017-02-02 21:38:32 -05002357bool ValidateProgramUniform1iv(gl::Context *context,
2358 GLuint program,
2359 GLint location,
2360 GLsizei count,
2361 const GLint *value)
2362{
2363 // Check for ES31 program uniform entry points
2364 if (context->getClientVersion() < Version(3, 1))
2365 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002366 context->handleError(InvalidOperation());
Frank Henigmana98a6472017-02-02 21:38:32 -05002367 return false;
2368 }
2369
2370 const LinkedUniform *uniform = nullptr;
2371 gl::Program *programObject = GetValidProgram(context, program);
2372 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2373 ValidateUniform1ivValue(context, uniform->type, count, value);
2374}
2375
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002376bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002377 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002378 GLuint program,
2379 GLint location,
2380 GLsizei count,
2381 GLboolean transpose)
2382{
2383 // Check for ES31 program uniform entry points
2384 if (context->getClientVersion() < Version(3, 1))
2385 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002386 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002387 return false;
2388 }
2389
2390 const LinkedUniform *uniform = nullptr;
2391 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002392 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2393 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002394}
2395
Jamie Madillc1d770e2017-04-13 17:31:24 -04002396bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002397{
2398 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002399 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002400 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002401 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002402 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002403 }
2404
Jamie Madill62d31cb2015-09-11 13:25:51 -04002405 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002406 gl::Program *programObject = context->getGLState().getProgram();
2407 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2408 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002409}
2410
Jamie Madillbe849e42017-05-02 15:49:00 -04002411bool ValidateUniform1iv(ValidationContext *context,
2412 GLint location,
2413 GLsizei count,
2414 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002415{
2416 const LinkedUniform *uniform = nullptr;
2417 gl::Program *programObject = context->getGLState().getProgram();
2418 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2419 ValidateUniform1ivValue(context, uniform->type, count, value);
2420}
2421
Jamie Madillc1d770e2017-04-13 17:31:24 -04002422bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002423 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002424 GLint location,
2425 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002426 GLboolean transpose)
2427{
2428 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002429 int rows = VariableRowCount(valueType);
2430 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002431 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002432 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002433 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002434 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002435 }
2436
Martin Radev1be913c2016-07-11 17:59:16 +03002437 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002438 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002439 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002440 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002441 }
2442
Jamie Madill62d31cb2015-09-11 13:25:51 -04002443 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002444 gl::Program *programObject = context->getGLState().getProgram();
2445 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2446 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002447}
2448
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002449bool ValidateStateQuery(ValidationContext *context,
2450 GLenum pname,
2451 GLenum *nativeType,
2452 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002453{
2454 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2455 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002456 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002457 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002458 }
2459
Jamie Madill0af26e12015-03-05 19:54:33 -05002460 const Caps &caps = context->getCaps();
2461
Jamie Madill893ab082014-05-16 16:56:10 -04002462 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2463 {
2464 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2465
Jamie Madill0af26e12015-03-05 19:54:33 -05002466 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002467 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002468 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002469 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002470 }
2471 }
2472
2473 switch (pname)
2474 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002475 case GL_TEXTURE_BINDING_2D:
2476 case GL_TEXTURE_BINDING_CUBE_MAP:
2477 case GL_TEXTURE_BINDING_3D:
2478 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002479 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002480 break;
2481 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2482 if (!context->getExtensions().eglStreamConsumerExternal &&
2483 !context->getExtensions().eglImageExternal)
2484 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002485 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2486 "nor GL_OES_EGL_image_external "
2487 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002488 return false;
2489 }
2490 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002491
He Yunchaoced53ae2016-11-29 15:00:51 +08002492 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2493 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002494 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002495 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2496 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002497 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002498 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002499 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002500 }
2501
Jamie Madill51f40ec2016-06-15 14:06:00 -04002502 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2503 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002504
2505 if (framebuffer->getReadBufferState() == GL_NONE)
2506 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002507 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Martin Radev138064f2016-07-15 12:03:41 +03002508 return false;
2509 }
2510
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002511 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002512 if (!attachment)
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 }
2518 break;
2519
He Yunchaoced53ae2016-11-29 15:00:51 +08002520 default:
2521 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002522 }
2523
2524 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002525 if (*numParams == 0)
2526 {
2527 return false;
2528 }
2529
2530 return true;
2531}
2532
2533bool ValidateRobustStateQuery(ValidationContext *context,
2534 GLenum pname,
2535 GLsizei bufSize,
2536 GLenum *nativeType,
2537 unsigned int *numParams)
2538{
2539 if (!ValidateRobustEntryPoint(context, bufSize))
2540 {
2541 return false;
2542 }
2543
2544 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2545 {
2546 return false;
2547 }
2548
2549 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002550 {
2551 return false;
2552 }
2553
2554 return true;
2555}
2556
Jamie Madillc29968b2016-01-20 11:17:23 -05002557bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2558 GLenum target,
2559 GLint level,
2560 GLenum internalformat,
2561 bool isSubImage,
2562 GLint xoffset,
2563 GLint yoffset,
2564 GLint zoffset,
2565 GLint x,
2566 GLint y,
2567 GLsizei width,
2568 GLsizei height,
2569 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002570 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002571{
Brandon Jones6cad5662017-06-14 13:25:13 -07002572 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002573 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002574 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2575 return false;
2576 }
2577
2578 if (width < 0 || height < 0)
2579 {
2580 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002581 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002582 }
2583
He Yunchaoced53ae2016-11-29 15:00:51 +08002584 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2585 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002586 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002587 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002588 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002589 }
2590
2591 if (border != 0)
2592 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002593 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002594 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002595 }
2596
2597 if (!ValidMipLevel(context, target, level))
2598 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002599 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002600 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002601 }
2602
Jamie Madill51f40ec2016-06-15 14:06:00 -04002603 const auto &state = context->getGLState();
2604 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002605 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002606 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002607 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002608 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002609 }
2610
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002611 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002612 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002613 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002614 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002615 }
2616
Martin Radev138064f2016-07-15 12:03:41 +03002617 if (readFramebuffer->getReadBufferState() == GL_NONE)
2618 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002619 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Martin Radev138064f2016-07-15 12:03:41 +03002620 return false;
2621 }
2622
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002623 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2624 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002625 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002626 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002627 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2628 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002629 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002630 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002631 return false;
2632 }
2633
Martin Radev04e2c3b2017-07-27 16:54:35 +03002634 // ANGLE_multiview spec, Revision 1:
2635 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2636 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2637 // is not NONE.
2638 if (source->getMultiviewLayout() != GL_NONE)
2639 {
2640 context->handleError(InvalidFramebufferOperation()
2641 << "The active read framebuffer object has multiview attachments.");
2642 return false;
2643 }
2644
Geoff Langaae65a42014-05-26 12:43:44 -04002645 const gl::Caps &caps = context->getCaps();
2646
Geoff Langaae65a42014-05-26 12:43:44 -04002647 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002648 switch (target)
2649 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002650 case GL_TEXTURE_2D:
2651 maxDimension = caps.max2DTextureSize;
2652 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002653
He Yunchaoced53ae2016-11-29 15:00:51 +08002654 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2655 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2656 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2657 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2658 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2659 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2660 maxDimension = caps.maxCubeMapTextureSize;
2661 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002662
He Yunchaoced53ae2016-11-29 15:00:51 +08002663 case GL_TEXTURE_2D_ARRAY:
2664 maxDimension = caps.max2DTextureSize;
2665 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002666
He Yunchaoced53ae2016-11-29 15:00:51 +08002667 case GL_TEXTURE_3D:
2668 maxDimension = caps.max3DTextureSize;
2669 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002670
He Yunchaoced53ae2016-11-29 15:00:51 +08002671 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002672 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002673 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002674 }
2675
Jamie Madillc29968b2016-01-20 11:17:23 -05002676 gl::Texture *texture =
2677 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002678 if (!texture)
2679 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002680 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002681 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002682 }
2683
Geoff Lang69cce582015-09-17 13:20:36 -04002684 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002685 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002686 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002687 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002688 }
2689
Geoff Langca271392017-04-05 12:30:00 -04002690 const gl::InternalFormat &formatInfo =
2691 gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002692
Geoff Lang966c9402017-04-18 12:38:27 -04002693 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002694 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002695 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002696 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002697 }
2698
2699 if (isSubImage)
2700 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002701 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2702 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2703 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002704 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002705 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002706 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002707 }
2708 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002709 else
2710 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002711 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002712 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002713 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002714 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002715 }
2716
Geoff Langeb66a6e2016-10-31 13:06:12 -04002717 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002718 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002719 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002720 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002721 }
2722
2723 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002724 if (static_cast<int>(width) > maxLevelDimension ||
2725 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002726 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002727 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002728 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002729 }
2730 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002731
Jamie Madill0c8abca2016-07-22 20:21:26 -04002732 if (textureFormatOut)
2733 {
2734 *textureFormatOut = texture->getFormat(target, level);
2735 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002736
2737 // Detect texture copying feedback loops for WebGL.
2738 if (context->getExtensions().webglCompatibility)
2739 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002740 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002741 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002742 context->handleError(InvalidOperation() << "Texture copying feedback loop formed "
2743 "between Framebuffer and specified "
2744 "Texture level.");
Jamie Madillf695a3a2017-01-11 17:36:35 -05002745 return false;
2746 }
2747 }
2748
Jamie Madill560a8d82014-05-21 13:06:20 -04002749 return true;
2750}
2751
Jiajia Qind9671222016-11-29 16:30:31 +08002752bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002753{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002754 switch (mode)
2755 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002756 case GL_POINTS:
2757 case GL_LINES:
2758 case GL_LINE_LOOP:
2759 case GL_LINE_STRIP:
2760 case GL_TRIANGLES:
2761 case GL_TRIANGLE_STRIP:
2762 case GL_TRIANGLE_FAN:
2763 break;
2764 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002765 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002766 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002767 }
2768
Jamie Madill250d33f2014-06-06 17:09:03 -04002769 if (count < 0)
2770 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002771 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002772 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002773 }
2774
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002775 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002776
Jamie Madill250d33f2014-06-06 17:09:03 -04002777 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002778 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002779 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002780 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002781 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002782 }
2783
Jamie Madillcbcde722017-01-06 14:50:00 -05002784 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2785 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002786 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002787 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
2788 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002789 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002790 const FramebufferAttachment *dsAttachment =
2791 framebuffer->getStencilOrDepthStencilAttachment();
2792 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002793 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002794 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002795
2796 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2797 bool differentWritemasks =
2798 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2799 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2800 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2801 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2802
2803 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002804 {
Jamie Madillcbcde722017-01-06 14:50:00 -05002805 if (!context->getExtensions().webglCompatibility)
2806 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002807 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2808 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002809 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002810 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002811 return false;
2812 }
Jamie Madillac528012014-06-20 13:21:23 -04002813 }
2814
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002815 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002816 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002817 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002818 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002819 }
2820
Geoff Lang7dd2e102014-11-10 15:19:26 -05002821 gl::Program *program = state.getProgram();
2822 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002823 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002824 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002825 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002826 }
2827
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002828 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002829 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002830 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002831 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002832 }
2833
Martin Radev7cf61662017-07-26 17:10:53 +03002834 if (context->getExtensions().multiview)
2835 {
Martin Radev7e69f762017-07-27 14:54:13 +03002836 const int programNumViews = program->getNumViews();
2837 const int framebufferNumViews = framebuffer->getNumViews();
2838 if (programNumViews != -1 && framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002839 {
2840 context->handleError(InvalidOperation() << "The number of views in the active program "
2841 "and draw framebuffer does not match.");
2842 return false;
2843 }
Martin Radev7e69f762017-07-27 14:54:13 +03002844
2845 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2846 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2847 framebufferNumViews > 1)
2848 {
2849 context->handleError(InvalidOperation()
2850 << "There is an active transform feedback object "
2851 "when the number of views in the active draw "
2852 "framebuffer is greater than 1.");
2853 return false;
2854 }
Martin Radev7cf61662017-07-26 17:10:53 +03002855 }
2856
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002857 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002858 for (unsigned int uniformBlockIndex = 0;
2859 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002860 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002861 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002862 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002863 const OffsetBindingPointer<Buffer> &uniformBuffer =
2864 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002865
Geoff Lang5d124a62015-09-15 13:03:27 -04002866 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002867 {
2868 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002869 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002870 InvalidOperation()
2871 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002872 return false;
2873 }
2874
Geoff Lang5d124a62015-09-15 13:03:27 -04002875 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002876 if (uniformBufferSize == 0)
2877 {
2878 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002879 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002880 }
2881
Jamie Madill62d31cb2015-09-11 13:25:51 -04002882 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002883 {
2884 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002885 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002886 InvalidOperation()
2887 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002888 return false;
2889 }
2890 }
2891
Geoff Lange0cff192017-05-30 13:04:56 -04002892 // Do some additonal WebGL-specific validation
Jamie Madilla4595b82017-01-11 17:36:34 -05002893 if (context->getExtensions().webglCompatibility)
2894 {
Geoff Lange0cff192017-05-30 13:04:56 -04002895 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002896 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2897 {
2898 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002899 InvalidOperation()
2900 << "Rendering feedback loop formed between Framebuffer and active Texture.");
Jamie Madilla4595b82017-01-11 17:36:34 -05002901 return false;
2902 }
Geoff Lange0cff192017-05-30 13:04:56 -04002903
Geoff Lang9ab5b822017-05-30 16:19:23 -04002904 // Detect that the vertex shader input types match the attribute types
2905 if (!ValidateVertexShaderAttributeTypeMatch(context))
2906 {
2907 return false;
2908 }
2909
Geoff Lange0cff192017-05-30 13:04:56 -04002910 // Detect that the color buffer types match the fragment shader output types
2911 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2912 {
2913 return false;
2914 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002915 }
2916
Jamie Madill250d33f2014-06-06 17:09:03 -04002917 // No-op if zero count
2918 return (count > 0);
2919}
2920
Jamie Madillc1d770e2017-04-13 17:31:24 -04002921bool ValidateDrawArraysCommon(ValidationContext *context,
2922 GLenum mode,
2923 GLint first,
2924 GLsizei count,
2925 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002926{
Jamie Madillfd716582014-06-06 17:09:04 -04002927 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002928 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002929 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002930 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002931 }
2932
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002933 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002934 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002935 if (curTransformFeedback && curTransformFeedback->isActive() &&
2936 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002937 {
2938 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002939 // that does not match the current transform feedback object's draw mode (if transform
2940 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002941 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002942 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002943 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002944 }
2945
Jiajia Qind9671222016-11-29 16:30:31 +08002946 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002947 {
2948 return false;
2949 }
2950
Corentin Wallez71168a02016-12-19 15:11:18 -08002951 // Check the computation of maxVertex doesn't overflow.
2952 // - first < 0 or count < 0 have been checked as an error condition
2953 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2954 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2955 ASSERT(count > 0 && first >= 0);
2956 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2957 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002958 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002959 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002960 return false;
2961 }
2962
Corentin Wallez71168a02016-12-19 15:11:18 -08002963 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002964 {
2965 return false;
2966 }
2967
2968 return true;
2969}
2970
He Yunchaoced53ae2016-11-29 15:00:51 +08002971bool ValidateDrawArraysInstanced(Context *context,
2972 GLenum mode,
2973 GLint first,
2974 GLsizei count,
2975 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002976{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002977 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
Geoff Lang87a93302014-09-16 13:29:43 -04002978}
2979
He Yunchaoced53ae2016-11-29 15:00:51 +08002980bool ValidateDrawArraysInstancedANGLE(Context *context,
2981 GLenum mode,
2982 GLint first,
2983 GLsizei count,
2984 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002985{
Corentin Wallez170efbf2017-05-02 13:45:01 -04002986 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002987 {
2988 return false;
2989 }
2990
Corentin Wallez0dc97812017-06-22 14:38:44 -04002991 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002992}
2993
Jiajia Qind9671222016-11-29 16:30:31 +08002994bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002995{
Jamie Madill250d33f2014-06-06 17:09:03 -04002996 switch (type)
2997 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002998 case GL_UNSIGNED_BYTE:
2999 case GL_UNSIGNED_SHORT:
3000 break;
3001 case GL_UNSIGNED_INT:
3002 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3003 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003004 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08003005 return false;
3006 }
3007 break;
3008 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003009 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08003010 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003011 }
3012
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003013 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003014
3015 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003016 if (curTransformFeedback && curTransformFeedback->isActive() &&
3017 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003018 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003019 // It is an invalid operation to call DrawElements, DrawRangeElements or
3020 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003021 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003022 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003023 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003024 }
3025
Jiajia Qind9671222016-11-29 16:30:31 +08003026 return true;
3027}
3028
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003029bool ValidateDrawElementsCommon(ValidationContext *context,
3030 GLenum mode,
3031 GLsizei count,
3032 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003033 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003034 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08003035{
3036 if (!ValidateDrawElementsBase(context, type))
3037 return false;
3038
3039 const State &state = context->getGLState();
3040
Corentin Wallez170efbf2017-05-02 13:45:01 -04003041 if (!ValidateDrawBase(context, mode, count))
3042 {
3043 return false;
3044 }
3045
Jamie Madill250d33f2014-06-06 17:09:03 -04003046 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003047 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003048 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003049 context->handleError(InvalidOperation() << "Index buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -04003050 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003051 }
3052
He Yunchaoced53ae2016-11-29 15:00:51 +08003053 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003054 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003055
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003056 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3057
3058 if (context->getExtensions().webglCompatibility)
3059 {
3060 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3061 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3062 {
3063 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3064 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3065 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003066 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003067 return false;
3068 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003069
3070 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3071 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3072 // error is generated.
3073 if (reinterpret_cast<intptr_t>(indices) < 0)
3074 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003075 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003076 return false;
3077 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003078 }
3079
3080 if (context->getExtensions().webglCompatibility ||
3081 !context->getGLState().areClientArraysEnabled())
3082 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003083 if (!elementArrayBuffer && count > 0)
3084 {
3085 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3086 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3087 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003088 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003089 return false;
3090 }
3091 }
3092
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003093 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003094 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003095 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003096 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003097 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3098 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3099 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3100 constexpr uint64_t kMaxTypeSize = 8;
3101 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3102 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3103 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003104
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003105 uint64_t typeSize = typeBytes;
3106 uint64_t elementCount = static_cast<uint64_t>(count);
3107 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3108
3109 // Doing the multiplication here is overflow-safe
3110 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3111
3112 // The offset can be any value, check for overflows
3113 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3114 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003115 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003116 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003117 return false;
3118 }
3119
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003120 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3121 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003122 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003123 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003124 return false;
3125 }
3126 }
3127 else if (!indices)
3128 {
3129 // This is an application error that would normally result in a crash,
3130 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003131 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04003132 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003133 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003134 }
3135
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003136 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill2b976812014-08-25 15:47:49 -04003137 // TODO: offer fast path, with disabled index validation.
3138 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003139 const auto &params = context->getParams<HasIndexRange>();
3140 const auto &indexRangeOpt = params.getIndexRange();
3141 if (!indexRangeOpt.valid())
Jamie Madill2b976812014-08-25 15:47:49 -04003142 {
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003143 // Unexpected error.
3144 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003145 }
3146
Jamie Madille79b1e12015-11-04 16:36:37 -05003147 // If we use an index greater than our maximum supported index range, return an error.
3148 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3149 // return an error if possible here.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003150 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
Jamie Madille79b1e12015-11-04 16:36:37 -05003151 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003152 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
Jamie Madille79b1e12015-11-04 16:36:37 -05003153 return false;
3154 }
3155
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003156 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
3157 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003158 {
3159 return false;
3160 }
3161
Geoff Lang3edfe032015-09-04 16:38:24 -04003162 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003163 return (indexRangeOpt.value().vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003164}
3165
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003166bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
3167 GLenum mode,
3168 GLsizei count,
3169 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003170 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003171 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003172{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003173 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003174}
3175
Geoff Lang3edfe032015-09-04 16:38:24 -04003176bool ValidateDrawElementsInstancedANGLE(Context *context,
3177 GLenum mode,
3178 GLsizei count,
3179 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003180 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003181 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003182{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003183 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003184 {
3185 return false;
3186 }
3187
Corentin Wallez0dc97812017-06-22 14:38:44 -04003188 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003189}
3190
He Yunchaoced53ae2016-11-29 15:00:51 +08003191bool ValidateFramebufferTextureBase(Context *context,
3192 GLenum target,
3193 GLenum attachment,
3194 GLuint texture,
3195 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003196{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003197 if (!ValidFramebufferTarget(target))
3198 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003199 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003200 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003201 }
3202
3203 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003204 {
3205 return false;
3206 }
3207
Jamie Madill55ec3b12014-07-03 10:38:57 -04003208 if (texture != 0)
3209 {
3210 gl::Texture *tex = context->getTexture(texture);
3211
Jamie Madillbe849e42017-05-02 15:49:00 -04003212 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003213 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003214 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003215 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003216 }
3217
3218 if (level < 0)
3219 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003220 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003221 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003222 }
3223 }
3224
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003225 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003226 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003227
Jamie Madill84115c92015-04-23 15:00:07 -04003228 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003229 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003230 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003231 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003232 }
3233
3234 return true;
3235}
3236
Geoff Langb1196682014-07-23 13:47:29 -04003237bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003238{
3239 if (program == 0)
3240 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003241 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003242 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003243 }
3244
Dian Xiang769769a2015-09-09 15:20:08 -07003245 gl::Program *programObject = GetValidProgram(context, program);
3246 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003247 {
3248 return false;
3249 }
3250
Jamie Madill0063c512014-08-25 15:47:53 -04003251 if (!programObject || !programObject->isLinked())
3252 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003253 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003254 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003255 }
3256
Geoff Lang7dd2e102014-11-10 15:19:26 -05003257 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003258 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003259 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003260 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003261 }
3262
Jamie Madill0063c512014-08-25 15:47:53 -04003263 return true;
3264}
3265
Geoff Langf41d0ee2016-10-07 13:04:23 -04003266static bool ValidateSizedGetUniform(Context *context,
3267 GLuint program,
3268 GLint location,
3269 GLsizei bufSize,
3270 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003271{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003272 if (length)
3273 {
3274 *length = 0;
3275 }
3276
Jamie Madill78f41802014-08-25 15:47:55 -04003277 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003278 {
Jamie Madill78f41802014-08-25 15:47:55 -04003279 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003280 }
3281
Geoff Langf41d0ee2016-10-07 13:04:23 -04003282 if (bufSize < 0)
3283 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003284 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003285 return false;
3286 }
3287
Jamie Madilla502c742014-08-28 17:19:13 -04003288 gl::Program *programObject = context->getProgram(program);
3289 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003290
Jamie Madill78f41802014-08-25 15:47:55 -04003291 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003292 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003293 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003294 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003295 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003296 context->handleError(InvalidOperation()
3297 << "bufSize of at least " << requiredBytes << " is required.");
Geoff Langb1196682014-07-23 13:47:29 -04003298 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003299 }
3300
Geoff Langf41d0ee2016-10-07 13:04:23 -04003301 if (length)
3302 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003303 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003304 }
3305
Jamie Madill0063c512014-08-25 15:47:53 -04003306 return true;
3307}
3308
He Yunchaoced53ae2016-11-29 15:00:51 +08003309bool ValidateGetnUniformfvEXT(Context *context,
3310 GLuint program,
3311 GLint location,
3312 GLsizei bufSize,
3313 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003314{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003315 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003316}
3317
He Yunchaoced53ae2016-11-29 15:00:51 +08003318bool ValidateGetnUniformivEXT(Context *context,
3319 GLuint program,
3320 GLint location,
3321 GLsizei bufSize,
3322 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003323{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003324 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3325}
3326
3327bool ValidateGetUniformfvRobustANGLE(Context *context,
3328 GLuint program,
3329 GLint location,
3330 GLsizei bufSize,
3331 GLsizei *length,
3332 GLfloat *params)
3333{
3334 if (!ValidateRobustEntryPoint(context, bufSize))
3335 {
3336 return false;
3337 }
3338
3339 // bufSize is validated in ValidateSizedGetUniform
3340 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3341}
3342
3343bool ValidateGetUniformivRobustANGLE(Context *context,
3344 GLuint program,
3345 GLint location,
3346 GLsizei bufSize,
3347 GLsizei *length,
3348 GLint *params)
3349{
3350 if (!ValidateRobustEntryPoint(context, bufSize))
3351 {
3352 return false;
3353 }
3354
3355 // bufSize is validated in ValidateSizedGetUniform
3356 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3357}
3358
3359bool ValidateGetUniformuivRobustANGLE(Context *context,
3360 GLuint program,
3361 GLint location,
3362 GLsizei bufSize,
3363 GLsizei *length,
3364 GLuint *params)
3365{
3366 if (!ValidateRobustEntryPoint(context, bufSize))
3367 {
3368 return false;
3369 }
3370
3371 if (context->getClientMajorVersion() < 3)
3372 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003373 context->handleError(InvalidOperation() << "Entry point requires at least OpenGL ES 3.0.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003374 return false;
3375 }
3376
3377 // bufSize is validated in ValidateSizedGetUniform
3378 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003379}
3380
He Yunchaoced53ae2016-11-29 15:00:51 +08003381bool ValidateDiscardFramebufferBase(Context *context,
3382 GLenum target,
3383 GLsizei numAttachments,
3384 const GLenum *attachments,
3385 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003386{
3387 if (numAttachments < 0)
3388 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003389 context->handleError(InvalidValue() << "numAttachments must not be less than zero");
Austin Kinross08332632015-05-05 13:35:47 -07003390 return false;
3391 }
3392
3393 for (GLsizei i = 0; i < numAttachments; ++i)
3394 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003395 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003396 {
3397 if (defaultFramebuffer)
3398 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003399 context->handleError(InvalidEnum()
3400 << "Invalid attachment when the default framebuffer is bound");
Austin Kinross08332632015-05-05 13:35:47 -07003401 return false;
3402 }
3403
3404 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003406 context->handleError(InvalidOperation() << "Requested color attachment is "
3407 "greater than the maximum supported "
3408 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003409 return false;
3410 }
3411 }
3412 else
3413 {
3414 switch (attachments[i])
3415 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003416 case GL_DEPTH_ATTACHMENT:
3417 case GL_STENCIL_ATTACHMENT:
3418 case GL_DEPTH_STENCIL_ATTACHMENT:
3419 if (defaultFramebuffer)
3420 {
3421 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003422 InvalidEnum()
3423 << "Invalid attachment when the default framebuffer is bound");
He Yunchaoced53ae2016-11-29 15:00:51 +08003424 return false;
3425 }
3426 break;
3427 case GL_COLOR:
3428 case GL_DEPTH:
3429 case GL_STENCIL:
3430 if (!defaultFramebuffer)
3431 {
3432 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003433 InvalidEnum()
3434 << "Invalid attachment when the default framebuffer is not bound");
He Yunchaoced53ae2016-11-29 15:00:51 +08003435 return false;
3436 }
3437 break;
3438 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003439 context->handleError(InvalidEnum() << "Invalid attachment");
Austin Kinross08332632015-05-05 13:35:47 -07003440 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003441 }
3442 }
3443 }
3444
3445 return true;
3446}
3447
Austin Kinross6ee1e782015-05-29 17:05:37 -07003448bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3449{
3450 // Note that debug marker calls must not set error state
3451
3452 if (length < 0)
3453 {
3454 return false;
3455 }
3456
3457 if (marker == nullptr)
3458 {
3459 return false;
3460 }
3461
3462 return true;
3463}
3464
3465bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3466{
3467 // Note that debug marker calls must not set error state
3468
3469 if (length < 0)
3470 {
3471 return false;
3472 }
3473
3474 if (length > 0 && marker == nullptr)
3475 {
3476 return false;
3477 }
3478
3479 return true;
3480}
3481
Geoff Langdcab33b2015-07-21 13:03:16 -04003482bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003483 GLenum target,
3484 egl::Image *image)
3485{
Geoff Langa8406172015-07-21 16:53:39 -04003486 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003488 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003489 return false;
3490 }
3491
3492 switch (target)
3493 {
3494 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003495 if (!context->getExtensions().eglImage)
3496 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003497 context->handleError(InvalidEnum()
3498 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003499 }
3500 break;
3501
3502 case GL_TEXTURE_EXTERNAL_OES:
3503 if (!context->getExtensions().eglImageExternal)
3504 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003505 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3506 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003507 }
Geoff Langa8406172015-07-21 16:53:39 -04003508 break;
3509
3510 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003511 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003512 return false;
3513 }
3514
Jamie Madill61e16b42017-06-19 11:13:23 -04003515 ASSERT(context->getCurrentDisplay());
3516 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003517 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003518 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003519 return false;
3520 }
3521
3522 if (image->getSamples() > 0)
3523 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003524 context->handleError(InvalidOperation()
3525 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003526 return false;
3527 }
3528
Geoff Langca271392017-04-05 12:30:00 -04003529 const TextureCaps &textureCaps =
3530 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003531 if (!textureCaps.texturable)
3532 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003533 context->handleError(InvalidOperation()
3534 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003535 return false;
3536 }
3537
Geoff Langdcab33b2015-07-21 13:03:16 -04003538 return true;
3539}
3540
3541bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003542 GLenum target,
3543 egl::Image *image)
3544{
Geoff Langa8406172015-07-21 16:53:39 -04003545 if (!context->getExtensions().eglImage)
3546 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003547 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003548 return false;
3549 }
3550
3551 switch (target)
3552 {
3553 case GL_RENDERBUFFER:
3554 break;
3555
3556 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003557 context->handleError(InvalidEnum() << "invalid renderbuffer target.");
Geoff Langa8406172015-07-21 16:53:39 -04003558 return false;
3559 }
3560
Jamie Madill61e16b42017-06-19 11:13:23 -04003561 ASSERT(context->getCurrentDisplay());
3562 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003563 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003564 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003565 return false;
3566 }
3567
Geoff Langca271392017-04-05 12:30:00 -04003568 const TextureCaps &textureCaps =
3569 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003570 if (!textureCaps.renderable)
3571 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003572 context->handleError(InvalidOperation()
3573 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003574 return false;
3575 }
3576
Geoff Langdcab33b2015-07-21 13:03:16 -04003577 return true;
3578}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003579
3580bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3581{
Geoff Lang36167ab2015-12-07 10:27:14 -05003582 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003583 {
3584 // The default VAO should always exist
3585 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003586 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003587 return false;
3588 }
3589
3590 return true;
3591}
3592
Geoff Langc5629752015-12-07 16:29:04 -05003593bool ValidateProgramBinaryBase(Context *context,
3594 GLuint program,
3595 GLenum binaryFormat,
3596 const void *binary,
3597 GLint length)
3598{
3599 Program *programObject = GetValidProgram(context, program);
3600 if (programObject == nullptr)
3601 {
3602 return false;
3603 }
3604
3605 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3606 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3607 programBinaryFormats.end())
3608 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003609 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003610 return false;
3611 }
3612
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003613 if (context->hasActiveTransformFeedback(program))
3614 {
3615 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003616 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3617 "is associated with an active transform "
3618 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003619 return false;
3620 }
3621
Geoff Langc5629752015-12-07 16:29:04 -05003622 return true;
3623}
3624
3625bool ValidateGetProgramBinaryBase(Context *context,
3626 GLuint program,
3627 GLsizei bufSize,
3628 GLsizei *length,
3629 GLenum *binaryFormat,
3630 void *binary)
3631{
3632 Program *programObject = GetValidProgram(context, program);
3633 if (programObject == nullptr)
3634 {
3635 return false;
3636 }
3637
3638 if (!programObject->isLinked())
3639 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003640 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003641 return false;
3642 }
3643
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003644 if (context->getCaps().programBinaryFormats.empty())
3645 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003646 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003647 return false;
3648 }
3649
Geoff Langc5629752015-12-07 16:29:04 -05003650 return true;
3651}
Jamie Madillc29968b2016-01-20 11:17:23 -05003652
Jamie Madillc29968b2016-01-20 11:17:23 -05003653bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3654{
3655 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3656 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3657 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003658 context->handleError(InvalidValue()
3659 << "n must be non-negative and no greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003660 return false;
3661 }
3662
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003663 ASSERT(context->getGLState().getDrawFramebuffer());
3664 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003665 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3666
3667 // This should come first before the check for the default frame buffer
3668 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3669 // rather than INVALID_OPERATION
3670 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3671 {
3672 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3673
3674 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003675 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3676 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003677 {
3678 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003679 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3680 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3681 // 3.1 is still a bit ambiguous about the error, but future specs are
3682 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003683 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003684 return false;
3685 }
3686 else if (bufs[colorAttachment] >= maxColorAttachment)
3687 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003688 context->handleError(InvalidOperation()
3689 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003690 return false;
3691 }
3692 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3693 frameBufferId != 0)
3694 {
3695 // INVALID_OPERATION-GL is bound to buffer and ith argument
3696 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003697 context->handleError(InvalidOperation()
3698 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003699 return false;
3700 }
3701 }
3702
3703 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3704 // and n is not 1 or bufs is bound to value other than BACK and NONE
3705 if (frameBufferId == 0)
3706 {
3707 if (n != 1)
3708 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003709 context->handleError(InvalidOperation()
3710 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003711 return false;
3712 }
3713
3714 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3715 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003716 context->handleError(
3717 InvalidOperation()
3718 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003719 return false;
3720 }
3721 }
3722
3723 return true;
3724}
3725
Geoff Lang496c02d2016-10-20 11:38:11 -07003726bool ValidateGetBufferPointervBase(Context *context,
3727 GLenum target,
3728 GLenum pname,
3729 GLsizei *length,
3730 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003731{
Geoff Lang496c02d2016-10-20 11:38:11 -07003732 if (length)
3733 {
3734 *length = 0;
3735 }
3736
3737 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3738 {
3739 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003740 InvalidOperation()
3741 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003742 return false;
3743 }
3744
Olli Etuaho4f667482016-03-30 15:56:35 +03003745 if (!ValidBufferTarget(context, target))
3746 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003747 context->handleError(InvalidEnum() << "Buffer target not valid: 0x" << std::hex
3748 << std::uppercase << target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003749 return false;
3750 }
3751
Geoff Lang496c02d2016-10-20 11:38:11 -07003752 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003753 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003754 case GL_BUFFER_MAP_POINTER:
3755 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003756
Geoff Lang496c02d2016-10-20 11:38:11 -07003757 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003758 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003759 return false;
3760 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003761
3762 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3763 // target bound to zero generate an INVALID_OPERATION error."
3764 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003765 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003766 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003767 context->handleError(InvalidOperation()
3768 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003769 return false;
3770 }
3771
Geoff Lang496c02d2016-10-20 11:38:11 -07003772 if (length)
3773 {
3774 *length = 1;
3775 }
3776
Olli Etuaho4f667482016-03-30 15:56:35 +03003777 return true;
3778}
3779
3780bool ValidateUnmapBufferBase(Context *context, GLenum target)
3781{
3782 if (!ValidBufferTarget(context, target))
3783 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003784 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003785 return false;
3786 }
3787
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003788 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003789
3790 if (buffer == nullptr || !buffer->isMapped())
3791 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003792 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003793 return false;
3794 }
3795
3796 return true;
3797}
3798
3799bool ValidateMapBufferRangeBase(Context *context,
3800 GLenum target,
3801 GLintptr offset,
3802 GLsizeiptr length,
3803 GLbitfield access)
3804{
3805 if (!ValidBufferTarget(context, target))
3806 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003807 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003808 return false;
3809 }
3810
Brandon Jones6cad5662017-06-14 13:25:13 -07003811 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003812 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003813 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3814 return false;
3815 }
3816
3817 if (length < 0)
3818 {
3819 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003820 return false;
3821 }
3822
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003823 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003824
3825 if (!buffer)
3826 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003827 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003828 return false;
3829 }
3830
3831 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003832 CheckedNumeric<size_t> checkedOffset(offset);
3833 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003834
Jamie Madille2e406c2016-06-02 13:04:10 -04003835 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003836 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003837 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003838 return false;
3839 }
3840
3841 // Check for invalid bits in the mask
3842 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3843 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3844 GL_MAP_UNSYNCHRONIZED_BIT;
3845
3846 if (access & ~(allAccessBits))
3847 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003848 context->handleError(InvalidValue()
3849 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003850 return false;
3851 }
3852
3853 if (length == 0)
3854 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003855 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003856 return false;
3857 }
3858
3859 if (buffer->isMapped())
3860 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003861 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003862 return false;
3863 }
3864
3865 // Check for invalid bit combinations
3866 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3867 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003868 context->handleError(InvalidOperation()
3869 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003870 return false;
3871 }
3872
3873 GLbitfield writeOnlyBits =
3874 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3875
3876 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3877 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003878 context->handleError(InvalidOperation()
3879 << "Invalid access bits when mapping buffer for reading: 0x"
3880 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003881 return false;
3882 }
3883
3884 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3885 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003886 context->handleError(
3887 InvalidOperation()
3888 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003889 return false;
3890 }
3891 return true;
3892}
3893
3894bool ValidateFlushMappedBufferRangeBase(Context *context,
3895 GLenum target,
3896 GLintptr offset,
3897 GLsizeiptr length)
3898{
Brandon Jones6cad5662017-06-14 13:25:13 -07003899 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003900 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003901 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3902 return false;
3903 }
3904
3905 if (length < 0)
3906 {
3907 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003908 return false;
3909 }
3910
3911 if (!ValidBufferTarget(context, target))
3912 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003913 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003914 return false;
3915 }
3916
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003917 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003918
3919 if (buffer == nullptr)
3920 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003921 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003922 return false;
3923 }
3924
3925 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3926 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003927 context->handleError(InvalidOperation()
3928 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003929 return false;
3930 }
3931
3932 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003933 CheckedNumeric<size_t> checkedOffset(offset);
3934 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003935
Jamie Madille2e406c2016-06-02 13:04:10 -04003936 if (!checkedSize.IsValid() ||
3937 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003938 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003939 context->handleError(InvalidValue()
3940 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003941 return false;
3942 }
3943
3944 return true;
3945}
3946
Olli Etuaho41997e72016-03-10 13:38:39 +02003947bool ValidateGenOrDelete(Context *context, GLint n)
3948{
3949 if (n < 0)
3950 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003951 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003952 return false;
3953 }
3954 return true;
3955}
3956
Geoff Langff5b2d52016-09-07 11:32:23 -04003957bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3958{
3959 if (!context->getExtensions().robustClientMemory)
3960 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003961 context->handleError(InvalidOperation()
3962 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003963 return false;
3964 }
3965
3966 if (bufSize < 0)
3967 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003968 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003969 return false;
3970 }
3971
3972 return true;
3973}
3974
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003975bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3976{
3977 if (bufSize < numParams)
3978 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003979 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3980 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003981 return false;
3982 }
3983
3984 return true;
3985}
3986
Jamie Madillbe849e42017-05-02 15:49:00 -04003987bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3988 GLenum target,
3989 GLenum attachment,
3990 GLenum pname,
3991 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003992{
Geoff Langff5b2d52016-09-07 11:32:23 -04003993 if (!ValidFramebufferTarget(target))
3994 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003995 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003996 return false;
3997 }
3998
3999 int clientVersion = context->getClientMajorVersion();
4000
4001 switch (pname)
4002 {
4003 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4004 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4005 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4006 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4007 break;
4008
Martin Radeve5285d22017-07-14 16:23:53 +03004009 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4010 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4011 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4012 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4013 if (clientVersion < 3 || !context->getExtensions().multiview)
4014 {
4015 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4016 return false;
4017 }
4018 break;
4019
Geoff Langff5b2d52016-09-07 11:32:23 -04004020 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4021 if (clientVersion < 3 && !context->getExtensions().sRGB)
4022 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004023 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004024 return false;
4025 }
4026 break;
4027
4028 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4029 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4030 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4031 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4032 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4033 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4034 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4035 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4036 if (clientVersion < 3)
4037 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004038 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004039 return false;
4040 }
4041 break;
4042
4043 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004044 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004045 return false;
4046 }
4047
4048 // Determine if the attachment is a valid enum
4049 switch (attachment)
4050 {
4051 case GL_BACK:
4052 case GL_FRONT:
4053 case GL_DEPTH:
4054 case GL_STENCIL:
4055 case GL_DEPTH_STENCIL_ATTACHMENT:
4056 if (clientVersion < 3)
4057 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004058 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004059 return false;
4060 }
4061 break;
4062
4063 case GL_DEPTH_ATTACHMENT:
4064 case GL_STENCIL_ATTACHMENT:
4065 break;
4066
4067 default:
4068 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4069 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4070 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004071 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004072 return false;
4073 }
4074 break;
4075 }
4076
4077 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4078 ASSERT(framebuffer);
4079
4080 if (framebuffer->id() == 0)
4081 {
4082 if (clientVersion < 3)
4083 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004084 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004085 return false;
4086 }
4087
4088 switch (attachment)
4089 {
4090 case GL_BACK:
4091 case GL_DEPTH:
4092 case GL_STENCIL:
4093 break;
4094
4095 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004096 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FramebufferInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004097 return false;
4098 }
4099 }
4100 else
4101 {
4102 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4103 {
4104 // Valid attachment query
4105 }
4106 else
4107 {
4108 switch (attachment)
4109 {
4110 case GL_DEPTH_ATTACHMENT:
4111 case GL_STENCIL_ATTACHMENT:
4112 break;
4113
4114 case GL_DEPTH_STENCIL_ATTACHMENT:
4115 if (!framebuffer->hasValidDepthStencil())
4116 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004117 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004118 return false;
4119 }
4120 break;
4121
4122 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004123 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FramebufferInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004124 return false;
4125 }
4126 }
4127 }
4128
4129 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4130 if (attachmentObject)
4131 {
4132 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4133 attachmentObject->type() == GL_TEXTURE ||
4134 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4135
4136 switch (pname)
4137 {
4138 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4139 if (attachmentObject->type() != GL_RENDERBUFFER &&
4140 attachmentObject->type() != GL_TEXTURE)
4141 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004142 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004143 return false;
4144 }
4145 break;
4146
4147 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4148 if (attachmentObject->type() != GL_TEXTURE)
4149 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004150 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004151 return false;
4152 }
4153 break;
4154
4155 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4156 if (attachmentObject->type() != GL_TEXTURE)
4157 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004158 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004159 return false;
4160 }
4161 break;
4162
4163 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4164 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4165 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004166 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FramebufferInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004167 return false;
4168 }
4169 break;
4170
4171 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4172 if (attachmentObject->type() != GL_TEXTURE)
4173 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004174 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004175 return false;
4176 }
4177 break;
4178
4179 default:
4180 break;
4181 }
4182 }
4183 else
4184 {
4185 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4186 // is NONE, then querying any other pname will generate INVALID_ENUM.
4187
4188 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4189 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4190 // INVALID_OPERATION for all other pnames
4191
4192 switch (pname)
4193 {
4194 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4195 break;
4196
4197 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4198 if (clientVersion < 3)
4199 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004200 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
4201 InvalidRenderbufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004202 return false;
4203 }
4204 break;
4205
4206 default:
4207 if (clientVersion < 3)
4208 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004209 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
4210 InvalidRenderbufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004211 return false;
4212 }
4213 else
4214 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004215 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
4216 InvalidRenderbufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004217 return false;
4218 }
4219 }
4220 }
4221
Martin Radeve5285d22017-07-14 16:23:53 +03004222 if (numParams)
4223 {
4224 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4225 {
4226 // Only when the viewport offsets are queried we can have a varying number of output
4227 // parameters.
4228 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4229 *numParams = numViews * 2;
4230 }
4231 else
4232 {
4233 // For all other queries we can have only one output parameter.
4234 *numParams = 1;
4235 }
4236 }
4237
Geoff Langff5b2d52016-09-07 11:32:23 -04004238 return true;
4239}
4240
4241bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4242 GLenum target,
4243 GLenum attachment,
4244 GLenum pname,
4245 GLsizei bufSize,
4246 GLsizei *numParams)
4247{
4248 if (!ValidateRobustEntryPoint(context, bufSize))
4249 {
4250 return false;
4251 }
4252
Jamie Madillbe849e42017-05-02 15:49:00 -04004253 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4254 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004255 {
4256 return false;
4257 }
4258
4259 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4260 {
4261 return false;
4262 }
4263
4264 return true;
4265}
4266
Geoff Langff5b2d52016-09-07 11:32:23 -04004267bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4268 GLenum target,
4269 GLenum pname,
4270 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004271 GLsizei *length,
4272 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004273{
4274 if (!ValidateRobustEntryPoint(context, bufSize))
4275 {
4276 return false;
4277 }
4278
Geoff Langebebe1c2016-10-14 12:01:31 -04004279 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004280 {
4281 return false;
4282 }
4283
Geoff Langebebe1c2016-10-14 12:01:31 -04004284 if (!ValidateRobustBufferSize(context, bufSize, *length))
4285 {
4286 return false;
4287 }
4288
4289 return true;
4290}
4291
4292bool ValidateGetBufferParameteri64v(ValidationContext *context,
4293 GLenum target,
4294 GLenum pname,
4295 GLint64 *params)
4296{
4297 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4298}
4299
4300bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4301 GLenum target,
4302 GLenum pname,
4303 GLsizei bufSize,
4304 GLsizei *length,
4305 GLint64 *params)
4306{
4307 if (!ValidateRobustEntryPoint(context, bufSize))
4308 {
4309 return false;
4310 }
4311
4312 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4313 {
4314 return false;
4315 }
4316
4317 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004318 {
4319 return false;
4320 }
4321
4322 return true;
4323}
4324
Jamie Madillbe849e42017-05-02 15:49:00 -04004325bool ValidateGetProgramivBase(ValidationContext *context,
4326 GLuint program,
4327 GLenum pname,
4328 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004329{
4330 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004331 if (numParams)
4332 {
4333 *numParams = 1;
4334 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004335
4336 Program *programObject = GetValidProgram(context, program);
4337 if (!programObject)
4338 {
4339 return false;
4340 }
4341
4342 switch (pname)
4343 {
4344 case GL_DELETE_STATUS:
4345 case GL_LINK_STATUS:
4346 case GL_VALIDATE_STATUS:
4347 case GL_INFO_LOG_LENGTH:
4348 case GL_ATTACHED_SHADERS:
4349 case GL_ACTIVE_ATTRIBUTES:
4350 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4351 case GL_ACTIVE_UNIFORMS:
4352 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4353 break;
4354
4355 case GL_PROGRAM_BINARY_LENGTH:
4356 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4357 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004358 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4359 "requires GL_OES_get_program_binary or "
4360 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004361 return false;
4362 }
4363 break;
4364
4365 case GL_ACTIVE_UNIFORM_BLOCKS:
4366 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4367 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4368 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4369 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4370 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4371 if (context->getClientMajorVersion() < 3)
4372 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004373 context->handleError(InvalidEnum() << "Querying requires at least ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004374 return false;
4375 }
4376 break;
4377
Yunchao He61afff12017-03-14 15:34:03 +08004378 case GL_PROGRAM_SEPARABLE:
4379 if (context->getClientVersion() < Version(3, 1))
4380 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004381 context->handleError(InvalidEnum() << "Querying requires at least ES 3.1.");
Yunchao He61afff12017-03-14 15:34:03 +08004382 return false;
4383 }
4384 break;
4385
Geoff Langff5b2d52016-09-07 11:32:23 -04004386 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004387 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004388 return false;
4389 }
4390
4391 return true;
4392}
4393
4394bool ValidateGetProgramivRobustANGLE(Context *context,
4395 GLuint program,
4396 GLenum pname,
4397 GLsizei bufSize,
4398 GLsizei *numParams)
4399{
4400 if (!ValidateRobustEntryPoint(context, bufSize))
4401 {
4402 return false;
4403 }
4404
Jamie Madillbe849e42017-05-02 15:49:00 -04004405 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004406 {
4407 return false;
4408 }
4409
4410 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4411 {
4412 return false;
4413 }
4414
4415 return true;
4416}
4417
Geoff Lang740d9022016-10-07 11:20:52 -04004418bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4419 GLenum target,
4420 GLenum pname,
4421 GLsizei bufSize,
4422 GLsizei *length,
4423 GLint *params)
4424{
4425 if (!ValidateRobustEntryPoint(context, bufSize))
4426 {
4427 return false;
4428 }
4429
4430 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4431 {
4432 return false;
4433 }
4434
4435 if (!ValidateRobustBufferSize(context, bufSize, *length))
4436 {
4437 return false;
4438 }
4439
4440 return true;
4441}
4442
Geoff Langd7d0ed32016-10-07 11:33:51 -04004443bool ValidateGetShaderivRobustANGLE(Context *context,
4444 GLuint shader,
4445 GLenum pname,
4446 GLsizei bufSize,
4447 GLsizei *length,
4448 GLint *params)
4449{
4450 if (!ValidateRobustEntryPoint(context, bufSize))
4451 {
4452 return false;
4453 }
4454
4455 if (!ValidateGetShaderivBase(context, shader, pname, length))
4456 {
4457 return false;
4458 }
4459
4460 if (!ValidateRobustBufferSize(context, bufSize, *length))
4461 {
4462 return false;
4463 }
4464
4465 return true;
4466}
4467
Geoff Langc1984ed2016-10-07 12:41:00 -04004468bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4469 GLenum target,
4470 GLenum pname,
4471 GLsizei bufSize,
4472 GLsizei *length,
4473 GLfloat *params)
4474{
4475 if (!ValidateRobustEntryPoint(context, bufSize))
4476 {
4477 return false;
4478 }
4479
4480 if (!ValidateGetTexParameterBase(context, target, pname, length))
4481 {
4482 return false;
4483 }
4484
4485 if (!ValidateRobustBufferSize(context, bufSize, *length))
4486 {
4487 return false;
4488 }
4489
4490 return true;
4491}
4492
Geoff Langc1984ed2016-10-07 12:41:00 -04004493bool ValidateGetTexParameterivRobustANGLE(Context *context,
4494 GLenum target,
4495 GLenum pname,
4496 GLsizei bufSize,
4497 GLsizei *length,
4498 GLint *params)
4499{
4500 if (!ValidateRobustEntryPoint(context, bufSize))
4501 {
4502 return false;
4503 }
4504
4505 if (!ValidateGetTexParameterBase(context, target, pname, length))
4506 {
4507 return false;
4508 }
4509
4510 if (!ValidateRobustBufferSize(context, bufSize, *length))
4511 {
4512 return false;
4513 }
4514
4515 return true;
4516}
4517
Geoff Langc1984ed2016-10-07 12:41:00 -04004518bool ValidateTexParameterfvRobustANGLE(Context *context,
4519 GLenum target,
4520 GLenum pname,
4521 GLsizei bufSize,
4522 const GLfloat *params)
4523{
4524 if (!ValidateRobustEntryPoint(context, bufSize))
4525 {
4526 return false;
4527 }
4528
4529 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4530}
4531
Geoff Langc1984ed2016-10-07 12:41:00 -04004532bool ValidateTexParameterivRobustANGLE(Context *context,
4533 GLenum target,
4534 GLenum pname,
4535 GLsizei bufSize,
4536 const GLint *params)
4537{
4538 if (!ValidateRobustEntryPoint(context, bufSize))
4539 {
4540 return false;
4541 }
4542
4543 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4544}
4545
4546bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4547{
4548 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4549}
4550
4551bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4552 GLuint sampler,
4553 GLenum pname,
4554 GLuint bufSize,
4555 GLsizei *length,
4556 GLfloat *params)
4557{
4558 if (!ValidateRobustEntryPoint(context, bufSize))
4559 {
4560 return false;
4561 }
4562
4563 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4564 {
4565 return false;
4566 }
4567
4568 if (!ValidateRobustBufferSize(context, bufSize, *length))
4569 {
4570 return false;
4571 }
4572
4573 return true;
4574}
4575
4576bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4577{
4578 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4579}
4580
4581bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4582 GLuint sampler,
4583 GLenum pname,
4584 GLuint bufSize,
4585 GLsizei *length,
4586 GLint *params)
4587{
4588 if (!ValidateRobustEntryPoint(context, bufSize))
4589 {
4590 return false;
4591 }
4592
4593 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4594 {
4595 return false;
4596 }
4597
4598 if (!ValidateRobustBufferSize(context, bufSize, *length))
4599 {
4600 return false;
4601 }
4602
4603 return true;
4604}
4605
4606bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4607{
4608 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4609}
4610
4611bool ValidateSamplerParameterfv(Context *context,
4612 GLuint sampler,
4613 GLenum pname,
4614 const GLfloat *params)
4615{
4616 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4617}
4618
4619bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4620 GLuint sampler,
4621 GLenum pname,
4622 GLsizei bufSize,
4623 const GLfloat *params)
4624{
4625 if (!ValidateRobustEntryPoint(context, bufSize))
4626 {
4627 return false;
4628 }
4629
4630 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4631}
4632
4633bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4634{
4635 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4636}
4637
4638bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4639{
4640 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4641}
4642
4643bool ValidateSamplerParameterivRobustANGLE(Context *context,
4644 GLuint sampler,
4645 GLenum pname,
4646 GLsizei bufSize,
4647 const GLint *params)
4648{
4649 if (!ValidateRobustEntryPoint(context, bufSize))
4650 {
4651 return false;
4652 }
4653
4654 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4655}
4656
Geoff Lang0b031062016-10-13 14:30:04 -04004657bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4658 GLuint index,
4659 GLenum pname,
4660 GLsizei bufSize,
4661 GLsizei *length,
4662 GLfloat *params)
4663{
4664 if (!ValidateRobustEntryPoint(context, bufSize))
4665 {
4666 return false;
4667 }
4668
4669 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4670 {
4671 return false;
4672 }
4673
4674 if (!ValidateRobustBufferSize(context, bufSize, *length))
4675 {
4676 return false;
4677 }
4678
4679 return true;
4680}
4681
Geoff Lang0b031062016-10-13 14:30:04 -04004682bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4683 GLuint index,
4684 GLenum pname,
4685 GLsizei bufSize,
4686 GLsizei *length,
4687 GLint *params)
4688{
4689 if (!ValidateRobustEntryPoint(context, bufSize))
4690 {
4691 return false;
4692 }
4693
4694 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4695 {
4696 return false;
4697 }
4698
4699 if (!ValidateRobustBufferSize(context, bufSize, *length))
4700 {
4701 return false;
4702 }
4703
4704 return true;
4705}
4706
Geoff Lang0b031062016-10-13 14:30:04 -04004707bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4708 GLuint index,
4709 GLenum pname,
4710 GLsizei bufSize,
4711 GLsizei *length,
4712 void **pointer)
4713{
4714 if (!ValidateRobustEntryPoint(context, bufSize))
4715 {
4716 return false;
4717 }
4718
4719 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4720 {
4721 return false;
4722 }
4723
4724 if (!ValidateRobustBufferSize(context, bufSize, *length))
4725 {
4726 return false;
4727 }
4728
4729 return true;
4730}
4731
4732bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
4733{
4734 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4735}
4736
4737bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4738 GLuint index,
4739 GLenum pname,
4740 GLsizei bufSize,
4741 GLsizei *length,
4742 GLint *params)
4743{
4744 if (!ValidateRobustEntryPoint(context, bufSize))
4745 {
4746 return false;
4747 }
4748
4749 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4750 {
4751 return false;
4752 }
4753
4754 if (!ValidateRobustBufferSize(context, bufSize, *length))
4755 {
4756 return false;
4757 }
4758
4759 return true;
4760}
4761
4762bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
4763{
4764 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4765}
4766
4767bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4768 GLuint index,
4769 GLenum pname,
4770 GLsizei bufSize,
4771 GLsizei *length,
4772 GLuint *params)
4773{
4774 if (!ValidateRobustEntryPoint(context, bufSize))
4775 {
4776 return false;
4777 }
4778
4779 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4780 {
4781 return false;
4782 }
4783
4784 if (!ValidateRobustBufferSize(context, bufSize, *length))
4785 {
4786 return false;
4787 }
4788
4789 return true;
4790}
4791
Geoff Lang6899b872016-10-14 11:30:13 -04004792bool ValidateGetActiveUniformBlockiv(Context *context,
4793 GLuint program,
4794 GLuint uniformBlockIndex,
4795 GLenum pname,
4796 GLint *params)
4797{
4798 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
4799}
4800
4801bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4802 GLuint program,
4803 GLuint uniformBlockIndex,
4804 GLenum pname,
4805 GLsizei bufSize,
4806 GLsizei *length,
4807 GLint *params)
4808{
4809 if (!ValidateRobustEntryPoint(context, bufSize))
4810 {
4811 return false;
4812 }
4813
4814 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4815 {
4816 return false;
4817 }
4818
4819 if (!ValidateRobustBufferSize(context, bufSize, *length))
4820 {
4821 return false;
4822 }
4823
4824 return true;
4825}
4826
Geoff Lang0a9661f2016-10-20 10:59:20 -07004827bool ValidateGetInternalFormativ(Context *context,
4828 GLenum target,
4829 GLenum internalformat,
4830 GLenum pname,
4831 GLsizei bufSize,
4832 GLint *params)
4833{
4834 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4835 nullptr);
4836}
4837
4838bool ValidateGetInternalFormativRobustANGLE(Context *context,
4839 GLenum target,
4840 GLenum internalformat,
4841 GLenum pname,
4842 GLsizei bufSize,
4843 GLsizei *length,
4844 GLint *params)
4845{
4846 if (!ValidateRobustEntryPoint(context, bufSize))
4847 {
4848 return false;
4849 }
4850
4851 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4852 {
4853 return false;
4854 }
4855
4856 if (!ValidateRobustBufferSize(context, bufSize, *length))
4857 {
4858 return false;
4859 }
4860
4861 return true;
4862}
4863
Shao80957d92017-02-20 21:25:59 +08004864bool ValidateVertexFormatBase(ValidationContext *context,
4865 GLuint attribIndex,
4866 GLint size,
4867 GLenum type,
4868 GLboolean pureInteger)
4869{
4870 const Caps &caps = context->getCaps();
4871 if (attribIndex >= caps.maxVertexAttributes)
4872 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004873 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Shao80957d92017-02-20 21:25:59 +08004874 return false;
4875 }
4876
4877 if (size < 1 || size > 4)
4878 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004879 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004880 return false;
Shao80957d92017-02-20 21:25:59 +08004881 }
4882
4883 switch (type)
4884 {
4885 case GL_BYTE:
4886 case GL_UNSIGNED_BYTE:
4887 case GL_SHORT:
4888 case GL_UNSIGNED_SHORT:
4889 break;
4890
4891 case GL_INT:
4892 case GL_UNSIGNED_INT:
4893 if (context->getClientMajorVersion() < 3)
4894 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004895 context->handleError(InvalidEnum()
4896 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004897 return false;
4898 }
4899 break;
4900
4901 case GL_FIXED:
4902 case GL_FLOAT:
4903 if (pureInteger)
4904 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004905 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004906 return false;
4907 }
4908 break;
4909
4910 case GL_HALF_FLOAT:
4911 if (context->getClientMajorVersion() < 3)
4912 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004913 context->handleError(InvalidEnum()
4914 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004915 return false;
4916 }
4917 if (pureInteger)
4918 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004919 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004920 return false;
4921 }
4922 break;
4923
4924 case GL_INT_2_10_10_10_REV:
4925 case GL_UNSIGNED_INT_2_10_10_10_REV:
4926 if (context->getClientMajorVersion() < 3)
4927 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004928 context->handleError(InvalidEnum()
4929 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004930 return false;
4931 }
4932 if (pureInteger)
4933 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004934 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004935 return false;
4936 }
4937 if (size != 4)
4938 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004939 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4940 "UNSIGNED_INT_2_10_10_10_REV and "
4941 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004942 return false;
4943 }
4944 break;
4945
4946 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004947 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004948 return false;
4949 }
4950
4951 return true;
4952}
4953
Geoff Lang76e65652017-03-27 14:58:02 -04004954// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4955// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4956// specified clear value and the type of a buffer that is being cleared generates an
4957// INVALID_OPERATION error instead of producing undefined results
4958bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4959 GLint drawbuffer,
4960 const GLenum *validComponentTypes,
4961 size_t validComponentTypeCount)
4962{
4963 const FramebufferAttachment *attachment =
4964 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4965 if (attachment)
4966 {
4967 GLenum componentType = attachment->getFormat().info->componentType;
4968 const GLenum *end = validComponentTypes + validComponentTypeCount;
4969 if (std::find(validComponentTypes, end, componentType) == end)
4970 {
4971 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004972 InvalidOperation()
4973 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004974 return false;
4975 }
4976 }
4977
4978 return true;
4979}
4980
Corentin Wallezb2931602017-04-11 15:58:57 -04004981bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4982 GLsizei imageSize,
4983 GLsizei dataSize)
4984{
4985 if (!ValidateRobustEntryPoint(context, dataSize))
4986 {
4987 return false;
4988 }
4989
4990 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
4991 if (pixelUnpackBuffer == nullptr)
4992 {
4993 if (dataSize < imageSize)
4994 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004995 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004996 }
4997 }
4998 return true;
4999}
5000
Jamie Madillbe849e42017-05-02 15:49:00 -04005001bool ValidateGetBufferParameterBase(ValidationContext *context,
5002 GLenum target,
5003 GLenum pname,
5004 bool pointerVersion,
5005 GLsizei *numParams)
5006{
5007 if (numParams)
5008 {
5009 *numParams = 0;
5010 }
5011
5012 if (!ValidBufferTarget(context, target))
5013 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005014 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005015 return false;
5016 }
5017
5018 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5019 if (!buffer)
5020 {
5021 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005022 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005023 return false;
5024 }
5025
5026 const Extensions &extensions = context->getExtensions();
5027
5028 switch (pname)
5029 {
5030 case GL_BUFFER_USAGE:
5031 case GL_BUFFER_SIZE:
5032 break;
5033
5034 case GL_BUFFER_ACCESS_OES:
5035 if (!extensions.mapBuffer)
5036 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005037 context->handleError(InvalidEnum()
5038 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005039 return false;
5040 }
5041 break;
5042
5043 case GL_BUFFER_MAPPED:
5044 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5045 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5046 !extensions.mapBufferRange)
5047 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005048 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5049 "GL_OES_mapbuffer or "
5050 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005051 return false;
5052 }
5053 break;
5054
5055 case GL_BUFFER_MAP_POINTER:
5056 if (!pointerVersion)
5057 {
5058 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005059 InvalidEnum()
5060 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005061 return false;
5062 }
5063 break;
5064
5065 case GL_BUFFER_ACCESS_FLAGS:
5066 case GL_BUFFER_MAP_OFFSET:
5067 case GL_BUFFER_MAP_LENGTH:
5068 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5069 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005070 context->handleError(InvalidEnum()
5071 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005072 return false;
5073 }
5074 break;
5075
5076 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005077 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005078 return false;
5079 }
5080
5081 // All buffer parameter queries return one value.
5082 if (numParams)
5083 {
5084 *numParams = 1;
5085 }
5086
5087 return true;
5088}
5089
5090bool ValidateGetRenderbufferParameterivBase(Context *context,
5091 GLenum target,
5092 GLenum pname,
5093 GLsizei *length)
5094{
5095 if (length)
5096 {
5097 *length = 0;
5098 }
5099
5100 if (target != GL_RENDERBUFFER)
5101 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005102 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005103 return false;
5104 }
5105
5106 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5107 if (renderbuffer == nullptr)
5108 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005109 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005110 return false;
5111 }
5112
5113 switch (pname)
5114 {
5115 case GL_RENDERBUFFER_WIDTH:
5116 case GL_RENDERBUFFER_HEIGHT:
5117 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5118 case GL_RENDERBUFFER_RED_SIZE:
5119 case GL_RENDERBUFFER_GREEN_SIZE:
5120 case GL_RENDERBUFFER_BLUE_SIZE:
5121 case GL_RENDERBUFFER_ALPHA_SIZE:
5122 case GL_RENDERBUFFER_DEPTH_SIZE:
5123 case GL_RENDERBUFFER_STENCIL_SIZE:
5124 break;
5125
5126 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5127 if (!context->getExtensions().framebufferMultisample)
5128 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005129 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005130 return false;
5131 }
5132 break;
5133
5134 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005135 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005136 return false;
5137 }
5138
5139 if (length)
5140 {
5141 *length = 1;
5142 }
5143 return true;
5144}
5145
5146bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5147{
5148 if (length)
5149 {
5150 *length = 0;
5151 }
5152
5153 if (GetValidShader(context, shader) == nullptr)
5154 {
5155 return false;
5156 }
5157
5158 switch (pname)
5159 {
5160 case GL_SHADER_TYPE:
5161 case GL_DELETE_STATUS:
5162 case GL_COMPILE_STATUS:
5163 case GL_INFO_LOG_LENGTH:
5164 case GL_SHADER_SOURCE_LENGTH:
5165 break;
5166
5167 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5168 if (!context->getExtensions().translatedShaderSource)
5169 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005170 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005171 return false;
5172 }
5173 break;
5174
5175 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005176 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005177 return false;
5178 }
5179
5180 if (length)
5181 {
5182 *length = 1;
5183 }
5184 return true;
5185}
5186
5187bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
5188{
5189 if (length)
5190 {
5191 *length = 0;
5192 }
5193
5194 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5195 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005196 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005197 return false;
5198 }
5199
5200 if (context->getTargetTexture(target) == nullptr)
5201 {
5202 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005203 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005204 return false;
5205 }
5206
5207 switch (pname)
5208 {
5209 case GL_TEXTURE_MAG_FILTER:
5210 case GL_TEXTURE_MIN_FILTER:
5211 case GL_TEXTURE_WRAP_S:
5212 case GL_TEXTURE_WRAP_T:
5213 break;
5214
5215 case GL_TEXTURE_USAGE_ANGLE:
5216 if (!context->getExtensions().textureUsage)
5217 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005218 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005219 return false;
5220 }
5221 break;
5222
5223 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5224 if (!context->getExtensions().textureFilterAnisotropic)
5225 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005226 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005227 return false;
5228 }
5229 break;
5230
5231 case GL_TEXTURE_IMMUTABLE_FORMAT:
5232 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5233 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005234 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005235 return false;
5236 }
5237 break;
5238
5239 case GL_TEXTURE_WRAP_R:
5240 case GL_TEXTURE_IMMUTABLE_LEVELS:
5241 case GL_TEXTURE_SWIZZLE_R:
5242 case GL_TEXTURE_SWIZZLE_G:
5243 case GL_TEXTURE_SWIZZLE_B:
5244 case GL_TEXTURE_SWIZZLE_A:
5245 case GL_TEXTURE_BASE_LEVEL:
5246 case GL_TEXTURE_MAX_LEVEL:
5247 case GL_TEXTURE_MIN_LOD:
5248 case GL_TEXTURE_MAX_LOD:
5249 case GL_TEXTURE_COMPARE_MODE:
5250 case GL_TEXTURE_COMPARE_FUNC:
5251 if (context->getClientMajorVersion() < 3)
5252 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005253 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005254 return false;
5255 }
5256 break;
5257
5258 case GL_TEXTURE_SRGB_DECODE_EXT:
5259 if (!context->getExtensions().textureSRGBDecode)
5260 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005261 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005262 return false;
5263 }
5264 break;
5265
5266 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005267 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005268 return false;
5269 }
5270
5271 if (length)
5272 {
5273 *length = 1;
5274 }
5275 return true;
5276}
5277
5278bool ValidateGetVertexAttribBase(Context *context,
5279 GLuint index,
5280 GLenum pname,
5281 GLsizei *length,
5282 bool pointer,
5283 bool pureIntegerEntryPoint)
5284{
5285 if (length)
5286 {
5287 *length = 0;
5288 }
5289
5290 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5291 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005292 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005293 return false;
5294 }
5295
5296 if (index >= context->getCaps().maxVertexAttributes)
5297 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005298 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Jamie Madillbe849e42017-05-02 15:49:00 -04005299 return false;
5300 }
5301
5302 if (pointer)
5303 {
5304 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5305 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005306 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005307 return false;
5308 }
5309 }
5310 else
5311 {
5312 switch (pname)
5313 {
5314 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5315 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5316 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5317 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5318 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5319 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5320 case GL_CURRENT_VERTEX_ATTRIB:
5321 break;
5322
5323 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5324 static_assert(
5325 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5326 "ANGLE extension enums not equal to GL enums.");
5327 if (context->getClientMajorVersion() < 3 &&
5328 !context->getExtensions().instancedArrays)
5329 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005330 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5331 "requires OpenGL ES 3.0 or "
5332 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005333 return false;
5334 }
5335 break;
5336
5337 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5338 if (context->getClientMajorVersion() < 3)
5339 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005340 context->handleError(
5341 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005342 return false;
5343 }
5344 break;
5345
5346 case GL_VERTEX_ATTRIB_BINDING:
5347 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5348 if (context->getClientVersion() < ES_3_1)
5349 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005350 context->handleError(InvalidEnum()
5351 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005352 return false;
5353 }
5354 break;
5355
5356 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005357 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005358 return false;
5359 }
5360 }
5361
5362 if (length)
5363 {
5364 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5365 {
5366 *length = 4;
5367 }
5368 else
5369 {
5370 *length = 1;
5371 }
5372 }
5373
5374 return true;
5375}
5376
Jamie Madill4928b7c2017-06-20 12:57:39 -04005377bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005378 GLint x,
5379 GLint y,
5380 GLsizei width,
5381 GLsizei height,
5382 GLenum format,
5383 GLenum type,
5384 GLsizei bufSize,
5385 GLsizei *length,
5386 GLsizei *columns,
5387 GLsizei *rows,
5388 void *pixels)
5389{
5390 if (length != nullptr)
5391 {
5392 *length = 0;
5393 }
5394 if (rows != nullptr)
5395 {
5396 *rows = 0;
5397 }
5398 if (columns != nullptr)
5399 {
5400 *columns = 0;
5401 }
5402
5403 if (width < 0 || height < 0)
5404 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005405 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005406 return false;
5407 }
5408
5409 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5410
5411 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5412 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005413 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005414 return false;
5415 }
5416
5417 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5418 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005419 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005420 return false;
5421 }
5422
5423 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5424 ASSERT(framebuffer);
5425
5426 if (framebuffer->getReadBufferState() == GL_NONE)
5427 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005428 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Jamie Madillbe849e42017-05-02 15:49:00 -04005429 return false;
5430 }
5431
5432 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5433 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5434 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5435 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5436 // situation is an application error that would lead to a crash in ANGLE.
5437 if (readBuffer == nullptr)
5438 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005439 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005440 return false;
5441 }
5442
Geoff Lang280ba992017-04-18 16:30:58 -04005443 if (context->getExtensions().webglCompatibility)
5444 {
5445 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5446 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5447 // and type before validating the combination of format and type. However, the
5448 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5449 // verifies that GL_INVALID_OPERATION is generated.
5450 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5451 // dEQP/WebGL.
5452 if (!ValidReadPixelsFormatEnum(context, format))
5453 {
5454 context->handleError(InvalidEnum() << "Invalid read format.");
5455 return false;
5456 }
5457
5458 if (!ValidReadPixelsTypeEnum(context, type))
5459 {
5460 context->handleError(InvalidEnum() << "Invalid read type.");
5461 return false;
5462 }
5463 }
5464
Jamie Madill4928b7c2017-06-20 12:57:39 -04005465 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5466 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005467 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5468
5469 bool validFormatTypeCombination =
5470 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5471
5472 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5473 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005474 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005475 return false;
5476 }
5477
5478 // Check for pixel pack buffer related API errors
5479 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5480 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5481 {
5482 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005483 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005484 return false;
5485 }
5486
5487 // .. the data would be packed to the buffer object such that the memory writes required
5488 // would exceed the data store size.
5489 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5490 const gl::Extents size(width, height, 1);
5491 const auto &pack = context->getGLState().getPackState();
5492
5493 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5494 if (endByteOrErr.isError())
5495 {
5496 context->handleError(endByteOrErr.getError());
5497 return false;
5498 }
5499
5500 size_t endByte = endByteOrErr.getResult();
5501 if (bufSize >= 0)
5502 {
5503 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5504 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005505 context->handleError(InvalidOperation()
5506 << "bufSize must be at least " << endByte << " bytes.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005507 return false;
5508 }
5509 }
5510
5511 if (pixelPackBuffer != nullptr)
5512 {
5513 CheckedNumeric<size_t> checkedEndByte(endByte);
5514 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5515 checkedEndByte += checkedOffset;
5516
5517 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5518 {
5519 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005520 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005521 return false;
5522 }
5523 }
5524
5525 if (pixelPackBuffer == nullptr && length != nullptr)
5526 {
5527 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5528 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005529 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005530 return false;
5531 }
5532
5533 *length = static_cast<GLsizei>(endByte);
5534 }
5535
5536 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5537 angle::CheckedNumeric<int> clippedExtent(length);
5538 if (start < 0)
5539 {
5540 // "subtract" the area that is less than 0
5541 clippedExtent += start;
5542 }
5543
5544 const int readExtent = start + length;
5545 if (readExtent > bufferSize)
5546 {
5547 // Subtract the region to the right of the read buffer
5548 clippedExtent -= (readExtent - bufferSize);
5549 }
5550
5551 if (!clippedExtent.IsValid())
5552 {
5553 return 0;
5554 }
5555
5556 return std::max(clippedExtent.ValueOrDie(), 0);
5557 };
5558
5559 if (columns != nullptr)
5560 {
5561 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5562 }
5563
5564 if (rows != nullptr)
5565 {
5566 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5567 }
5568
5569 return true;
5570}
5571
5572template <typename ParamType>
5573bool ValidateTexParameterBase(Context *context,
5574 GLenum target,
5575 GLenum pname,
5576 GLsizei bufSize,
5577 const ParamType *params)
5578{
5579 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5580 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005581 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005582 return false;
5583 }
5584
5585 if (context->getTargetTexture(target) == nullptr)
5586 {
5587 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005588 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005589 return false;
5590 }
5591
5592 const GLsizei minBufSize = 1;
5593 if (bufSize >= 0 && bufSize < minBufSize)
5594 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005595 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005596 return false;
5597 }
5598
5599 switch (pname)
5600 {
5601 case GL_TEXTURE_WRAP_R:
5602 case GL_TEXTURE_SWIZZLE_R:
5603 case GL_TEXTURE_SWIZZLE_G:
5604 case GL_TEXTURE_SWIZZLE_B:
5605 case GL_TEXTURE_SWIZZLE_A:
5606 case GL_TEXTURE_BASE_LEVEL:
5607 case GL_TEXTURE_MAX_LEVEL:
5608 case GL_TEXTURE_COMPARE_MODE:
5609 case GL_TEXTURE_COMPARE_FUNC:
5610 case GL_TEXTURE_MIN_LOD:
5611 case GL_TEXTURE_MAX_LOD:
5612 if (context->getClientMajorVersion() < 3)
5613 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005614 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005615 return false;
5616 }
5617 if (target == GL_TEXTURE_EXTERNAL_OES &&
5618 !context->getExtensions().eglImageExternalEssl3)
5619 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005620 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5621 "available without "
5622 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005623 return false;
5624 }
5625 break;
5626
5627 default:
5628 break;
5629 }
5630
JiangYizhou4cff8d62017-07-06 14:54:09 +08005631 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5632 {
5633 switch (pname)
5634 {
5635 case GL_TEXTURE_MIN_FILTER:
5636 case GL_TEXTURE_MAG_FILTER:
5637 case GL_TEXTURE_WRAP_S:
5638 case GL_TEXTURE_WRAP_T:
5639 case GL_TEXTURE_WRAP_R:
5640 case GL_TEXTURE_MIN_LOD:
5641 case GL_TEXTURE_MAX_LOD:
5642 case GL_TEXTURE_COMPARE_MODE:
5643 case GL_TEXTURE_COMPARE_FUNC:
5644 context->handleError(InvalidEnum()
5645 << "Invalid parameter for 2D multisampled textures.");
5646 return false;
5647 }
5648 }
5649
Jamie Madillbe849e42017-05-02 15:49:00 -04005650 switch (pname)
5651 {
5652 case GL_TEXTURE_WRAP_S:
5653 case GL_TEXTURE_WRAP_T:
5654 case GL_TEXTURE_WRAP_R:
5655 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
5656 {
5657 return false;
5658 }
5659 break;
5660
5661 case GL_TEXTURE_MIN_FILTER:
5662 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
5663 {
5664 return false;
5665 }
5666 break;
5667
5668 case GL_TEXTURE_MAG_FILTER:
5669 if (!ValidateTextureMagFilterValue(context, params))
5670 {
5671 return false;
5672 }
5673 break;
5674
5675 case GL_TEXTURE_USAGE_ANGLE:
5676 switch (ConvertToGLenum(params[0]))
5677 {
5678 case GL_NONE:
5679 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5680 break;
5681
5682 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005683 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005684 return false;
5685 }
5686 break;
5687
5688 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5689 if (!context->getExtensions().textureFilterAnisotropic)
5690 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005691 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005692 return false;
5693 }
5694
5695 // we assume the parameter passed to this validation method is truncated, not rounded
5696 if (params[0] < 1)
5697 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005698 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005699 return false;
5700 }
5701 break;
5702
5703 case GL_TEXTURE_MIN_LOD:
5704 case GL_TEXTURE_MAX_LOD:
5705 // any value is permissible
5706 break;
5707
5708 case GL_TEXTURE_COMPARE_MODE:
5709 if (!ValidateTextureCompareModeValue(context, params))
5710 {
5711 return false;
5712 }
5713 break;
5714
5715 case GL_TEXTURE_COMPARE_FUNC:
5716 if (!ValidateTextureCompareFuncValue(context, params))
5717 {
5718 return false;
5719 }
5720 break;
5721
5722 case GL_TEXTURE_SWIZZLE_R:
5723 case GL_TEXTURE_SWIZZLE_G:
5724 case GL_TEXTURE_SWIZZLE_B:
5725 case GL_TEXTURE_SWIZZLE_A:
5726 switch (ConvertToGLenum(params[0]))
5727 {
5728 case GL_RED:
5729 case GL_GREEN:
5730 case GL_BLUE:
5731 case GL_ALPHA:
5732 case GL_ZERO:
5733 case GL_ONE:
5734 break;
5735
5736 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005737 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005738 return false;
5739 }
5740 break;
5741
5742 case GL_TEXTURE_BASE_LEVEL:
5743 if (params[0] < 0)
5744 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005745 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005746 return false;
5747 }
5748 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5749 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005750 context->handleError(InvalidOperation()
5751 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005752 return false;
5753 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005754 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5755 {
5756 context->handleError(InvalidOperation()
5757 << "Base level must be 0 for multisampled textures.");
5758 return false;
5759 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005760 break;
5761
5762 case GL_TEXTURE_MAX_LEVEL:
5763 if (params[0] < 0)
5764 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005765 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005766 return false;
5767 }
5768 break;
5769
5770 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5771 if (context->getClientVersion() < Version(3, 1))
5772 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005773 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005774 return false;
5775 }
5776 switch (ConvertToGLenum(params[0]))
5777 {
5778 case GL_DEPTH_COMPONENT:
5779 case GL_STENCIL_INDEX:
5780 break;
5781
5782 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005783 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005784 return false;
5785 }
5786 break;
5787
5788 case GL_TEXTURE_SRGB_DECODE_EXT:
5789 if (!ValidateTextureSRGBDecodeValue(context, params))
5790 {
5791 return false;
5792 }
5793 break;
5794
5795 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005796 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005797 return false;
5798 }
5799
5800 return true;
5801}
5802
5803template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5804template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5805
Jamie Madillc29968b2016-01-20 11:17:23 -05005806} // namespace gl