blob: 66d1f6503bb6002bc3315566c3065acc7fe5cd80 [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);
592 *length = static_cast<GLsizei>(uniformBlock.memberUniformIndexes.size());
593 }
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 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001449 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001450 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001451 }
1452 }
1453 else
1454 {
1455 switch (attachment)
1456 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001457 case GL_DEPTH_ATTACHMENT:
1458 case GL_STENCIL_ATTACHMENT:
1459 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001460
He Yunchaoced53ae2016-11-29 15:00:51 +08001461 case GL_DEPTH_STENCIL_ATTACHMENT:
1462 if (!context->getExtensions().webglCompatibility &&
1463 context->getClientMajorVersion() < 3)
1464 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001465 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001466 return false;
1467 }
1468 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001469
He Yunchaoced53ae2016-11-29 15:00:51 +08001470 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001471 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001472 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001473 }
1474 }
1475
1476 return true;
1477}
1478
Jamie Madille8fb6402017-02-14 17:56:40 -05001479bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001480 GLenum target,
1481 GLsizei samples,
1482 GLenum internalformat,
1483 GLsizei width,
1484 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001485{
1486 switch (target)
1487 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001488 case GL_RENDERBUFFER:
1489 break;
1490 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001491 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001492 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001493 }
1494
1495 if (width < 0 || height < 0 || samples < 0)
1496 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001497 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001498 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001499 }
1500
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001501 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1502 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1503
1504 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001505 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001506 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001507 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001508 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001509 }
1510
1511 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1512 // 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 -08001513 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001514 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1515 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001516 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001517 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001518 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001519 }
1520
Geoff Langaae65a42014-05-26 12:43:44 -04001521 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001522 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001523 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001524 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001525 }
1526
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001527 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001528 if (handle == 0)
1529 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001530 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001531 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001532 }
1533
1534 return true;
1535}
1536
He Yunchaoced53ae2016-11-29 15:00:51 +08001537bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1538 GLenum target,
1539 GLenum attachment,
1540 GLenum renderbuffertarget,
1541 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001542{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001543 if (!ValidFramebufferTarget(target))
1544 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001545 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001546 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001547 }
1548
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001549 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001550
Jamie Madill84115c92015-04-23 15:00:07 -04001551 ASSERT(framebuffer);
1552 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001553 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001554 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001555 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001556 }
1557
Jamie Madillb4472272014-07-03 10:38:55 -04001558 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001559 {
Jamie Madillb4472272014-07-03 10:38:55 -04001560 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001561 }
1562
Jamie Madillab9d82c2014-01-21 16:38:14 -05001563 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1564 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1565 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1566 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1567 if (renderbuffer != 0)
1568 {
1569 if (!context->getRenderbuffer(renderbuffer))
1570 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001571 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001572 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001573 }
1574 }
1575
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001576 return true;
1577}
1578
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001579bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001580 GLint srcX0,
1581 GLint srcY0,
1582 GLint srcX1,
1583 GLint srcY1,
1584 GLint dstX0,
1585 GLint dstY0,
1586 GLint dstX1,
1587 GLint dstY1,
1588 GLbitfield mask,
1589 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001590{
1591 switch (filter)
1592 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001593 case GL_NEAREST:
1594 break;
1595 case GL_LINEAR:
1596 break;
1597 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001598 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001599 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001600 }
1601
1602 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1603 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001604 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001605 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001606 }
1607
1608 if (mask == 0)
1609 {
1610 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1611 // buffers are copied.
1612 return false;
1613 }
1614
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001615 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1616 // color buffer, leaving only nearest being unfiltered from above
1617 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1618 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001619 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001620 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001621 }
1622
Jamie Madill51f40ec2016-06-15 14:06:00 -04001623 const auto &glState = context->getGLState();
1624 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1625 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001626
1627 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001628 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001629 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001630 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001631 }
1632
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001633 if (readFramebuffer->id() == drawFramebuffer->id())
1634 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001635 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001636 return false;
1637 }
1638
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001639 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001640 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001641 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001642 return false;
1643 }
1644
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001645 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001647 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001648 return false;
1649 }
1650
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001651 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001652 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001653 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001654 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001655 }
1656
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001657 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1658
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001659 if (mask & GL_COLOR_BUFFER_BIT)
1660 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001661 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001662 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001663
He Yunchao66a41a22016-12-15 16:45:05 +08001664 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001665 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001666 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001667
Geoff Langa15472a2015-08-11 11:48:03 -04001668 for (size_t drawbufferIdx = 0;
1669 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001670 {
Geoff Langa15472a2015-08-11 11:48:03 -04001671 const FramebufferAttachment *attachment =
1672 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1673 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001674 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001675 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001676
Geoff Langb2f3d052013-08-13 12:49:27 -04001677 // The GL ES 3.0.2 spec (pg 193) states that:
1678 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001679 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1680 // as well
1681 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1682 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001683 // Changes with EXT_color_buffer_float:
1684 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001685 GLenum readComponentType = readFormat.info->componentType;
1686 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001687 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001688 readComponentType == GL_SIGNED_NORMALIZED);
1689 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1690 drawComponentType == GL_SIGNED_NORMALIZED);
1691
1692 if (extensions.colorBufferFloat)
1693 {
1694 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1695 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1696
1697 if (readFixedOrFloat != drawFixedOrFloat)
1698 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001699 context->handleError(InvalidOperation()
1700 << "If the read buffer contains fixed-point or "
1701 "floating-point values, the draw buffer must "
1702 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001703 return false;
1704 }
1705 }
1706 else if (readFixedPoint != drawFixedPoint)
1707 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001708 context->handleError(InvalidOperation()
1709 << "If the read buffer contains fixed-point values, "
1710 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001711 return false;
1712 }
1713
1714 if (readComponentType == GL_UNSIGNED_INT &&
1715 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001716 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001717 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001718 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001719 }
1720
Jamie Madill6163c752015-12-07 16:32:59 -05001721 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001722 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001723 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001724 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001725 }
1726
Jamie Madilla3944d42016-07-22 22:13:26 -04001727 if (readColorBuffer->getSamples() > 0 &&
1728 (!Format::SameSized(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001729 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001730 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001731 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001732 }
Geoff Lange4915782017-04-12 15:19:07 -04001733
1734 if (context->getExtensions().webglCompatibility &&
1735 *readColorBuffer == *attachment)
1736 {
1737 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001738 InvalidOperation()
1739 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001740 return false;
1741 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001742 }
1743 }
1744
Jamie Madilla3944d42016-07-22 22:13:26 -04001745 if ((readFormat.info->componentType == GL_INT ||
1746 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1747 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001748 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001749 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001750 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001751 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001752 }
He Yunchao66a41a22016-12-15 16:45:05 +08001753 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1754 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1755 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1756 // situation is an application error that would lead to a crash in ANGLE.
1757 else if (drawFramebuffer->hasEnabledDrawBuffer())
1758 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001759 context->handleError(
1760 InvalidOperation()
1761 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001762 return false;
1763 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001764 }
1765
He Yunchaoced53ae2016-11-29 15:00:51 +08001766 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001767 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1768 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001769 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001770 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001771 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001772 const gl::FramebufferAttachment *readBuffer =
1773 readFramebuffer->getAttachment(attachments[i]);
1774 const gl::FramebufferAttachment *drawBuffer =
1775 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001776
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001777 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001778 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001779 if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001780 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001781 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001782 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001783 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001784
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001785 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001786 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001787 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001788 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001789 }
Geoff Lange4915782017-04-12 15:19:07 -04001790
1791 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1792 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001793 context->handleError(
1794 InvalidOperation()
1795 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001796 return false;
1797 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001798 }
He Yunchao66a41a22016-12-15 16:45:05 +08001799 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1800 else if (drawBuffer)
1801 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001802 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1803 "depth/stencil attachment of a "
1804 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001805 return false;
1806 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001807 }
1808 }
1809
1810 return true;
1811}
1812
Jamie Madill4928b7c2017-06-20 12:57:39 -04001813bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001814 GLint x,
1815 GLint y,
1816 GLsizei width,
1817 GLsizei height,
1818 GLenum format,
1819 GLenum type,
1820 GLsizei bufSize,
1821 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001822 GLsizei *columns,
1823 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001824 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001825{
1826 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001827 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001828 return false;
1829 }
1830
Geoff Lang62fce5b2016-09-30 10:46:35 -04001831 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001832 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001833 {
Geoff Langb1196682014-07-23 13:47:29 -04001834 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001835 }
1836
Geoff Lang62fce5b2016-09-30 10:46:35 -04001837 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001838 {
Geoff Langb1196682014-07-23 13:47:29 -04001839 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001840 }
1841
Jamie Madillc29968b2016-01-20 11:17:23 -05001842 return true;
1843}
1844
1845bool ValidateReadnPixelsEXT(Context *context,
1846 GLint x,
1847 GLint y,
1848 GLsizei width,
1849 GLsizei height,
1850 GLenum format,
1851 GLenum type,
1852 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001853 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001854{
1855 if (bufSize < 0)
1856 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001857 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001858 return false;
1859 }
1860
Geoff Lang62fce5b2016-09-30 10:46:35 -04001861 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001862 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001863}
Jamie Madill26e91952014-03-05 15:01:27 -05001864
Jamie Madill4928b7c2017-06-20 12:57:39 -04001865bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001866 GLint x,
1867 GLint y,
1868 GLsizei width,
1869 GLsizei height,
1870 GLenum format,
1871 GLenum type,
1872 GLsizei bufSize,
1873 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001874 GLsizei *columns,
1875 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001876 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001877{
1878 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001879 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001880 return false;
1881 }
1882
Geoff Lange93daba2017-03-30 13:54:40 -04001883 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1884 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001885 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001886 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001887 }
1888
Geoff Lang62fce5b2016-09-30 10:46:35 -04001889 if (!ValidateRobustBufferSize(context, bufSize, *length))
1890 {
1891 return false;
1892 }
1893
1894 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001895}
1896
Olli Etuaho41997e72016-03-10 13:38:39 +02001897bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001898{
1899 if (!context->getExtensions().occlusionQueryBoolean &&
1900 !context->getExtensions().disjointTimerQuery)
1901 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001902 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001903 return false;
1904 }
1905
Olli Etuaho41997e72016-03-10 13:38:39 +02001906 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001907}
1908
Olli Etuaho41997e72016-03-10 13:38:39 +02001909bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001910{
1911 if (!context->getExtensions().occlusionQueryBoolean &&
1912 !context->getExtensions().disjointTimerQuery)
1913 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001914 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001915 return false;
1916 }
1917
Olli Etuaho41997e72016-03-10 13:38:39 +02001918 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001919}
1920
1921bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001922{
1923 if (!ValidQueryType(context, target))
1924 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001925 context->handleError(InvalidEnum() << "Invalid query target");
Geoff Langb1196682014-07-23 13:47:29 -04001926 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001927 }
1928
1929 if (id == 0)
1930 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001931 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001932 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001933 }
1934
1935 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1936 // of zero, if the active query object name for <target> is non-zero (for the
1937 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1938 // the active query for either target is non-zero), if <id> is the name of an
1939 // existing query object whose type does not match <target>, or if <id> is the
1940 // active query object name for any query type, the error INVALID_OPERATION is
1941 // generated.
1942
1943 // Ensure no other queries are active
1944 // NOTE: If other queries than occlusion are supported, we will need to check
1945 // separately that:
1946 // a) The query ID passed is not the current active query for any target/type
1947 // b) There are no active queries for the requested target (and in the case
1948 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1949 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001950
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001951 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001952 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001953 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001954 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001955 }
1956
1957 Query *queryObject = context->getQuery(id, true, target);
1958
1959 // check that name was obtained with glGenQueries
1960 if (!queryObject)
1961 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001962 context->handleError(InvalidOperation() << "Invalid query id");
Geoff Langb1196682014-07-23 13:47:29 -04001963 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001964 }
1965
1966 // check for type mismatch
1967 if (queryObject->getType() != target)
1968 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001969 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001970 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001971 }
1972
1973 return true;
1974}
1975
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001976bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1977{
1978 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001979 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001980 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001981 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001982 return false;
1983 }
1984
1985 return ValidateBeginQueryBase(context, target, id);
1986}
1987
1988bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001989{
1990 if (!ValidQueryType(context, target))
1991 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001992 context->handleError(InvalidEnum() << "Invalid query target");
Geoff Langb1196682014-07-23 13:47:29 -04001993 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001994 }
1995
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001996 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001997
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001998 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001999 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002000 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04002001 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002002 }
2003
Jamie Madill45c785d2014-05-13 14:09:34 -04002004 return true;
2005}
2006
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002007bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2008{
2009 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002010 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002011 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002012 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002013 return false;
2014 }
2015
2016 return ValidateEndQueryBase(context, target);
2017}
2018
2019bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2020{
2021 if (!context->getExtensions().disjointTimerQuery)
2022 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002023 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002024 return false;
2025 }
2026
2027 if (target != GL_TIMESTAMP_EXT)
2028 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002029 context->handleError(InvalidEnum() << "Invalid query target");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002030 return false;
2031 }
2032
2033 Query *queryObject = context->getQuery(id, true, target);
2034 if (queryObject == nullptr)
2035 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002036 context->handleError(InvalidOperation() << "Invalid query id");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002037 return false;
2038 }
2039
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002040 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002041 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002042 context->handleError(InvalidOperation() << "Query is active");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002043 return false;
2044 }
2045
2046 return true;
2047}
2048
Geoff Lang2186c382016-10-14 10:54:54 -04002049bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002050{
Geoff Lang2186c382016-10-14 10:54:54 -04002051 if (numParams)
2052 {
2053 *numParams = 0;
2054 }
2055
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002056 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2057 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002058 context->handleError(InvalidEnum() << "Invalid query type");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002059 return false;
2060 }
2061
2062 switch (pname)
2063 {
2064 case GL_CURRENT_QUERY_EXT:
2065 if (target == GL_TIMESTAMP_EXT)
2066 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002067 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002068 return false;
2069 }
2070 break;
2071 case GL_QUERY_COUNTER_BITS_EXT:
2072 if (!context->getExtensions().disjointTimerQuery ||
2073 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2074 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002075 context->handleError(InvalidEnum() << "Invalid pname");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002076 return false;
2077 }
2078 break;
2079 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002080 context->handleError(InvalidEnum() << "Invalid pname");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002081 return false;
2082 }
2083
Geoff Lang2186c382016-10-14 10:54:54 -04002084 if (numParams)
2085 {
2086 // All queries return only one value
2087 *numParams = 1;
2088 }
2089
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002090 return true;
2091}
2092
2093bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2094{
2095 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002096 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002097 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002098 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002099 return false;
2100 }
2101
Geoff Lang2186c382016-10-14 10:54:54 -04002102 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002103}
2104
Geoff Lang2186c382016-10-14 10:54:54 -04002105bool ValidateGetQueryivRobustANGLE(Context *context,
2106 GLenum target,
2107 GLenum pname,
2108 GLsizei bufSize,
2109 GLsizei *length,
2110 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002111{
Geoff Lang2186c382016-10-14 10:54:54 -04002112 if (!ValidateRobustEntryPoint(context, bufSize))
2113 {
2114 return false;
2115 }
2116
2117 if (!ValidateGetQueryivBase(context, target, pname, length))
2118 {
2119 return false;
2120 }
2121
2122 if (!ValidateRobustBufferSize(context, bufSize, *length))
2123 {
2124 return false;
2125 }
2126
2127 return true;
2128}
2129
2130bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2131{
2132 if (numParams)
2133 {
2134 *numParams = 0;
2135 }
2136
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002137 Query *queryObject = context->getQuery(id, false, GL_NONE);
2138
2139 if (!queryObject)
2140 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002141 context->handleError(InvalidOperation() << "Query does not exist");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002142 return false;
2143 }
2144
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002145 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002146 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002147 context->handleError(InvalidOperation() << "Query currently active");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002148 return false;
2149 }
2150
2151 switch (pname)
2152 {
2153 case GL_QUERY_RESULT_EXT:
2154 case GL_QUERY_RESULT_AVAILABLE_EXT:
2155 break;
2156
2157 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002158 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002159 return false;
2160 }
2161
Geoff Lang2186c382016-10-14 10:54:54 -04002162 if (numParams)
2163 {
2164 *numParams = 1;
2165 }
2166
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002167 return true;
2168}
2169
2170bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2171{
2172 if (!context->getExtensions().disjointTimerQuery)
2173 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002174 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002175 return false;
2176 }
Geoff Lang2186c382016-10-14 10:54:54 -04002177 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2178}
2179
2180bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2181 GLuint id,
2182 GLenum pname,
2183 GLsizei bufSize,
2184 GLsizei *length,
2185 GLint *params)
2186{
2187 if (!context->getExtensions().disjointTimerQuery)
2188 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002189 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04002190 return false;
2191 }
2192
2193 if (!ValidateRobustEntryPoint(context, bufSize))
2194 {
2195 return false;
2196 }
2197
2198 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2199 {
2200 return false;
2201 }
2202
2203 if (!ValidateRobustBufferSize(context, bufSize, *length))
2204 {
2205 return false;
2206 }
2207
2208 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002209}
2210
2211bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2212{
2213 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002214 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002215 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002216 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002217 return false;
2218 }
Geoff Lang2186c382016-10-14 10:54:54 -04002219 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2220}
2221
2222bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2223 GLuint id,
2224 GLenum pname,
2225 GLsizei bufSize,
2226 GLsizei *length,
2227 GLuint *params)
2228{
2229 if (!context->getExtensions().disjointTimerQuery &&
2230 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2231 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002232 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002233 return false;
2234 }
2235
2236 if (!ValidateRobustEntryPoint(context, bufSize))
2237 {
2238 return false;
2239 }
2240
2241 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2242 {
2243 return false;
2244 }
2245
2246 if (!ValidateRobustBufferSize(context, bufSize, *length))
2247 {
2248 return false;
2249 }
2250
2251 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002252}
2253
2254bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2255{
2256 if (!context->getExtensions().disjointTimerQuery)
2257 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002258 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002259 return false;
2260 }
Geoff Lang2186c382016-10-14 10:54:54 -04002261 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2262}
2263
2264bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2265 GLuint id,
2266 GLenum pname,
2267 GLsizei bufSize,
2268 GLsizei *length,
2269 GLint64 *params)
2270{
2271 if (!context->getExtensions().disjointTimerQuery)
2272 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002273 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002274 return false;
2275 }
2276
2277 if (!ValidateRobustEntryPoint(context, bufSize))
2278 {
2279 return false;
2280 }
2281
2282 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2283 {
2284 return false;
2285 }
2286
2287 if (!ValidateRobustBufferSize(context, bufSize, *length))
2288 {
2289 return false;
2290 }
2291
2292 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002293}
2294
2295bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2296{
2297 if (!context->getExtensions().disjointTimerQuery)
2298 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002299 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002300 return false;
2301 }
Geoff Lang2186c382016-10-14 10:54:54 -04002302 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2303}
2304
2305bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2306 GLuint id,
2307 GLenum pname,
2308 GLsizei bufSize,
2309 GLsizei *length,
2310 GLuint64 *params)
2311{
2312 if (!context->getExtensions().disjointTimerQuery)
2313 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002314 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002315 return false;
2316 }
2317
2318 if (!ValidateRobustEntryPoint(context, bufSize))
2319 {
2320 return false;
2321 }
2322
2323 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2324 {
2325 return false;
2326 }
2327
2328 if (!ValidateRobustBufferSize(context, bufSize, *length))
2329 {
2330 return false;
2331 }
2332
2333 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002334}
2335
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002336bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002337 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002338 GLuint program,
2339 GLint location,
2340 GLsizei count)
2341{
2342 // Check for ES31 program uniform entry points
2343 if (context->getClientVersion() < Version(3, 1))
2344 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002345 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002346 return false;
2347 }
2348
2349 const LinkedUniform *uniform = nullptr;
2350 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002351 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2352 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002353}
2354
Frank Henigmana98a6472017-02-02 21:38:32 -05002355bool ValidateProgramUniform1iv(gl::Context *context,
2356 GLuint program,
2357 GLint location,
2358 GLsizei count,
2359 const GLint *value)
2360{
2361 // Check for ES31 program uniform entry points
2362 if (context->getClientVersion() < Version(3, 1))
2363 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002364 context->handleError(InvalidOperation());
Frank Henigmana98a6472017-02-02 21:38:32 -05002365 return false;
2366 }
2367
2368 const LinkedUniform *uniform = nullptr;
2369 gl::Program *programObject = GetValidProgram(context, program);
2370 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2371 ValidateUniform1ivValue(context, uniform->type, count, value);
2372}
2373
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002374bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002375 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002376 GLuint program,
2377 GLint location,
2378 GLsizei count,
2379 GLboolean transpose)
2380{
2381 // Check for ES31 program uniform entry points
2382 if (context->getClientVersion() < Version(3, 1))
2383 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002384 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002385 return false;
2386 }
2387
2388 const LinkedUniform *uniform = nullptr;
2389 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002390 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2391 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002392}
2393
Jamie Madillc1d770e2017-04-13 17:31:24 -04002394bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002395{
2396 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002397 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002398 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002399 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002400 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002401 }
2402
Jamie Madill62d31cb2015-09-11 13:25:51 -04002403 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002404 gl::Program *programObject = context->getGLState().getProgram();
2405 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2406 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002407}
2408
Jamie Madillbe849e42017-05-02 15:49:00 -04002409bool ValidateUniform1iv(ValidationContext *context,
2410 GLint location,
2411 GLsizei count,
2412 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002413{
2414 const LinkedUniform *uniform = nullptr;
2415 gl::Program *programObject = context->getGLState().getProgram();
2416 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2417 ValidateUniform1ivValue(context, uniform->type, count, value);
2418}
2419
Jamie Madillc1d770e2017-04-13 17:31:24 -04002420bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002421 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002422 GLint location,
2423 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002424 GLboolean transpose)
2425{
2426 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002427 int rows = VariableRowCount(valueType);
2428 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002429 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002430 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002431 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002432 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002433 }
2434
Martin Radev1be913c2016-07-11 17:59:16 +03002435 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002436 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002437 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002438 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002439 }
2440
Jamie Madill62d31cb2015-09-11 13:25:51 -04002441 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002442 gl::Program *programObject = context->getGLState().getProgram();
2443 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2444 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002445}
2446
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002447bool ValidateStateQuery(ValidationContext *context,
2448 GLenum pname,
2449 GLenum *nativeType,
2450 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002451{
2452 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2453 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002454 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002455 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002456 }
2457
Jamie Madill0af26e12015-03-05 19:54:33 -05002458 const Caps &caps = context->getCaps();
2459
Jamie Madill893ab082014-05-16 16:56:10 -04002460 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2461 {
2462 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2463
Jamie Madill0af26e12015-03-05 19:54:33 -05002464 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002465 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002466 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002467 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002468 }
2469 }
2470
2471 switch (pname)
2472 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002473 case GL_TEXTURE_BINDING_2D:
2474 case GL_TEXTURE_BINDING_CUBE_MAP:
2475 case GL_TEXTURE_BINDING_3D:
2476 case GL_TEXTURE_BINDING_2D_ARRAY:
2477 break;
2478 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2479 if (!context->getExtensions().eglStreamConsumerExternal &&
2480 !context->getExtensions().eglImageExternal)
2481 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002482 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2483 "nor GL_OES_EGL_image_external "
2484 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002485 return false;
2486 }
2487 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002488
He Yunchaoced53ae2016-11-29 15:00:51 +08002489 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2490 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002491 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002492 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2493 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002494 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002495 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002496 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002497 }
2498
Jamie Madill51f40ec2016-06-15 14:06:00 -04002499 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2500 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002501
2502 if (framebuffer->getReadBufferState() == GL_NONE)
2503 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002504 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Martin Radev138064f2016-07-15 12:03:41 +03002505 return false;
2506 }
2507
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002508 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002509 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002510 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002511 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002512 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002513 }
2514 }
2515 break;
2516
He Yunchaoced53ae2016-11-29 15:00:51 +08002517 default:
2518 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002519 }
2520
2521 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002522 if (*numParams == 0)
2523 {
2524 return false;
2525 }
2526
2527 return true;
2528}
2529
2530bool ValidateRobustStateQuery(ValidationContext *context,
2531 GLenum pname,
2532 GLsizei bufSize,
2533 GLenum *nativeType,
2534 unsigned int *numParams)
2535{
2536 if (!ValidateRobustEntryPoint(context, bufSize))
2537 {
2538 return false;
2539 }
2540
2541 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2542 {
2543 return false;
2544 }
2545
2546 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002547 {
2548 return false;
2549 }
2550
2551 return true;
2552}
2553
Jamie Madillc29968b2016-01-20 11:17:23 -05002554bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2555 GLenum target,
2556 GLint level,
2557 GLenum internalformat,
2558 bool isSubImage,
2559 GLint xoffset,
2560 GLint yoffset,
2561 GLint zoffset,
2562 GLint x,
2563 GLint y,
2564 GLsizei width,
2565 GLsizei height,
2566 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002567 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002568{
Brandon Jones6cad5662017-06-14 13:25:13 -07002569 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002570 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002571 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2572 return false;
2573 }
2574
2575 if (width < 0 || height < 0)
2576 {
2577 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002578 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002579 }
2580
He Yunchaoced53ae2016-11-29 15:00:51 +08002581 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2582 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002583 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002584 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002585 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002586 }
2587
2588 if (border != 0)
2589 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002590 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002591 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002592 }
2593
2594 if (!ValidMipLevel(context, target, level))
2595 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002596 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002597 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002598 }
2599
Jamie Madill51f40ec2016-06-15 14:06:00 -04002600 const auto &state = context->getGLState();
2601 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002602 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002603 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002604 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002605 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002606 }
2607
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002608 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002609 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002610 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002611 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002612 }
2613
Martin Radev138064f2016-07-15 12:03:41 +03002614 if (readFramebuffer->getReadBufferState() == GL_NONE)
2615 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002616 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Martin Radev138064f2016-07-15 12:03:41 +03002617 return false;
2618 }
2619
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002620 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2621 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002622 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002623 // situation is an application error that would lead to a crash in ANGLE.
2624 if (readFramebuffer->getReadColorbuffer() == nullptr)
2625 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002626 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002627 return false;
2628 }
2629
Geoff Langaae65a42014-05-26 12:43:44 -04002630 const gl::Caps &caps = context->getCaps();
2631
Geoff Langaae65a42014-05-26 12:43:44 -04002632 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002633 switch (target)
2634 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002635 case GL_TEXTURE_2D:
2636 maxDimension = caps.max2DTextureSize;
2637 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002638
He Yunchaoced53ae2016-11-29 15:00:51 +08002639 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2640 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2641 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2642 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2643 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2644 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2645 maxDimension = caps.maxCubeMapTextureSize;
2646 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002647
He Yunchaoced53ae2016-11-29 15:00:51 +08002648 case GL_TEXTURE_2D_ARRAY:
2649 maxDimension = caps.max2DTextureSize;
2650 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002651
He Yunchaoced53ae2016-11-29 15:00:51 +08002652 case GL_TEXTURE_3D:
2653 maxDimension = caps.max3DTextureSize;
2654 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002655
He Yunchaoced53ae2016-11-29 15:00:51 +08002656 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002657 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002658 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002659 }
2660
Jamie Madillc29968b2016-01-20 11:17:23 -05002661 gl::Texture *texture =
2662 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002663 if (!texture)
2664 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002665 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002666 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002667 }
2668
Geoff Lang69cce582015-09-17 13:20:36 -04002669 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002670 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002671 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002672 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002673 }
2674
Geoff Langca271392017-04-05 12:30:00 -04002675 const gl::InternalFormat &formatInfo =
2676 gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002677
Geoff Lang966c9402017-04-18 12:38:27 -04002678 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002679 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002680 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002681 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002682 }
2683
2684 if (isSubImage)
2685 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002686 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2687 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2688 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002689 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002690 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002691 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002692 }
2693 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002694 else
2695 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002696 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002697 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002698 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002699 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002700 }
2701
Geoff Langeb66a6e2016-10-31 13:06:12 -04002702 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002703 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002704 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002705 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002706 }
2707
2708 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002709 if (static_cast<int>(width) > maxLevelDimension ||
2710 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002711 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002712 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002713 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002714 }
2715 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002716
Jamie Madill0c8abca2016-07-22 20:21:26 -04002717 if (textureFormatOut)
2718 {
2719 *textureFormatOut = texture->getFormat(target, level);
2720 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002721
2722 // Detect texture copying feedback loops for WebGL.
2723 if (context->getExtensions().webglCompatibility)
2724 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002725 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002726 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002727 context->handleError(InvalidOperation() << "Texture copying feedback loop formed "
2728 "between Framebuffer and specified "
2729 "Texture level.");
Jamie Madillf695a3a2017-01-11 17:36:35 -05002730 return false;
2731 }
2732 }
2733
Jamie Madill560a8d82014-05-21 13:06:20 -04002734 return true;
2735}
2736
Jiajia Qind9671222016-11-29 16:30:31 +08002737bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002738{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002739 switch (mode)
2740 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002741 case GL_POINTS:
2742 case GL_LINES:
2743 case GL_LINE_LOOP:
2744 case GL_LINE_STRIP:
2745 case GL_TRIANGLES:
2746 case GL_TRIANGLE_STRIP:
2747 case GL_TRIANGLE_FAN:
2748 break;
2749 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002750 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002751 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002752 }
2753
Jamie Madill250d33f2014-06-06 17:09:03 -04002754 if (count < 0)
2755 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002756 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002757 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002758 }
2759
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002760 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002761
Jamie Madill250d33f2014-06-06 17:09:03 -04002762 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002763 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002765 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002766 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002767 }
2768
Jamie Madillcbcde722017-01-06 14:50:00 -05002769 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2770 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002771 Framebuffer *framebuffer = state.getDrawFramebuffer();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002772 if (context->getLimitations().noSeparateStencilRefsAndMasks ||
2773 context->getExtensions().webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002774 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002775 const FramebufferAttachment *dsAttachment =
2776 framebuffer->getStencilOrDepthStencilAttachment();
2777 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002778 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002779 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002780
2781 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2782 bool differentWritemasks =
2783 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2784 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2785 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2786 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2787
2788 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002789 {
Jamie Madillcbcde722017-01-06 14:50:00 -05002790 if (!context->getExtensions().webglCompatibility)
2791 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002792 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2793 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002794 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002795 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002796 return false;
2797 }
Jamie Madillac528012014-06-20 13:21:23 -04002798 }
2799
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002800 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002801 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002802 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002803 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002804 }
2805
Geoff Lang7dd2e102014-11-10 15:19:26 -05002806 gl::Program *program = state.getProgram();
2807 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002808 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002809 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002810 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002811 }
2812
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002813 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002814 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002815 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002816 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002817 }
2818
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002819 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002820 for (unsigned int uniformBlockIndex = 0;
2821 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002822 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002823 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002824 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002825 const OffsetBindingPointer<Buffer> &uniformBuffer =
2826 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002827
Geoff Lang5d124a62015-09-15 13:03:27 -04002828 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002829 {
2830 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002831 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002832 InvalidOperation()
2833 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002834 return false;
2835 }
2836
Geoff Lang5d124a62015-09-15 13:03:27 -04002837 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002838 if (uniformBufferSize == 0)
2839 {
2840 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002841 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002842 }
2843
Jamie Madill62d31cb2015-09-11 13:25:51 -04002844 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002845 {
2846 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002847 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002848 InvalidOperation()
2849 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002850 return false;
2851 }
2852 }
2853
Geoff Lange0cff192017-05-30 13:04:56 -04002854 // Do some additonal WebGL-specific validation
Jamie Madilla4595b82017-01-11 17:36:34 -05002855 if (context->getExtensions().webglCompatibility)
2856 {
Geoff Lange0cff192017-05-30 13:04:56 -04002857 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002858 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2859 {
2860 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002861 InvalidOperation()
2862 << "Rendering feedback loop formed between Framebuffer and active Texture.");
Jamie Madilla4595b82017-01-11 17:36:34 -05002863 return false;
2864 }
Geoff Lange0cff192017-05-30 13:04:56 -04002865
Geoff Lang9ab5b822017-05-30 16:19:23 -04002866 // Detect that the vertex shader input types match the attribute types
2867 if (!ValidateVertexShaderAttributeTypeMatch(context))
2868 {
2869 return false;
2870 }
2871
Geoff Lange0cff192017-05-30 13:04:56 -04002872 // Detect that the color buffer types match the fragment shader output types
2873 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2874 {
2875 return false;
2876 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002877 }
2878
Jamie Madill250d33f2014-06-06 17:09:03 -04002879 // No-op if zero count
2880 return (count > 0);
2881}
2882
Jamie Madillc1d770e2017-04-13 17:31:24 -04002883bool ValidateDrawArraysCommon(ValidationContext *context,
2884 GLenum mode,
2885 GLint first,
2886 GLsizei count,
2887 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002888{
Jamie Madillfd716582014-06-06 17:09:04 -04002889 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002890 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002891 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002892 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002893 }
2894
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002895 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002896 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002897 if (curTransformFeedback && curTransformFeedback->isActive() &&
2898 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002899 {
2900 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002901 // that does not match the current transform feedback object's draw mode (if transform
2902 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002903 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002904 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002905 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002906 }
2907
Jiajia Qind9671222016-11-29 16:30:31 +08002908 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002909 {
2910 return false;
2911 }
2912
Corentin Wallez71168a02016-12-19 15:11:18 -08002913 // Check the computation of maxVertex doesn't overflow.
2914 // - first < 0 or count < 0 have been checked as an error condition
2915 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2916 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2917 ASSERT(count > 0 && first >= 0);
2918 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2919 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002920 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002921 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002922 return false;
2923 }
2924
Corentin Wallez71168a02016-12-19 15:11:18 -08002925 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002926 {
2927 return false;
2928 }
2929
2930 return true;
2931}
2932
He Yunchaoced53ae2016-11-29 15:00:51 +08002933bool ValidateDrawArraysInstanced(Context *context,
2934 GLenum mode,
2935 GLint first,
2936 GLsizei count,
2937 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002938{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002939 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
Geoff Lang87a93302014-09-16 13:29:43 -04002940}
2941
He Yunchaoced53ae2016-11-29 15:00:51 +08002942bool ValidateDrawArraysInstancedANGLE(Context *context,
2943 GLenum mode,
2944 GLint first,
2945 GLsizei count,
2946 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002947{
Corentin Wallez170efbf2017-05-02 13:45:01 -04002948 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002949 {
2950 return false;
2951 }
2952
Corentin Wallez0dc97812017-06-22 14:38:44 -04002953 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002954}
2955
Jiajia Qind9671222016-11-29 16:30:31 +08002956bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002957{
Jamie Madill250d33f2014-06-06 17:09:03 -04002958 switch (type)
2959 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002960 case GL_UNSIGNED_BYTE:
2961 case GL_UNSIGNED_SHORT:
2962 break;
2963 case GL_UNSIGNED_INT:
2964 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2965 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002966 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002967 return false;
2968 }
2969 break;
2970 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002971 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002972 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002973 }
2974
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002975 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002976
2977 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002978 if (curTransformFeedback && curTransformFeedback->isActive() &&
2979 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002980 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002981 // It is an invalid operation to call DrawElements, DrawRangeElements or
2982 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002983 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002984 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002985 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002986 }
2987
Jiajia Qind9671222016-11-29 16:30:31 +08002988 return true;
2989}
2990
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002991bool ValidateDrawElementsCommon(ValidationContext *context,
2992 GLenum mode,
2993 GLsizei count,
2994 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002995 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002996 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002997{
2998 if (!ValidateDrawElementsBase(context, type))
2999 return false;
3000
3001 const State &state = context->getGLState();
3002
Corentin Wallez170efbf2017-05-02 13:45:01 -04003003 if (!ValidateDrawBase(context, mode, count))
3004 {
3005 return false;
3006 }
3007
Jamie Madill250d33f2014-06-06 17:09:03 -04003008 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003009 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003010 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003011 context->handleError(InvalidOperation() << "Index buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -04003012 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003013 }
3014
He Yunchaoced53ae2016-11-29 15:00:51 +08003015 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003016 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003017
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003018 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3019
3020 if (context->getExtensions().webglCompatibility)
3021 {
3022 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3023 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3024 {
3025 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3026 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3027 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003028 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003029 return false;
3030 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003031
3032 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3033 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3034 // error is generated.
3035 if (reinterpret_cast<intptr_t>(indices) < 0)
3036 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003037 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003038 return false;
3039 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003040 }
3041
3042 if (context->getExtensions().webglCompatibility ||
3043 !context->getGLState().areClientArraysEnabled())
3044 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003045 if (!elementArrayBuffer && count > 0)
3046 {
3047 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3048 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3049 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003050 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003051 return false;
3052 }
3053 }
3054
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003055 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003056 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003057 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003058 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003059 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3060 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3061 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3062 constexpr uint64_t kMaxTypeSize = 8;
3063 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3064 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3065 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003066
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003067 uint64_t typeSize = typeBytes;
3068 uint64_t elementCount = static_cast<uint64_t>(count);
3069 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3070
3071 // Doing the multiplication here is overflow-safe
3072 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3073
3074 // The offset can be any value, check for overflows
3075 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3076 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003077 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003078 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003079 return false;
3080 }
3081
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003082 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3083 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003084 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003085 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003086 return false;
3087 }
3088 }
3089 else if (!indices)
3090 {
3091 // This is an application error that would normally result in a crash,
3092 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003093 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04003094 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003095 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003096 }
3097
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003098 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill2b976812014-08-25 15:47:49 -04003099 // TODO: offer fast path, with disabled index validation.
3100 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003101 const auto &params = context->getParams<HasIndexRange>();
3102 const auto &indexRangeOpt = params.getIndexRange();
3103 if (!indexRangeOpt.valid())
Jamie Madill2b976812014-08-25 15:47:49 -04003104 {
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003105 // Unexpected error.
3106 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003107 }
3108
Jamie Madille79b1e12015-11-04 16:36:37 -05003109 // If we use an index greater than our maximum supported index range, return an error.
3110 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3111 // return an error if possible here.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003112 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
Jamie Madille79b1e12015-11-04 16:36:37 -05003113 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003114 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
Jamie Madille79b1e12015-11-04 16:36:37 -05003115 return false;
3116 }
3117
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003118 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
3119 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003120 {
3121 return false;
3122 }
3123
Geoff Lang3edfe032015-09-04 16:38:24 -04003124 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003125 return (indexRangeOpt.value().vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003126}
3127
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003128bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
3129 GLenum mode,
3130 GLsizei count,
3131 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003132 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003133 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003134{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003135 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003136}
3137
Geoff Lang3edfe032015-09-04 16:38:24 -04003138bool ValidateDrawElementsInstancedANGLE(Context *context,
3139 GLenum mode,
3140 GLsizei count,
3141 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003142 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003143 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003144{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003145 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003146 {
3147 return false;
3148 }
3149
Corentin Wallez0dc97812017-06-22 14:38:44 -04003150 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003151}
3152
He Yunchaoced53ae2016-11-29 15:00:51 +08003153bool ValidateFramebufferTextureBase(Context *context,
3154 GLenum target,
3155 GLenum attachment,
3156 GLuint texture,
3157 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003158{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003159 if (!ValidFramebufferTarget(target))
3160 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003161 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003162 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003163 }
3164
3165 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003166 {
3167 return false;
3168 }
3169
Jamie Madill55ec3b12014-07-03 10:38:57 -04003170 if (texture != 0)
3171 {
3172 gl::Texture *tex = context->getTexture(texture);
3173
Jamie Madillbe849e42017-05-02 15:49:00 -04003174 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003175 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003176 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003177 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003178 }
3179
3180 if (level < 0)
3181 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003182 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003183 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003184 }
3185 }
3186
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003187 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003188 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003189
Jamie Madill84115c92015-04-23 15:00:07 -04003190 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003191 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003192 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003193 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003194 }
3195
3196 return true;
3197}
3198
Geoff Langb1196682014-07-23 13:47:29 -04003199bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003200{
3201 if (program == 0)
3202 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003203 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003204 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003205 }
3206
Dian Xiang769769a2015-09-09 15:20:08 -07003207 gl::Program *programObject = GetValidProgram(context, program);
3208 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003209 {
3210 return false;
3211 }
3212
Jamie Madill0063c512014-08-25 15:47:53 -04003213 if (!programObject || !programObject->isLinked())
3214 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003215 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003216 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003217 }
3218
Geoff Lang7dd2e102014-11-10 15:19:26 -05003219 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003220 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003221 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003222 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003223 }
3224
Jamie Madill0063c512014-08-25 15:47:53 -04003225 return true;
3226}
3227
Geoff Langf41d0ee2016-10-07 13:04:23 -04003228static bool ValidateSizedGetUniform(Context *context,
3229 GLuint program,
3230 GLint location,
3231 GLsizei bufSize,
3232 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003233{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003234 if (length)
3235 {
3236 *length = 0;
3237 }
3238
Jamie Madill78f41802014-08-25 15:47:55 -04003239 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003240 {
Jamie Madill78f41802014-08-25 15:47:55 -04003241 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003242 }
3243
Geoff Langf41d0ee2016-10-07 13:04:23 -04003244 if (bufSize < 0)
3245 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003246 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003247 return false;
3248 }
3249
Jamie Madilla502c742014-08-28 17:19:13 -04003250 gl::Program *programObject = context->getProgram(program);
3251 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003252
Jamie Madill78f41802014-08-25 15:47:55 -04003253 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003254 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003255 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003256 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003257 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003258 context->handleError(InvalidOperation()
3259 << "bufSize of at least " << requiredBytes << " is required.");
Geoff Langb1196682014-07-23 13:47:29 -04003260 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003261 }
3262
Geoff Langf41d0ee2016-10-07 13:04:23 -04003263 if (length)
3264 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003265 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003266 }
3267
Jamie Madill0063c512014-08-25 15:47:53 -04003268 return true;
3269}
3270
He Yunchaoced53ae2016-11-29 15:00:51 +08003271bool ValidateGetnUniformfvEXT(Context *context,
3272 GLuint program,
3273 GLint location,
3274 GLsizei bufSize,
3275 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003276{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003277 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003278}
3279
He Yunchaoced53ae2016-11-29 15:00:51 +08003280bool ValidateGetnUniformivEXT(Context *context,
3281 GLuint program,
3282 GLint location,
3283 GLsizei bufSize,
3284 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003285{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003286 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3287}
3288
3289bool ValidateGetUniformfvRobustANGLE(Context *context,
3290 GLuint program,
3291 GLint location,
3292 GLsizei bufSize,
3293 GLsizei *length,
3294 GLfloat *params)
3295{
3296 if (!ValidateRobustEntryPoint(context, bufSize))
3297 {
3298 return false;
3299 }
3300
3301 // bufSize is validated in ValidateSizedGetUniform
3302 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3303}
3304
3305bool ValidateGetUniformivRobustANGLE(Context *context,
3306 GLuint program,
3307 GLint location,
3308 GLsizei bufSize,
3309 GLsizei *length,
3310 GLint *params)
3311{
3312 if (!ValidateRobustEntryPoint(context, bufSize))
3313 {
3314 return false;
3315 }
3316
3317 // bufSize is validated in ValidateSizedGetUniform
3318 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3319}
3320
3321bool ValidateGetUniformuivRobustANGLE(Context *context,
3322 GLuint program,
3323 GLint location,
3324 GLsizei bufSize,
3325 GLsizei *length,
3326 GLuint *params)
3327{
3328 if (!ValidateRobustEntryPoint(context, bufSize))
3329 {
3330 return false;
3331 }
3332
3333 if (context->getClientMajorVersion() < 3)
3334 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003335 context->handleError(InvalidOperation() << "Entry point requires at least OpenGL ES 3.0.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003336 return false;
3337 }
3338
3339 // bufSize is validated in ValidateSizedGetUniform
3340 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003341}
3342
He Yunchaoced53ae2016-11-29 15:00:51 +08003343bool ValidateDiscardFramebufferBase(Context *context,
3344 GLenum target,
3345 GLsizei numAttachments,
3346 const GLenum *attachments,
3347 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003348{
3349 if (numAttachments < 0)
3350 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003351 context->handleError(InvalidValue() << "numAttachments must not be less than zero");
Austin Kinross08332632015-05-05 13:35:47 -07003352 return false;
3353 }
3354
3355 for (GLsizei i = 0; i < numAttachments; ++i)
3356 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003357 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003358 {
3359 if (defaultFramebuffer)
3360 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003361 context->handleError(InvalidEnum()
3362 << "Invalid attachment when the default framebuffer is bound");
Austin Kinross08332632015-05-05 13:35:47 -07003363 return false;
3364 }
3365
3366 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3367 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003368 context->handleError(InvalidOperation() << "Requested color attachment is "
3369 "greater than the maximum supported "
3370 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003371 return false;
3372 }
3373 }
3374 else
3375 {
3376 switch (attachments[i])
3377 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003378 case GL_DEPTH_ATTACHMENT:
3379 case GL_STENCIL_ATTACHMENT:
3380 case GL_DEPTH_STENCIL_ATTACHMENT:
3381 if (defaultFramebuffer)
3382 {
3383 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003384 InvalidEnum()
3385 << "Invalid attachment when the default framebuffer is bound");
He Yunchaoced53ae2016-11-29 15:00:51 +08003386 return false;
3387 }
3388 break;
3389 case GL_COLOR:
3390 case GL_DEPTH:
3391 case GL_STENCIL:
3392 if (!defaultFramebuffer)
3393 {
3394 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003395 InvalidEnum()
3396 << "Invalid attachment when the default framebuffer is not bound");
He Yunchaoced53ae2016-11-29 15:00:51 +08003397 return false;
3398 }
3399 break;
3400 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003401 context->handleError(InvalidEnum() << "Invalid attachment");
Austin Kinross08332632015-05-05 13:35:47 -07003402 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003403 }
3404 }
3405 }
3406
3407 return true;
3408}
3409
Austin Kinross6ee1e782015-05-29 17:05:37 -07003410bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3411{
3412 // Note that debug marker calls must not set error state
3413
3414 if (length < 0)
3415 {
3416 return false;
3417 }
3418
3419 if (marker == nullptr)
3420 {
3421 return false;
3422 }
3423
3424 return true;
3425}
3426
3427bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3428{
3429 // Note that debug marker calls must not set error state
3430
3431 if (length < 0)
3432 {
3433 return false;
3434 }
3435
3436 if (length > 0 && marker == nullptr)
3437 {
3438 return false;
3439 }
3440
3441 return true;
3442}
3443
Geoff Langdcab33b2015-07-21 13:03:16 -04003444bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003445 GLenum target,
3446 egl::Image *image)
3447{
Geoff Langa8406172015-07-21 16:53:39 -04003448 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3449 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003450 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003451 return false;
3452 }
3453
3454 switch (target)
3455 {
3456 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003457 if (!context->getExtensions().eglImage)
3458 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003459 context->handleError(InvalidEnum()
3460 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003461 }
3462 break;
3463
3464 case GL_TEXTURE_EXTERNAL_OES:
3465 if (!context->getExtensions().eglImageExternal)
3466 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003467 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3468 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003469 }
Geoff Langa8406172015-07-21 16:53:39 -04003470 break;
3471
3472 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003473 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003474 return false;
3475 }
3476
Jamie Madill61e16b42017-06-19 11:13:23 -04003477 ASSERT(context->getCurrentDisplay());
3478 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003479 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003480 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003481 return false;
3482 }
3483
3484 if (image->getSamples() > 0)
3485 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003486 context->handleError(InvalidOperation()
3487 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003488 return false;
3489 }
3490
Geoff Langca271392017-04-05 12:30:00 -04003491 const TextureCaps &textureCaps =
3492 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003493 if (!textureCaps.texturable)
3494 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003495 context->handleError(InvalidOperation()
3496 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003497 return false;
3498 }
3499
Geoff Langdcab33b2015-07-21 13:03:16 -04003500 return true;
3501}
3502
3503bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003504 GLenum target,
3505 egl::Image *image)
3506{
Geoff Langa8406172015-07-21 16:53:39 -04003507 if (!context->getExtensions().eglImage)
3508 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003509 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003510 return false;
3511 }
3512
3513 switch (target)
3514 {
3515 case GL_RENDERBUFFER:
3516 break;
3517
3518 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003519 context->handleError(InvalidEnum() << "invalid renderbuffer target.");
Geoff Langa8406172015-07-21 16:53:39 -04003520 return false;
3521 }
3522
Jamie Madill61e16b42017-06-19 11:13:23 -04003523 ASSERT(context->getCurrentDisplay());
3524 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003525 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003526 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003527 return false;
3528 }
3529
Geoff Langca271392017-04-05 12:30:00 -04003530 const TextureCaps &textureCaps =
3531 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003532 if (!textureCaps.renderable)
3533 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003534 context->handleError(InvalidOperation()
3535 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003536 return false;
3537 }
3538
Geoff Langdcab33b2015-07-21 13:03:16 -04003539 return true;
3540}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003541
3542bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3543{
Geoff Lang36167ab2015-12-07 10:27:14 -05003544 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003545 {
3546 // The default VAO should always exist
3547 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003548 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003549 return false;
3550 }
3551
3552 return true;
3553}
3554
Geoff Langc5629752015-12-07 16:29:04 -05003555bool ValidateProgramBinaryBase(Context *context,
3556 GLuint program,
3557 GLenum binaryFormat,
3558 const void *binary,
3559 GLint length)
3560{
3561 Program *programObject = GetValidProgram(context, program);
3562 if (programObject == nullptr)
3563 {
3564 return false;
3565 }
3566
3567 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3568 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3569 programBinaryFormats.end())
3570 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003571 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003572 return false;
3573 }
3574
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003575 if (context->hasActiveTransformFeedback(program))
3576 {
3577 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003578 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3579 "is associated with an active transform "
3580 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003581 return false;
3582 }
3583
Geoff Langc5629752015-12-07 16:29:04 -05003584 return true;
3585}
3586
3587bool ValidateGetProgramBinaryBase(Context *context,
3588 GLuint program,
3589 GLsizei bufSize,
3590 GLsizei *length,
3591 GLenum *binaryFormat,
3592 void *binary)
3593{
3594 Program *programObject = GetValidProgram(context, program);
3595 if (programObject == nullptr)
3596 {
3597 return false;
3598 }
3599
3600 if (!programObject->isLinked())
3601 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003602 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003603 return false;
3604 }
3605
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003606 if (context->getCaps().programBinaryFormats.empty())
3607 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003608 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003609 return false;
3610 }
3611
Geoff Langc5629752015-12-07 16:29:04 -05003612 return true;
3613}
Jamie Madillc29968b2016-01-20 11:17:23 -05003614
Jamie Madillc29968b2016-01-20 11:17:23 -05003615bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3616{
3617 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3618 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3619 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003620 context->handleError(InvalidValue()
3621 << "n must be non-negative and no greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003622 return false;
3623 }
3624
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003625 ASSERT(context->getGLState().getDrawFramebuffer());
3626 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003627 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3628
3629 // This should come first before the check for the default frame buffer
3630 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3631 // rather than INVALID_OPERATION
3632 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3633 {
3634 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3635
3636 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003637 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3638 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003639 {
3640 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003641 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3642 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3643 // 3.1 is still a bit ambiguous about the error, but future specs are
3644 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003645 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003646 return false;
3647 }
3648 else if (bufs[colorAttachment] >= maxColorAttachment)
3649 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003650 context->handleError(InvalidOperation()
3651 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003652 return false;
3653 }
3654 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3655 frameBufferId != 0)
3656 {
3657 // INVALID_OPERATION-GL is bound to buffer and ith argument
3658 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003659 context->handleError(InvalidOperation()
3660 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003661 return false;
3662 }
3663 }
3664
3665 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3666 // and n is not 1 or bufs is bound to value other than BACK and NONE
3667 if (frameBufferId == 0)
3668 {
3669 if (n != 1)
3670 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003671 context->handleError(InvalidOperation()
3672 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003673 return false;
3674 }
3675
3676 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3677 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003678 context->handleError(
3679 InvalidOperation()
3680 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003681 return false;
3682 }
3683 }
3684
3685 return true;
3686}
3687
Geoff Lang496c02d2016-10-20 11:38:11 -07003688bool ValidateGetBufferPointervBase(Context *context,
3689 GLenum target,
3690 GLenum pname,
3691 GLsizei *length,
3692 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003693{
Geoff Lang496c02d2016-10-20 11:38:11 -07003694 if (length)
3695 {
3696 *length = 0;
3697 }
3698
3699 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3700 {
3701 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003702 InvalidOperation()
3703 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003704 return false;
3705 }
3706
Olli Etuaho4f667482016-03-30 15:56:35 +03003707 if (!ValidBufferTarget(context, target))
3708 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003709 context->handleError(InvalidEnum() << "Buffer target not valid: 0x" << std::hex
3710 << std::uppercase << target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003711 return false;
3712 }
3713
Geoff Lang496c02d2016-10-20 11:38:11 -07003714 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003715 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003716 case GL_BUFFER_MAP_POINTER:
3717 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003718
Geoff Lang496c02d2016-10-20 11:38:11 -07003719 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003720 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003721 return false;
3722 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003723
3724 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3725 // target bound to zero generate an INVALID_OPERATION error."
3726 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003727 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003728 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003729 context->handleError(InvalidOperation()
3730 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003731 return false;
3732 }
3733
Geoff Lang496c02d2016-10-20 11:38:11 -07003734 if (length)
3735 {
3736 *length = 1;
3737 }
3738
Olli Etuaho4f667482016-03-30 15:56:35 +03003739 return true;
3740}
3741
3742bool ValidateUnmapBufferBase(Context *context, GLenum target)
3743{
3744 if (!ValidBufferTarget(context, target))
3745 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003746 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003747 return false;
3748 }
3749
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003750 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003751
3752 if (buffer == nullptr || !buffer->isMapped())
3753 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003754 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003755 return false;
3756 }
3757
3758 return true;
3759}
3760
3761bool ValidateMapBufferRangeBase(Context *context,
3762 GLenum target,
3763 GLintptr offset,
3764 GLsizeiptr length,
3765 GLbitfield access)
3766{
3767 if (!ValidBufferTarget(context, target))
3768 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003769 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003770 return false;
3771 }
3772
Brandon Jones6cad5662017-06-14 13:25:13 -07003773 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003774 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003775 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3776 return false;
3777 }
3778
3779 if (length < 0)
3780 {
3781 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003782 return false;
3783 }
3784
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003785 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003786
3787 if (!buffer)
3788 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003789 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003790 return false;
3791 }
3792
3793 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003794 CheckedNumeric<size_t> checkedOffset(offset);
3795 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003796
Jamie Madille2e406c2016-06-02 13:04:10 -04003797 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003798 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003799 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003800 return false;
3801 }
3802
3803 // Check for invalid bits in the mask
3804 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3805 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3806 GL_MAP_UNSYNCHRONIZED_BIT;
3807
3808 if (access & ~(allAccessBits))
3809 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003810 context->handleError(InvalidValue()
3811 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003812 return false;
3813 }
3814
3815 if (length == 0)
3816 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003817 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003818 return false;
3819 }
3820
3821 if (buffer->isMapped())
3822 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003823 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003824 return false;
3825 }
3826
3827 // Check for invalid bit combinations
3828 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3829 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003830 context->handleError(InvalidOperation()
3831 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003832 return false;
3833 }
3834
3835 GLbitfield writeOnlyBits =
3836 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3837
3838 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3839 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003840 context->handleError(InvalidOperation()
3841 << "Invalid access bits when mapping buffer for reading: 0x"
3842 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003843 return false;
3844 }
3845
3846 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3847 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003848 context->handleError(
3849 InvalidOperation()
3850 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003851 return false;
3852 }
3853 return true;
3854}
3855
3856bool ValidateFlushMappedBufferRangeBase(Context *context,
3857 GLenum target,
3858 GLintptr offset,
3859 GLsizeiptr length)
3860{
Brandon Jones6cad5662017-06-14 13:25:13 -07003861 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003862 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003863 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3864 return false;
3865 }
3866
3867 if (length < 0)
3868 {
3869 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003870 return false;
3871 }
3872
3873 if (!ValidBufferTarget(context, target))
3874 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003875 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003876 return false;
3877 }
3878
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003879 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003880
3881 if (buffer == nullptr)
3882 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003883 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003884 return false;
3885 }
3886
3887 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3888 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003889 context->handleError(InvalidOperation()
3890 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003891 return false;
3892 }
3893
3894 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003895 CheckedNumeric<size_t> checkedOffset(offset);
3896 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003897
Jamie Madille2e406c2016-06-02 13:04:10 -04003898 if (!checkedSize.IsValid() ||
3899 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003900 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003901 context->handleError(InvalidValue()
3902 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003903 return false;
3904 }
3905
3906 return true;
3907}
3908
Olli Etuaho41997e72016-03-10 13:38:39 +02003909bool ValidateGenOrDelete(Context *context, GLint n)
3910{
3911 if (n < 0)
3912 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003913 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003914 return false;
3915 }
3916 return true;
3917}
3918
Geoff Langff5b2d52016-09-07 11:32:23 -04003919bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3920{
3921 if (!context->getExtensions().robustClientMemory)
3922 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003923 context->handleError(InvalidOperation()
3924 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003925 return false;
3926 }
3927
3928 if (bufSize < 0)
3929 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003930 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003931 return false;
3932 }
3933
3934 return true;
3935}
3936
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003937bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3938{
3939 if (bufSize < numParams)
3940 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003941 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3942 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003943 return false;
3944 }
3945
3946 return true;
3947}
3948
Jamie Madillbe849e42017-05-02 15:49:00 -04003949bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3950 GLenum target,
3951 GLenum attachment,
3952 GLenum pname,
3953 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003954{
3955 // Only one parameter is returned from glGetFramebufferAttachmentParameteriv
Yunchao He33151a52017-04-13 09:58:17 +08003956 if (numParams)
3957 {
3958 *numParams = 1;
3959 }
Geoff Langff5b2d52016-09-07 11:32:23 -04003960
3961 if (!ValidFramebufferTarget(target))
3962 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003963 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003964 return false;
3965 }
3966
3967 int clientVersion = context->getClientMajorVersion();
3968
3969 switch (pname)
3970 {
3971 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3972 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3973 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3974 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3975 break;
3976
3977 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3978 if (clientVersion < 3 && !context->getExtensions().sRGB)
3979 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003980 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003981 return false;
3982 }
3983 break;
3984
3985 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3986 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3987 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3988 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3989 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3990 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3991 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3992 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3993 if (clientVersion < 3)
3994 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003995 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003996 return false;
3997 }
3998 break;
3999
4000 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004001 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004002 return false;
4003 }
4004
4005 // Determine if the attachment is a valid enum
4006 switch (attachment)
4007 {
4008 case GL_BACK:
4009 case GL_FRONT:
4010 case GL_DEPTH:
4011 case GL_STENCIL:
4012 case GL_DEPTH_STENCIL_ATTACHMENT:
4013 if (clientVersion < 3)
4014 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004015 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004016 return false;
4017 }
4018 break;
4019
4020 case GL_DEPTH_ATTACHMENT:
4021 case GL_STENCIL_ATTACHMENT:
4022 break;
4023
4024 default:
4025 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4026 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4027 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004028 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004029 return false;
4030 }
4031 break;
4032 }
4033
4034 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4035 ASSERT(framebuffer);
4036
4037 if (framebuffer->id() == 0)
4038 {
4039 if (clientVersion < 3)
4040 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004041 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004042 return false;
4043 }
4044
4045 switch (attachment)
4046 {
4047 case GL_BACK:
4048 case GL_DEPTH:
4049 case GL_STENCIL:
4050 break;
4051
4052 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004053 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FramebufferInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004054 return false;
4055 }
4056 }
4057 else
4058 {
4059 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4060 {
4061 // Valid attachment query
4062 }
4063 else
4064 {
4065 switch (attachment)
4066 {
4067 case GL_DEPTH_ATTACHMENT:
4068 case GL_STENCIL_ATTACHMENT:
4069 break;
4070
4071 case GL_DEPTH_STENCIL_ATTACHMENT:
4072 if (!framebuffer->hasValidDepthStencil())
4073 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004074 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004075 return false;
4076 }
4077 break;
4078
4079 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004080 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FramebufferInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004081 return false;
4082 }
4083 }
4084 }
4085
4086 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4087 if (attachmentObject)
4088 {
4089 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4090 attachmentObject->type() == GL_TEXTURE ||
4091 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4092
4093 switch (pname)
4094 {
4095 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4096 if (attachmentObject->type() != GL_RENDERBUFFER &&
4097 attachmentObject->type() != GL_TEXTURE)
4098 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004099 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004100 return false;
4101 }
4102 break;
4103
4104 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4105 if (attachmentObject->type() != GL_TEXTURE)
4106 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004107 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004108 return false;
4109 }
4110 break;
4111
4112 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4113 if (attachmentObject->type() != GL_TEXTURE)
4114 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004115 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004116 return false;
4117 }
4118 break;
4119
4120 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4121 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4122 {
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 break;
4127
4128 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4129 if (attachmentObject->type() != GL_TEXTURE)
4130 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004131 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004132 return false;
4133 }
4134 break;
4135
4136 default:
4137 break;
4138 }
4139 }
4140 else
4141 {
4142 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4143 // is NONE, then querying any other pname will generate INVALID_ENUM.
4144
4145 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4146 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4147 // INVALID_OPERATION for all other pnames
4148
4149 switch (pname)
4150 {
4151 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4152 break;
4153
4154 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4155 if (clientVersion < 3)
4156 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004157 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
4158 InvalidRenderbufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004159 return false;
4160 }
4161 break;
4162
4163 default:
4164 if (clientVersion < 3)
4165 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004166 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
4167 InvalidRenderbufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004168 return false;
4169 }
4170 else
4171 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004172 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
4173 InvalidRenderbufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004174 return false;
4175 }
4176 }
4177 }
4178
4179 return true;
4180}
4181
4182bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4183 GLenum target,
4184 GLenum attachment,
4185 GLenum pname,
4186 GLsizei bufSize,
4187 GLsizei *numParams)
4188{
4189 if (!ValidateRobustEntryPoint(context, bufSize))
4190 {
4191 return false;
4192 }
4193
Jamie Madillbe849e42017-05-02 15:49:00 -04004194 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4195 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004196 {
4197 return false;
4198 }
4199
4200 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4201 {
4202 return false;
4203 }
4204
4205 return true;
4206}
4207
Geoff Langff5b2d52016-09-07 11:32:23 -04004208bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4209 GLenum target,
4210 GLenum pname,
4211 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004212 GLsizei *length,
4213 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004214{
4215 if (!ValidateRobustEntryPoint(context, bufSize))
4216 {
4217 return false;
4218 }
4219
Geoff Langebebe1c2016-10-14 12:01:31 -04004220 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004221 {
4222 return false;
4223 }
4224
Geoff Langebebe1c2016-10-14 12:01:31 -04004225 if (!ValidateRobustBufferSize(context, bufSize, *length))
4226 {
4227 return false;
4228 }
4229
4230 return true;
4231}
4232
4233bool ValidateGetBufferParameteri64v(ValidationContext *context,
4234 GLenum target,
4235 GLenum pname,
4236 GLint64 *params)
4237{
4238 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4239}
4240
4241bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4242 GLenum target,
4243 GLenum pname,
4244 GLsizei bufSize,
4245 GLsizei *length,
4246 GLint64 *params)
4247{
4248 if (!ValidateRobustEntryPoint(context, bufSize))
4249 {
4250 return false;
4251 }
4252
4253 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4254 {
4255 return false;
4256 }
4257
4258 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004259 {
4260 return false;
4261 }
4262
4263 return true;
4264}
4265
Jamie Madillbe849e42017-05-02 15:49:00 -04004266bool ValidateGetProgramivBase(ValidationContext *context,
4267 GLuint program,
4268 GLenum pname,
4269 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004270{
4271 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004272 if (numParams)
4273 {
4274 *numParams = 1;
4275 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004276
4277 Program *programObject = GetValidProgram(context, program);
4278 if (!programObject)
4279 {
4280 return false;
4281 }
4282
4283 switch (pname)
4284 {
4285 case GL_DELETE_STATUS:
4286 case GL_LINK_STATUS:
4287 case GL_VALIDATE_STATUS:
4288 case GL_INFO_LOG_LENGTH:
4289 case GL_ATTACHED_SHADERS:
4290 case GL_ACTIVE_ATTRIBUTES:
4291 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4292 case GL_ACTIVE_UNIFORMS:
4293 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4294 break;
4295
4296 case GL_PROGRAM_BINARY_LENGTH:
4297 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4298 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004299 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4300 "requires GL_OES_get_program_binary or "
4301 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004302 return false;
4303 }
4304 break;
4305
4306 case GL_ACTIVE_UNIFORM_BLOCKS:
4307 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4308 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4309 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4310 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4311 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4312 if (context->getClientMajorVersion() < 3)
4313 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004314 context->handleError(InvalidEnum() << "Querying requires at least ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004315 return false;
4316 }
4317 break;
4318
Yunchao He61afff12017-03-14 15:34:03 +08004319 case GL_PROGRAM_SEPARABLE:
4320 if (context->getClientVersion() < Version(3, 1))
4321 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004322 context->handleError(InvalidEnum() << "Querying requires at least ES 3.1.");
Yunchao He61afff12017-03-14 15:34:03 +08004323 return false;
4324 }
4325 break;
4326
Geoff Langff5b2d52016-09-07 11:32:23 -04004327 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004328 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004329 return false;
4330 }
4331
4332 return true;
4333}
4334
4335bool ValidateGetProgramivRobustANGLE(Context *context,
4336 GLuint program,
4337 GLenum pname,
4338 GLsizei bufSize,
4339 GLsizei *numParams)
4340{
4341 if (!ValidateRobustEntryPoint(context, bufSize))
4342 {
4343 return false;
4344 }
4345
Jamie Madillbe849e42017-05-02 15:49:00 -04004346 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004347 {
4348 return false;
4349 }
4350
4351 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4352 {
4353 return false;
4354 }
4355
4356 return true;
4357}
4358
Geoff Lang740d9022016-10-07 11:20:52 -04004359bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4360 GLenum target,
4361 GLenum pname,
4362 GLsizei bufSize,
4363 GLsizei *length,
4364 GLint *params)
4365{
4366 if (!ValidateRobustEntryPoint(context, bufSize))
4367 {
4368 return false;
4369 }
4370
4371 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4372 {
4373 return false;
4374 }
4375
4376 if (!ValidateRobustBufferSize(context, bufSize, *length))
4377 {
4378 return false;
4379 }
4380
4381 return true;
4382}
4383
Geoff Langd7d0ed32016-10-07 11:33:51 -04004384bool ValidateGetShaderivRobustANGLE(Context *context,
4385 GLuint shader,
4386 GLenum pname,
4387 GLsizei bufSize,
4388 GLsizei *length,
4389 GLint *params)
4390{
4391 if (!ValidateRobustEntryPoint(context, bufSize))
4392 {
4393 return false;
4394 }
4395
4396 if (!ValidateGetShaderivBase(context, shader, pname, length))
4397 {
4398 return false;
4399 }
4400
4401 if (!ValidateRobustBufferSize(context, bufSize, *length))
4402 {
4403 return false;
4404 }
4405
4406 return true;
4407}
4408
Geoff Langc1984ed2016-10-07 12:41:00 -04004409bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4410 GLenum target,
4411 GLenum pname,
4412 GLsizei bufSize,
4413 GLsizei *length,
4414 GLfloat *params)
4415{
4416 if (!ValidateRobustEntryPoint(context, bufSize))
4417 {
4418 return false;
4419 }
4420
4421 if (!ValidateGetTexParameterBase(context, target, pname, length))
4422 {
4423 return false;
4424 }
4425
4426 if (!ValidateRobustBufferSize(context, bufSize, *length))
4427 {
4428 return false;
4429 }
4430
4431 return true;
4432}
4433
Geoff Langc1984ed2016-10-07 12:41:00 -04004434bool ValidateGetTexParameterivRobustANGLE(Context *context,
4435 GLenum target,
4436 GLenum pname,
4437 GLsizei bufSize,
4438 GLsizei *length,
4439 GLint *params)
4440{
4441 if (!ValidateRobustEntryPoint(context, bufSize))
4442 {
4443 return false;
4444 }
4445
4446 if (!ValidateGetTexParameterBase(context, target, pname, length))
4447 {
4448 return false;
4449 }
4450
4451 if (!ValidateRobustBufferSize(context, bufSize, *length))
4452 {
4453 return false;
4454 }
4455
4456 return true;
4457}
4458
Geoff Langc1984ed2016-10-07 12:41:00 -04004459bool ValidateTexParameterfvRobustANGLE(Context *context,
4460 GLenum target,
4461 GLenum pname,
4462 GLsizei bufSize,
4463 const GLfloat *params)
4464{
4465 if (!ValidateRobustEntryPoint(context, bufSize))
4466 {
4467 return false;
4468 }
4469
4470 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4471}
4472
Geoff Langc1984ed2016-10-07 12:41:00 -04004473bool ValidateTexParameterivRobustANGLE(Context *context,
4474 GLenum target,
4475 GLenum pname,
4476 GLsizei bufSize,
4477 const GLint *params)
4478{
4479 if (!ValidateRobustEntryPoint(context, bufSize))
4480 {
4481 return false;
4482 }
4483
4484 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4485}
4486
4487bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4488{
4489 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4490}
4491
4492bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4493 GLuint sampler,
4494 GLenum pname,
4495 GLuint bufSize,
4496 GLsizei *length,
4497 GLfloat *params)
4498{
4499 if (!ValidateRobustEntryPoint(context, bufSize))
4500 {
4501 return false;
4502 }
4503
4504 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4505 {
4506 return false;
4507 }
4508
4509 if (!ValidateRobustBufferSize(context, bufSize, *length))
4510 {
4511 return false;
4512 }
4513
4514 return true;
4515}
4516
4517bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4518{
4519 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4520}
4521
4522bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4523 GLuint sampler,
4524 GLenum pname,
4525 GLuint bufSize,
4526 GLsizei *length,
4527 GLint *params)
4528{
4529 if (!ValidateRobustEntryPoint(context, bufSize))
4530 {
4531 return false;
4532 }
4533
4534 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4535 {
4536 return false;
4537 }
4538
4539 if (!ValidateRobustBufferSize(context, bufSize, *length))
4540 {
4541 return false;
4542 }
4543
4544 return true;
4545}
4546
4547bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4548{
4549 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4550}
4551
4552bool ValidateSamplerParameterfv(Context *context,
4553 GLuint sampler,
4554 GLenum pname,
4555 const GLfloat *params)
4556{
4557 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4558}
4559
4560bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4561 GLuint sampler,
4562 GLenum pname,
4563 GLsizei bufSize,
4564 const GLfloat *params)
4565{
4566 if (!ValidateRobustEntryPoint(context, bufSize))
4567 {
4568 return false;
4569 }
4570
4571 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4572}
4573
4574bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4575{
4576 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4577}
4578
4579bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4580{
4581 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4582}
4583
4584bool ValidateSamplerParameterivRobustANGLE(Context *context,
4585 GLuint sampler,
4586 GLenum pname,
4587 GLsizei bufSize,
4588 const GLint *params)
4589{
4590 if (!ValidateRobustEntryPoint(context, bufSize))
4591 {
4592 return false;
4593 }
4594
4595 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4596}
4597
Geoff Lang0b031062016-10-13 14:30:04 -04004598bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4599 GLuint index,
4600 GLenum pname,
4601 GLsizei bufSize,
4602 GLsizei *length,
4603 GLfloat *params)
4604{
4605 if (!ValidateRobustEntryPoint(context, bufSize))
4606 {
4607 return false;
4608 }
4609
4610 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4611 {
4612 return false;
4613 }
4614
4615 if (!ValidateRobustBufferSize(context, bufSize, *length))
4616 {
4617 return false;
4618 }
4619
4620 return true;
4621}
4622
Geoff Lang0b031062016-10-13 14:30:04 -04004623bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4624 GLuint index,
4625 GLenum pname,
4626 GLsizei bufSize,
4627 GLsizei *length,
4628 GLint *params)
4629{
4630 if (!ValidateRobustEntryPoint(context, bufSize))
4631 {
4632 return false;
4633 }
4634
4635 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4636 {
4637 return false;
4638 }
4639
4640 if (!ValidateRobustBufferSize(context, bufSize, *length))
4641 {
4642 return false;
4643 }
4644
4645 return true;
4646}
4647
Geoff Lang0b031062016-10-13 14:30:04 -04004648bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4649 GLuint index,
4650 GLenum pname,
4651 GLsizei bufSize,
4652 GLsizei *length,
4653 void **pointer)
4654{
4655 if (!ValidateRobustEntryPoint(context, bufSize))
4656 {
4657 return false;
4658 }
4659
4660 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4661 {
4662 return false;
4663 }
4664
4665 if (!ValidateRobustBufferSize(context, bufSize, *length))
4666 {
4667 return false;
4668 }
4669
4670 return true;
4671}
4672
4673bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
4674{
4675 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4676}
4677
4678bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4679 GLuint index,
4680 GLenum pname,
4681 GLsizei bufSize,
4682 GLsizei *length,
4683 GLint *params)
4684{
4685 if (!ValidateRobustEntryPoint(context, bufSize))
4686 {
4687 return false;
4688 }
4689
4690 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4691 {
4692 return false;
4693 }
4694
4695 if (!ValidateRobustBufferSize(context, bufSize, *length))
4696 {
4697 return false;
4698 }
4699
4700 return true;
4701}
4702
4703bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
4704{
4705 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4706}
4707
4708bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4709 GLuint index,
4710 GLenum pname,
4711 GLsizei bufSize,
4712 GLsizei *length,
4713 GLuint *params)
4714{
4715 if (!ValidateRobustEntryPoint(context, bufSize))
4716 {
4717 return false;
4718 }
4719
4720 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4721 {
4722 return false;
4723 }
4724
4725 if (!ValidateRobustBufferSize(context, bufSize, *length))
4726 {
4727 return false;
4728 }
4729
4730 return true;
4731}
4732
Geoff Lang6899b872016-10-14 11:30:13 -04004733bool ValidateGetActiveUniformBlockiv(Context *context,
4734 GLuint program,
4735 GLuint uniformBlockIndex,
4736 GLenum pname,
4737 GLint *params)
4738{
4739 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
4740}
4741
4742bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4743 GLuint program,
4744 GLuint uniformBlockIndex,
4745 GLenum pname,
4746 GLsizei bufSize,
4747 GLsizei *length,
4748 GLint *params)
4749{
4750 if (!ValidateRobustEntryPoint(context, bufSize))
4751 {
4752 return false;
4753 }
4754
4755 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4756 {
4757 return false;
4758 }
4759
4760 if (!ValidateRobustBufferSize(context, bufSize, *length))
4761 {
4762 return false;
4763 }
4764
4765 return true;
4766}
4767
Geoff Lang0a9661f2016-10-20 10:59:20 -07004768bool ValidateGetInternalFormativ(Context *context,
4769 GLenum target,
4770 GLenum internalformat,
4771 GLenum pname,
4772 GLsizei bufSize,
4773 GLint *params)
4774{
4775 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4776 nullptr);
4777}
4778
4779bool ValidateGetInternalFormativRobustANGLE(Context *context,
4780 GLenum target,
4781 GLenum internalformat,
4782 GLenum pname,
4783 GLsizei bufSize,
4784 GLsizei *length,
4785 GLint *params)
4786{
4787 if (!ValidateRobustEntryPoint(context, bufSize))
4788 {
4789 return false;
4790 }
4791
4792 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4793 {
4794 return false;
4795 }
4796
4797 if (!ValidateRobustBufferSize(context, bufSize, *length))
4798 {
4799 return false;
4800 }
4801
4802 return true;
4803}
4804
Shao80957d92017-02-20 21:25:59 +08004805bool ValidateVertexFormatBase(ValidationContext *context,
4806 GLuint attribIndex,
4807 GLint size,
4808 GLenum type,
4809 GLboolean pureInteger)
4810{
4811 const Caps &caps = context->getCaps();
4812 if (attribIndex >= caps.maxVertexAttributes)
4813 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004814 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Shao80957d92017-02-20 21:25:59 +08004815 return false;
4816 }
4817
4818 if (size < 1 || size > 4)
4819 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004820 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004821 return false;
Shao80957d92017-02-20 21:25:59 +08004822 }
4823
4824 switch (type)
4825 {
4826 case GL_BYTE:
4827 case GL_UNSIGNED_BYTE:
4828 case GL_SHORT:
4829 case GL_UNSIGNED_SHORT:
4830 break;
4831
4832 case GL_INT:
4833 case GL_UNSIGNED_INT:
4834 if (context->getClientMajorVersion() < 3)
4835 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004836 context->handleError(InvalidEnum()
4837 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004838 return false;
4839 }
4840 break;
4841
4842 case GL_FIXED:
4843 case GL_FLOAT:
4844 if (pureInteger)
4845 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004846 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004847 return false;
4848 }
4849 break;
4850
4851 case GL_HALF_FLOAT:
4852 if (context->getClientMajorVersion() < 3)
4853 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004854 context->handleError(InvalidEnum()
4855 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004856 return false;
4857 }
4858 if (pureInteger)
4859 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004860 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004861 return false;
4862 }
4863 break;
4864
4865 case GL_INT_2_10_10_10_REV:
4866 case GL_UNSIGNED_INT_2_10_10_10_REV:
4867 if (context->getClientMajorVersion() < 3)
4868 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004869 context->handleError(InvalidEnum()
4870 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004871 return false;
4872 }
4873 if (pureInteger)
4874 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004875 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004876 return false;
4877 }
4878 if (size != 4)
4879 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004880 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4881 "UNSIGNED_INT_2_10_10_10_REV and "
4882 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004883 return false;
4884 }
4885 break;
4886
4887 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004888 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004889 return false;
4890 }
4891
4892 return true;
4893}
4894
Geoff Lang76e65652017-03-27 14:58:02 -04004895// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4896// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4897// specified clear value and the type of a buffer that is being cleared generates an
4898// INVALID_OPERATION error instead of producing undefined results
4899bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4900 GLint drawbuffer,
4901 const GLenum *validComponentTypes,
4902 size_t validComponentTypeCount)
4903{
4904 const FramebufferAttachment *attachment =
4905 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4906 if (attachment)
4907 {
4908 GLenum componentType = attachment->getFormat().info->componentType;
4909 const GLenum *end = validComponentTypes + validComponentTypeCount;
4910 if (std::find(validComponentTypes, end, componentType) == end)
4911 {
4912 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004913 InvalidOperation()
4914 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004915 return false;
4916 }
4917 }
4918
4919 return true;
4920}
4921
Corentin Wallezb2931602017-04-11 15:58:57 -04004922bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4923 GLsizei imageSize,
4924 GLsizei dataSize)
4925{
4926 if (!ValidateRobustEntryPoint(context, dataSize))
4927 {
4928 return false;
4929 }
4930
4931 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
4932 if (pixelUnpackBuffer == nullptr)
4933 {
4934 if (dataSize < imageSize)
4935 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004936 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004937 }
4938 }
4939 return true;
4940}
4941
Jamie Madillbe849e42017-05-02 15:49:00 -04004942bool ValidateGetBufferParameterBase(ValidationContext *context,
4943 GLenum target,
4944 GLenum pname,
4945 bool pointerVersion,
4946 GLsizei *numParams)
4947{
4948 if (numParams)
4949 {
4950 *numParams = 0;
4951 }
4952
4953 if (!ValidBufferTarget(context, target))
4954 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004955 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004956 return false;
4957 }
4958
4959 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4960 if (!buffer)
4961 {
4962 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004963 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004964 return false;
4965 }
4966
4967 const Extensions &extensions = context->getExtensions();
4968
4969 switch (pname)
4970 {
4971 case GL_BUFFER_USAGE:
4972 case GL_BUFFER_SIZE:
4973 break;
4974
4975 case GL_BUFFER_ACCESS_OES:
4976 if (!extensions.mapBuffer)
4977 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004978 context->handleError(InvalidEnum()
4979 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004980 return false;
4981 }
4982 break;
4983
4984 case GL_BUFFER_MAPPED:
4985 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4986 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4987 !extensions.mapBufferRange)
4988 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004989 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4990 "GL_OES_mapbuffer or "
4991 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004992 return false;
4993 }
4994 break;
4995
4996 case GL_BUFFER_MAP_POINTER:
4997 if (!pointerVersion)
4998 {
4999 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005000 InvalidEnum()
5001 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005002 return false;
5003 }
5004 break;
5005
5006 case GL_BUFFER_ACCESS_FLAGS:
5007 case GL_BUFFER_MAP_OFFSET:
5008 case GL_BUFFER_MAP_LENGTH:
5009 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5010 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005011 context->handleError(InvalidEnum()
5012 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005013 return false;
5014 }
5015 break;
5016
5017 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005018 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005019 return false;
5020 }
5021
5022 // All buffer parameter queries return one value.
5023 if (numParams)
5024 {
5025 *numParams = 1;
5026 }
5027
5028 return true;
5029}
5030
5031bool ValidateGetRenderbufferParameterivBase(Context *context,
5032 GLenum target,
5033 GLenum pname,
5034 GLsizei *length)
5035{
5036 if (length)
5037 {
5038 *length = 0;
5039 }
5040
5041 if (target != GL_RENDERBUFFER)
5042 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005043 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005044 return false;
5045 }
5046
5047 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5048 if (renderbuffer == nullptr)
5049 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005050 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005051 return false;
5052 }
5053
5054 switch (pname)
5055 {
5056 case GL_RENDERBUFFER_WIDTH:
5057 case GL_RENDERBUFFER_HEIGHT:
5058 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5059 case GL_RENDERBUFFER_RED_SIZE:
5060 case GL_RENDERBUFFER_GREEN_SIZE:
5061 case GL_RENDERBUFFER_BLUE_SIZE:
5062 case GL_RENDERBUFFER_ALPHA_SIZE:
5063 case GL_RENDERBUFFER_DEPTH_SIZE:
5064 case GL_RENDERBUFFER_STENCIL_SIZE:
5065 break;
5066
5067 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5068 if (!context->getExtensions().framebufferMultisample)
5069 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005070 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005071 return false;
5072 }
5073 break;
5074
5075 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005076 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005077 return false;
5078 }
5079
5080 if (length)
5081 {
5082 *length = 1;
5083 }
5084 return true;
5085}
5086
5087bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5088{
5089 if (length)
5090 {
5091 *length = 0;
5092 }
5093
5094 if (GetValidShader(context, shader) == nullptr)
5095 {
5096 return false;
5097 }
5098
5099 switch (pname)
5100 {
5101 case GL_SHADER_TYPE:
5102 case GL_DELETE_STATUS:
5103 case GL_COMPILE_STATUS:
5104 case GL_INFO_LOG_LENGTH:
5105 case GL_SHADER_SOURCE_LENGTH:
5106 break;
5107
5108 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5109 if (!context->getExtensions().translatedShaderSource)
5110 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005111 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005112 return false;
5113 }
5114 break;
5115
5116 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005117 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005118 return false;
5119 }
5120
5121 if (length)
5122 {
5123 *length = 1;
5124 }
5125 return true;
5126}
5127
5128bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
5129{
5130 if (length)
5131 {
5132 *length = 0;
5133 }
5134
5135 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5136 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005137 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005138 return false;
5139 }
5140
5141 if (context->getTargetTexture(target) == nullptr)
5142 {
5143 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005144 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005145 return false;
5146 }
5147
5148 switch (pname)
5149 {
5150 case GL_TEXTURE_MAG_FILTER:
5151 case GL_TEXTURE_MIN_FILTER:
5152 case GL_TEXTURE_WRAP_S:
5153 case GL_TEXTURE_WRAP_T:
5154 break;
5155
5156 case GL_TEXTURE_USAGE_ANGLE:
5157 if (!context->getExtensions().textureUsage)
5158 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005159 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005160 return false;
5161 }
5162 break;
5163
5164 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5165 if (!context->getExtensions().textureFilterAnisotropic)
5166 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005167 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005168 return false;
5169 }
5170 break;
5171
5172 case GL_TEXTURE_IMMUTABLE_FORMAT:
5173 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5174 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005175 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005176 return false;
5177 }
5178 break;
5179
5180 case GL_TEXTURE_WRAP_R:
5181 case GL_TEXTURE_IMMUTABLE_LEVELS:
5182 case GL_TEXTURE_SWIZZLE_R:
5183 case GL_TEXTURE_SWIZZLE_G:
5184 case GL_TEXTURE_SWIZZLE_B:
5185 case GL_TEXTURE_SWIZZLE_A:
5186 case GL_TEXTURE_BASE_LEVEL:
5187 case GL_TEXTURE_MAX_LEVEL:
5188 case GL_TEXTURE_MIN_LOD:
5189 case GL_TEXTURE_MAX_LOD:
5190 case GL_TEXTURE_COMPARE_MODE:
5191 case GL_TEXTURE_COMPARE_FUNC:
5192 if (context->getClientMajorVersion() < 3)
5193 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005194 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005195 return false;
5196 }
5197 break;
5198
5199 case GL_TEXTURE_SRGB_DECODE_EXT:
5200 if (!context->getExtensions().textureSRGBDecode)
5201 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005202 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005203 return false;
5204 }
5205 break;
5206
5207 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005208 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005209 return false;
5210 }
5211
5212 if (length)
5213 {
5214 *length = 1;
5215 }
5216 return true;
5217}
5218
5219bool ValidateGetVertexAttribBase(Context *context,
5220 GLuint index,
5221 GLenum pname,
5222 GLsizei *length,
5223 bool pointer,
5224 bool pureIntegerEntryPoint)
5225{
5226 if (length)
5227 {
5228 *length = 0;
5229 }
5230
5231 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5232 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005233 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005234 return false;
5235 }
5236
5237 if (index >= context->getCaps().maxVertexAttributes)
5238 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005239 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Jamie Madillbe849e42017-05-02 15:49:00 -04005240 return false;
5241 }
5242
5243 if (pointer)
5244 {
5245 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5246 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005247 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005248 return false;
5249 }
5250 }
5251 else
5252 {
5253 switch (pname)
5254 {
5255 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5256 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5257 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5258 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5259 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5260 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5261 case GL_CURRENT_VERTEX_ATTRIB:
5262 break;
5263
5264 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5265 static_assert(
5266 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5267 "ANGLE extension enums not equal to GL enums.");
5268 if (context->getClientMajorVersion() < 3 &&
5269 !context->getExtensions().instancedArrays)
5270 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005271 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5272 "requires OpenGL ES 3.0 or "
5273 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005274 return false;
5275 }
5276 break;
5277
5278 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5279 if (context->getClientMajorVersion() < 3)
5280 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005281 context->handleError(
5282 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005283 return false;
5284 }
5285 break;
5286
5287 case GL_VERTEX_ATTRIB_BINDING:
5288 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5289 if (context->getClientVersion() < ES_3_1)
5290 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005291 context->handleError(InvalidEnum()
5292 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005293 return false;
5294 }
5295 break;
5296
5297 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005298 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005299 return false;
5300 }
5301 }
5302
5303 if (length)
5304 {
5305 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5306 {
5307 *length = 4;
5308 }
5309 else
5310 {
5311 *length = 1;
5312 }
5313 }
5314
5315 return true;
5316}
5317
Jamie Madill4928b7c2017-06-20 12:57:39 -04005318bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005319 GLint x,
5320 GLint y,
5321 GLsizei width,
5322 GLsizei height,
5323 GLenum format,
5324 GLenum type,
5325 GLsizei bufSize,
5326 GLsizei *length,
5327 GLsizei *columns,
5328 GLsizei *rows,
5329 void *pixels)
5330{
5331 if (length != nullptr)
5332 {
5333 *length = 0;
5334 }
5335 if (rows != nullptr)
5336 {
5337 *rows = 0;
5338 }
5339 if (columns != nullptr)
5340 {
5341 *columns = 0;
5342 }
5343
5344 if (width < 0 || height < 0)
5345 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005346 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005347 return false;
5348 }
5349
5350 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5351
5352 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5353 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005354 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005355 return false;
5356 }
5357
5358 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5359 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005360 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005361 return false;
5362 }
5363
5364 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5365 ASSERT(framebuffer);
5366
5367 if (framebuffer->getReadBufferState() == GL_NONE)
5368 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005369 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Jamie Madillbe849e42017-05-02 15:49:00 -04005370 return false;
5371 }
5372
5373 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5374 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5375 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5376 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5377 // situation is an application error that would lead to a crash in ANGLE.
5378 if (readBuffer == nullptr)
5379 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005380 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005381 return false;
5382 }
5383
Geoff Lang280ba992017-04-18 16:30:58 -04005384 if (context->getExtensions().webglCompatibility)
5385 {
5386 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5387 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5388 // and type before validating the combination of format and type. However, the
5389 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5390 // verifies that GL_INVALID_OPERATION is generated.
5391 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5392 // dEQP/WebGL.
5393 if (!ValidReadPixelsFormatEnum(context, format))
5394 {
5395 context->handleError(InvalidEnum() << "Invalid read format.");
5396 return false;
5397 }
5398
5399 if (!ValidReadPixelsTypeEnum(context, type))
5400 {
5401 context->handleError(InvalidEnum() << "Invalid read type.");
5402 return false;
5403 }
5404 }
5405
Jamie Madill4928b7c2017-06-20 12:57:39 -04005406 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5407 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005408 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5409
5410 bool validFormatTypeCombination =
5411 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5412
5413 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5414 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005415 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005416 return false;
5417 }
5418
5419 // Check for pixel pack buffer related API errors
5420 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5421 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5422 {
5423 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005424 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005425 return false;
5426 }
5427
5428 // .. the data would be packed to the buffer object such that the memory writes required
5429 // would exceed the data store size.
5430 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5431 const gl::Extents size(width, height, 1);
5432 const auto &pack = context->getGLState().getPackState();
5433
5434 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5435 if (endByteOrErr.isError())
5436 {
5437 context->handleError(endByteOrErr.getError());
5438 return false;
5439 }
5440
5441 size_t endByte = endByteOrErr.getResult();
5442 if (bufSize >= 0)
5443 {
5444 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5445 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005446 context->handleError(InvalidOperation()
5447 << "bufSize must be at least " << endByte << " bytes.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005448 return false;
5449 }
5450 }
5451
5452 if (pixelPackBuffer != nullptr)
5453 {
5454 CheckedNumeric<size_t> checkedEndByte(endByte);
5455 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5456 checkedEndByte += checkedOffset;
5457
5458 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5459 {
5460 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005461 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005462 return false;
5463 }
5464 }
5465
5466 if (pixelPackBuffer == nullptr && length != nullptr)
5467 {
5468 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5469 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005470 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005471 return false;
5472 }
5473
5474 *length = static_cast<GLsizei>(endByte);
5475 }
5476
5477 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5478 angle::CheckedNumeric<int> clippedExtent(length);
5479 if (start < 0)
5480 {
5481 // "subtract" the area that is less than 0
5482 clippedExtent += start;
5483 }
5484
5485 const int readExtent = start + length;
5486 if (readExtent > bufferSize)
5487 {
5488 // Subtract the region to the right of the read buffer
5489 clippedExtent -= (readExtent - bufferSize);
5490 }
5491
5492 if (!clippedExtent.IsValid())
5493 {
5494 return 0;
5495 }
5496
5497 return std::max(clippedExtent.ValueOrDie(), 0);
5498 };
5499
5500 if (columns != nullptr)
5501 {
5502 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5503 }
5504
5505 if (rows != nullptr)
5506 {
5507 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5508 }
5509
5510 return true;
5511}
5512
5513template <typename ParamType>
5514bool ValidateTexParameterBase(Context *context,
5515 GLenum target,
5516 GLenum pname,
5517 GLsizei bufSize,
5518 const ParamType *params)
5519{
5520 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5521 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005522 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005523 return false;
5524 }
5525
5526 if (context->getTargetTexture(target) == nullptr)
5527 {
5528 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005529 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005530 return false;
5531 }
5532
5533 const GLsizei minBufSize = 1;
5534 if (bufSize >= 0 && bufSize < minBufSize)
5535 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005536 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005537 return false;
5538 }
5539
5540 switch (pname)
5541 {
5542 case GL_TEXTURE_WRAP_R:
5543 case GL_TEXTURE_SWIZZLE_R:
5544 case GL_TEXTURE_SWIZZLE_G:
5545 case GL_TEXTURE_SWIZZLE_B:
5546 case GL_TEXTURE_SWIZZLE_A:
5547 case GL_TEXTURE_BASE_LEVEL:
5548 case GL_TEXTURE_MAX_LEVEL:
5549 case GL_TEXTURE_COMPARE_MODE:
5550 case GL_TEXTURE_COMPARE_FUNC:
5551 case GL_TEXTURE_MIN_LOD:
5552 case GL_TEXTURE_MAX_LOD:
5553 if (context->getClientMajorVersion() < 3)
5554 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005555 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005556 return false;
5557 }
5558 if (target == GL_TEXTURE_EXTERNAL_OES &&
5559 !context->getExtensions().eglImageExternalEssl3)
5560 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005561 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5562 "available without "
5563 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005564 return false;
5565 }
5566 break;
5567
5568 default:
5569 break;
5570 }
5571
5572 switch (pname)
5573 {
5574 case GL_TEXTURE_WRAP_S:
5575 case GL_TEXTURE_WRAP_T:
5576 case GL_TEXTURE_WRAP_R:
5577 if (!ValidateTextureWrapModeValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
5578 {
5579 return false;
5580 }
5581 break;
5582
5583 case GL_TEXTURE_MIN_FILTER:
5584 if (!ValidateTextureMinFilterValue(context, params, target == GL_TEXTURE_EXTERNAL_OES))
5585 {
5586 return false;
5587 }
5588 break;
5589
5590 case GL_TEXTURE_MAG_FILTER:
5591 if (!ValidateTextureMagFilterValue(context, params))
5592 {
5593 return false;
5594 }
5595 break;
5596
5597 case GL_TEXTURE_USAGE_ANGLE:
5598 switch (ConvertToGLenum(params[0]))
5599 {
5600 case GL_NONE:
5601 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5602 break;
5603
5604 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005605 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005606 return false;
5607 }
5608 break;
5609
5610 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5611 if (!context->getExtensions().textureFilterAnisotropic)
5612 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005613 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005614 return false;
5615 }
5616
5617 // we assume the parameter passed to this validation method is truncated, not rounded
5618 if (params[0] < 1)
5619 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005620 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005621 return false;
5622 }
5623 break;
5624
5625 case GL_TEXTURE_MIN_LOD:
5626 case GL_TEXTURE_MAX_LOD:
5627 // any value is permissible
5628 break;
5629
5630 case GL_TEXTURE_COMPARE_MODE:
5631 if (!ValidateTextureCompareModeValue(context, params))
5632 {
5633 return false;
5634 }
5635 break;
5636
5637 case GL_TEXTURE_COMPARE_FUNC:
5638 if (!ValidateTextureCompareFuncValue(context, params))
5639 {
5640 return false;
5641 }
5642 break;
5643
5644 case GL_TEXTURE_SWIZZLE_R:
5645 case GL_TEXTURE_SWIZZLE_G:
5646 case GL_TEXTURE_SWIZZLE_B:
5647 case GL_TEXTURE_SWIZZLE_A:
5648 switch (ConvertToGLenum(params[0]))
5649 {
5650 case GL_RED:
5651 case GL_GREEN:
5652 case GL_BLUE:
5653 case GL_ALPHA:
5654 case GL_ZERO:
5655 case GL_ONE:
5656 break;
5657
5658 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005659 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005660 return false;
5661 }
5662 break;
5663
5664 case GL_TEXTURE_BASE_LEVEL:
5665 if (params[0] < 0)
5666 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005667 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005668 return false;
5669 }
5670 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5671 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005672 context->handleError(InvalidOperation()
5673 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005674 return false;
5675 }
5676 break;
5677
5678 case GL_TEXTURE_MAX_LEVEL:
5679 if (params[0] < 0)
5680 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005681 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005682 return false;
5683 }
5684 break;
5685
5686 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5687 if (context->getClientVersion() < Version(3, 1))
5688 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005689 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005690 return false;
5691 }
5692 switch (ConvertToGLenum(params[0]))
5693 {
5694 case GL_DEPTH_COMPONENT:
5695 case GL_STENCIL_INDEX:
5696 break;
5697
5698 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005699 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005700 return false;
5701 }
5702 break;
5703
5704 case GL_TEXTURE_SRGB_DECODE_EXT:
5705 if (!ValidateTextureSRGBDecodeValue(context, params))
5706 {
5707 return false;
5708 }
5709 break;
5710
5711 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005712 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005713 return false;
5714 }
5715
5716 return true;
5717}
5718
5719template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5720template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5721
Jamie Madillc29968b2016-01-20 11:17:23 -05005722} // namespace gl