blob: cb0b596f2f33a1854ef306066bacdaaf2af8f909 [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>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400260bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400261{
262 switch (ConvertToGLenum(params[0]))
263 {
264 case GL_CLAMP_TO_EDGE:
265 break;
266
267 case GL_REPEAT:
268 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400269 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400270 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400271 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500272 context->handleError(InvalidEnum()
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400273 << "texture 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>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400287bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400288{
289 switch (ConvertToGLenum(params[0]))
290 {
291 case GL_NEAREST:
292 case GL_LINEAR:
293 break;
294
295 case GL_NEAREST_MIPMAP_NEAREST:
296 case GL_LINEAR_MIPMAP_NEAREST:
297 case GL_NEAREST_MIPMAP_LINEAR:
298 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400299 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400300 {
301 // OES_EGL_image_external specifies this error.
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400302 context->handleError(InvalidEnum()
303 << "texture only support NEAREST and LINEAR filtering");
Geoff Langc1984ed2016-10-07 12:41:00 -0400304 return false;
305 }
306 break;
307
308 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700309 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400310 return false;
311 }
312
313 return true;
314}
315
316template <typename ParamType>
317bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
318{
319 switch (ConvertToGLenum(params[0]))
320 {
321 case GL_NEAREST:
322 case GL_LINEAR:
323 break;
324
325 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700326 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400327 return false;
328 }
329
330 return true;
331}
332
333template <typename ParamType>
334bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
335{
336 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
337 switch (ConvertToGLenum(params[0]))
338 {
339 case GL_NONE:
340 case GL_COMPARE_REF_TO_TEXTURE:
341 break;
342
343 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500344 context->handleError(InvalidEnum() << "Unknown param value.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400345 return false;
346 }
347
348 return true;
349}
350
351template <typename ParamType>
352bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
353{
354 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
355 switch (ConvertToGLenum(params[0]))
356 {
357 case GL_LEQUAL:
358 case GL_GEQUAL:
359 case GL_LESS:
360 case GL_GREATER:
361 case GL_EQUAL:
362 case GL_NOTEQUAL:
363 case GL_ALWAYS:
364 case GL_NEVER:
365 break;
366
367 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500368 context->handleError(InvalidEnum() << "Unknown param value.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400369 return false;
370 }
371
372 return true;
373}
374
375template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700376bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
377{
378 if (!context->getExtensions().textureSRGBDecode)
379 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700380 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700381 return false;
382 }
383
384 switch (ConvertToGLenum(params[0]))
385 {
386 case GL_DECODE_EXT:
387 case GL_SKIP_DECODE_EXT:
388 break;
389
390 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500391 context->handleError(InvalidEnum() << "Unknown param value.");
Geoff Lang81c6b572016-10-19 14:07:52 -0700392 return false;
393 }
394
395 return true;
396}
397
398template <typename ParamType>
Geoff Langc1984ed2016-10-07 12:41:00 -0400399bool ValidateSamplerParameterBase(Context *context,
400 GLuint sampler,
401 GLenum pname,
402 GLsizei bufSize,
403 ParamType *params)
404{
405 if (context->getClientMajorVersion() < 3)
406 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500407 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400408 return false;
409 }
410
411 if (!context->isSampler(sampler))
412 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500413 context->handleError(InvalidOperation() << "Sampler is not valid.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400414 return false;
415 }
416
417 const GLsizei minBufSize = 1;
418 if (bufSize >= 0 && bufSize < minBufSize)
419 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500420 context->handleError(InvalidOperation() << "bufSize must be at least " << minBufSize);
Geoff Langc1984ed2016-10-07 12:41:00 -0400421 return false;
422 }
423
424 switch (pname)
425 {
426 case GL_TEXTURE_WRAP_S:
427 case GL_TEXTURE_WRAP_T:
428 case GL_TEXTURE_WRAP_R:
429 if (!ValidateTextureWrapModeValue(context, params, false))
430 {
431 return false;
432 }
433 break;
434
435 case GL_TEXTURE_MIN_FILTER:
436 if (!ValidateTextureMinFilterValue(context, params, false))
437 {
438 return false;
439 }
440 break;
441
442 case GL_TEXTURE_MAG_FILTER:
443 if (!ValidateTextureMagFilterValue(context, params))
444 {
445 return false;
446 }
447 break;
448
449 case GL_TEXTURE_MIN_LOD:
450 case GL_TEXTURE_MAX_LOD:
451 // any value is permissible
452 break;
453
454 case GL_TEXTURE_COMPARE_MODE:
455 if (!ValidateTextureCompareModeValue(context, params))
456 {
457 return false;
458 }
459 break;
460
461 case GL_TEXTURE_COMPARE_FUNC:
462 if (!ValidateTextureCompareFuncValue(context, params))
463 {
464 return false;
465 }
466 break;
467
Geoff Lang81c6b572016-10-19 14:07:52 -0700468 case GL_TEXTURE_SRGB_DECODE_EXT:
469 if (!ValidateTextureSRGBDecodeValue(context, params))
470 {
471 return false;
472 }
473 break;
474
Geoff Langc1984ed2016-10-07 12:41:00 -0400475 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700476 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langc1984ed2016-10-07 12:41:00 -0400477 return false;
478 }
479
480 return true;
481}
482
483bool ValidateGetSamplerParameterBase(Context *context,
484 GLuint sampler,
485 GLenum pname,
486 GLsizei *length)
487{
488 if (length)
489 {
490 *length = 0;
491 }
492
493 if (context->getClientMajorVersion() < 3)
494 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500495 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400496 return false;
497 }
498
499 if (!context->isSampler(sampler))
500 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500501 context->handleError(InvalidOperation() << "Sampler is not valid.");
Geoff Langc1984ed2016-10-07 12:41:00 -0400502 return false;
503 }
504
505 switch (pname)
506 {
507 case GL_TEXTURE_WRAP_S:
508 case GL_TEXTURE_WRAP_T:
509 case GL_TEXTURE_WRAP_R:
510 case GL_TEXTURE_MIN_FILTER:
511 case GL_TEXTURE_MAG_FILTER:
512 case GL_TEXTURE_MIN_LOD:
513 case GL_TEXTURE_MAX_LOD:
514 case GL_TEXTURE_COMPARE_MODE:
515 case GL_TEXTURE_COMPARE_FUNC:
516 break;
517
Geoff Lang81c6b572016-10-19 14:07:52 -0700518 case GL_TEXTURE_SRGB_DECODE_EXT:
519 if (!context->getExtensions().textureSRGBDecode)
520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500521 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Geoff Lang81c6b572016-10-19 14:07:52 -0700522 return false;
523 }
524 break;
525
Geoff Langc1984ed2016-10-07 12:41:00 -0400526 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700527 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langc1984ed2016-10-07 12:41:00 -0400528 return false;
529 }
530
531 if (length)
532 {
533 *length = 1;
534 }
535 return true;
536}
537
Geoff Lang6899b872016-10-14 11:30:13 -0400538bool ValidateGetActiveUniformBlockivBase(Context *context,
539 GLuint program,
540 GLuint uniformBlockIndex,
541 GLenum pname,
542 GLsizei *length)
543{
544 if (length)
545 {
546 *length = 0;
547 }
548
549 if (context->getClientMajorVersion() < 3)
550 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500551 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Lang6899b872016-10-14 11:30:13 -0400552 return false;
553 }
554
555 Program *programObject = GetValidProgram(context, program);
556 if (!programObject)
557 {
558 return false;
559 }
560
561 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
562 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500563 context->handleError(InvalidValue()
564 << "uniformBlockIndex exceeds active uniform block count.");
Geoff Lang6899b872016-10-14 11:30:13 -0400565 return false;
566 }
567
568 switch (pname)
569 {
570 case GL_UNIFORM_BLOCK_BINDING:
571 case GL_UNIFORM_BLOCK_DATA_SIZE:
572 case GL_UNIFORM_BLOCK_NAME_LENGTH:
573 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
574 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
575 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
576 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
577 break;
578
579 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700580 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang6899b872016-10-14 11:30:13 -0400581 return false;
582 }
583
584 if (length)
585 {
586 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
587 {
588 const UniformBlock &uniformBlock =
589 programObject->getUniformBlockByIndex(uniformBlockIndex);
jchen10eaef1e52017-06-13 10:44:11 +0800590 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
Geoff Lang6899b872016-10-14 11:30:13 -0400591 }
592 else
593 {
594 *length = 1;
595 }
596 }
597
598 return true;
599}
600
Geoff Lang0a9661f2016-10-20 10:59:20 -0700601bool ValidateGetInternalFormativBase(Context *context,
602 GLenum target,
603 GLenum internalformat,
604 GLenum pname,
605 GLsizei bufSize,
606 GLsizei *numParams)
607{
608 if (numParams)
609 {
610 *numParams = 0;
611 }
612
613 if (context->getClientMajorVersion() < 3)
614 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500615 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700616 return false;
617 }
618
619 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
620 if (!formatCaps.renderable)
621 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500622 context->handleError(InvalidEnum() << "Internal format is not renderable.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700623 return false;
624 }
625
626 switch (target)
627 {
628 case GL_RENDERBUFFER:
629 break;
630
JiangYizhoubddc46b2016-12-09 09:50:51 +0800631 case GL_TEXTURE_2D_MULTISAMPLE:
632 if (context->getClientVersion() < ES_3_1)
633 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500634 context->handleError(InvalidOperation()
635 << "Texture target requires at least OpenGL ES 3.1.");
JiangYizhoubddc46b2016-12-09 09:50:51 +0800636 return false;
637 }
638 break;
639
Geoff Lang0a9661f2016-10-20 10:59:20 -0700640 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500641 context->handleError(InvalidEnum() << "Invalid target.");
Geoff Lang0a9661f2016-10-20 10:59:20 -0700642 return false;
643 }
644
645 if (bufSize < 0)
646 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700647 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
Geoff Lang0a9661f2016-10-20 10:59:20 -0700648 return false;
649 }
650
651 GLsizei maxWriteParams = 0;
652 switch (pname)
653 {
654 case GL_NUM_SAMPLE_COUNTS:
655 maxWriteParams = 1;
656 break;
657
658 case GL_SAMPLES:
659 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
660 break;
661
662 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700663 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang0a9661f2016-10-20 10:59:20 -0700664 return false;
665 }
666
667 if (numParams)
668 {
669 // glGetInternalFormativ will not overflow bufSize
670 *numParams = std::min(bufSize, maxWriteParams);
671 }
672
673 return true;
674}
675
Jamie Madillc1d770e2017-04-13 17:31:24 -0400676bool ValidateUniformCommonBase(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500677 gl::Program *program,
678 GLint location,
679 GLsizei count,
680 const LinkedUniform **uniformOut)
681{
682 // TODO(Jiajia): Add image uniform check in future.
683 if (count < 0)
684 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700685 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500686 return false;
687 }
688
Brandon Jones6cad5662017-06-14 13:25:13 -0700689 if (!program)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500690 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700691 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
692 return false;
693 }
694
695 if (!program->isLinked())
696 {
697 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500698 return false;
699 }
700
701 if (location == -1)
702 {
703 // Silently ignore the uniform command
704 return false;
705 }
706
707 const auto &uniformLocations = program->getUniformLocations();
Jamie Madillbe849e42017-05-02 15:49:00 -0400708 size_t castedLocation = static_cast<size_t>(location);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500709 if (castedLocation >= uniformLocations.size())
710 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500711 context->handleError(InvalidOperation() << "Invalid uniform location");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500712 return false;
713 }
714
715 const auto &uniformLocation = uniformLocations[castedLocation];
716 if (uniformLocation.ignored)
717 {
718 // Silently ignore the uniform command
719 return false;
720 }
721
722 if (!uniformLocation.used)
723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500724 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500725 return false;
726 }
727
728 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
729
730 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
731 if (!uniform.isArray() && count > 1)
732 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500733 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500734 return false;
735 }
736
737 *uniformOut = &uniform;
738 return true;
739}
740
Frank Henigman999b0fd2017-02-02 21:45:55 -0500741bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -0500742 GLenum uniformType,
743 GLsizei count,
744 const GLint *value)
745{
746 // Value type is GL_INT, because we only get here from glUniform1i{v}.
747 // It is compatible with INT or BOOL.
748 // Do these cheap tests first, for a little extra speed.
749 if (GL_INT == uniformType || GL_BOOL == uniformType)
750 {
751 return true;
752 }
753
754 if (IsSamplerType(uniformType))
755 {
Frank Henigman999b0fd2017-02-02 21:45:55 -0500756 // Check that the values are in range.
757 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
758 for (GLsizei i = 0; i < count; ++i)
759 {
760 if (value[i] < 0 || value[i] >= max)
761 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500762 context->handleError(InvalidValue() << "sampler uniform value out of range");
Frank Henigman999b0fd2017-02-02 21:45:55 -0500763 return false;
764 }
765 }
Frank Henigmana98a6472017-02-02 21:38:32 -0500766 return true;
767 }
768
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500769 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmana98a6472017-02-02 21:38:32 -0500770 return false;
771}
772
Jamie Madillc1d770e2017-04-13 17:31:24 -0400773bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500774{
775 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -0500776 // Do the cheaper test first, for a little extra speed.
777 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500778 {
779 return true;
780 }
781
Brandon Jones6cad5662017-06-14 13:25:13 -0700782 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeDoesNotMatchMethod);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500783 return false;
784}
785
Jamie Madillc1d770e2017-04-13 17:31:24 -0400786bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500787{
788 // Check that the value type is compatible with uniform type.
789 if (valueType == uniformType)
790 {
791 return true;
792 }
793
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500794 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500795 return false;
796}
797
Geoff Lange0cff192017-05-30 13:04:56 -0400798bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
799{
800 const Program *program = context->getGLState().getProgram();
801 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
802
803 const auto &programOutputTypes = program->getOutputVariableTypes();
804 for (size_t drawBufferIdx = 0; drawBufferIdx < programOutputTypes.size(); drawBufferIdx++)
805 {
806 GLenum outputType = programOutputTypes[drawBufferIdx];
807 GLenum inputType = framebuffer->getDrawbufferWriteType(drawBufferIdx);
808 if (outputType != GL_NONE && inputType != GL_NONE && inputType != outputType)
809 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500810 context->handleError(InvalidOperation() << "Fragment shader output type does not "
811 "match the bound framebuffer attachment "
812 "type.");
Geoff Lange0cff192017-05-30 13:04:56 -0400813 return false;
814 }
815 }
816
817 return true;
818}
819
Geoff Lang9ab5b822017-05-30 16:19:23 -0400820bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
821{
822 const Program *program = context->getGLState().getProgram();
823 const VertexArray *vao = context->getGLState().getVertexArray();
824
825 for (const auto &shaderAttribute : program->getAttributes())
826 {
Geoff Lang69df2422017-07-05 12:42:31 -0400827 // gl_VertexID and gl_InstanceID are active attributes but don't have a bound attribute.
828 if (shaderAttribute.isBuiltIn())
829 {
830 continue;
831 }
832
Geoff Lang9ab5b822017-05-30 16:19:23 -0400833 GLenum shaderInputType = VariableComponentType(shaderAttribute.type);
834
835 const auto &attrib = vao->getVertexAttribute(shaderAttribute.location);
836 const auto &currentValue =
837 context->getGLState().getVertexAttribCurrentValue(shaderAttribute.location);
838 GLenum vertexType = attrib.enabled ? GetVertexAttributeBaseType(attrib) : currentValue.Type;
839
840 if (shaderInputType != GL_NONE && vertexType != GL_NONE && shaderInputType != vertexType)
841 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500842 context->handleError(InvalidOperation() << "Vertex shader input type does not "
843 "match the type of the bound vertex "
844 "attribute.");
Geoff Lang9ab5b822017-05-30 16:19:23 -0400845 return false;
846 }
847 }
848
849 return true;
850}
851
Geoff Langf41a7152016-09-19 15:11:17 -0400852} // anonymous namespace
853
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500854bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400855{
Jamie Madilld7460c72014-01-21 16:38:14 -0500856 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400857 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800858 case GL_TEXTURE_2D:
859 case GL_TEXTURE_CUBE_MAP:
860 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400861
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400862 case GL_TEXTURE_RECTANGLE_ANGLE:
863 return context->getExtensions().textureRectangle;
864
He Yunchaoced53ae2016-11-29 15:00:51 +0800865 case GL_TEXTURE_3D:
866 case GL_TEXTURE_2D_ARRAY:
867 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500868
He Yunchaoced53ae2016-11-29 15:00:51 +0800869 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800870 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400871
He Yunchaoced53ae2016-11-29 15:00:51 +0800872 default:
873 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500874 }
Jamie Madill35d15012013-10-07 10:46:37 -0400875}
876
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500877bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
878{
879 switch (target)
880 {
881 case GL_TEXTURE_2D:
882 case GL_TEXTURE_CUBE_MAP:
883 return true;
884
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400885 case GL_TEXTURE_RECTANGLE_ANGLE:
886 return context->getExtensions().textureRectangle;
887
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500888 default:
889 return false;
890 }
891}
892
893bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
894{
895 switch (target)
896 {
897 case GL_TEXTURE_3D:
898 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300899 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500900
901 default:
902 return false;
903 }
904}
905
Ian Ewellbda75592016-04-18 17:25:54 -0400906// Most texture GL calls are not compatible with external textures, so we have a separate validation
907// function for use in the GL calls that do
908bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
909{
910 return (target == GL_TEXTURE_EXTERNAL_OES) &&
911 (context->getExtensions().eglImageExternal ||
912 context->getExtensions().eglStreamConsumerExternal);
913}
914
Shannon Woods4dfed832014-03-17 20:03:39 -0400915// This function differs from ValidTextureTarget in that the target must be
916// usable as the destination of a 2D operation-- so a cube face is valid, but
917// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400918// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500919bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400920{
921 switch (target)
922 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800923 case GL_TEXTURE_2D:
924 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
925 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
926 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
927 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
928 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
929 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
930 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400931 case GL_TEXTURE_RECTANGLE_ANGLE:
932 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800933 default:
934 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500935 }
936}
937
Jamie Madillbe849e42017-05-02 15:49:00 -0400938bool ValidateDrawElementsInstancedBase(ValidationContext *context,
939 GLenum mode,
940 GLsizei count,
941 GLenum type,
942 const GLvoid *indices,
943 GLsizei primcount)
944{
945 if (primcount < 0)
946 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500947 context->handleError(InvalidValue() << "primcount cannot be negative.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400948 return false;
949 }
950
951 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
952 {
953 return false;
954 }
955
956 // No-op zero primitive count
957 return (primcount > 0);
958}
959
960bool ValidateDrawArraysInstancedBase(Context *context,
961 GLenum mode,
962 GLint first,
963 GLsizei count,
964 GLsizei primcount)
965{
966 if (primcount < 0)
967 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500968 context->handleError(InvalidValue() << "primcount cannot be negative.");
Jamie Madillbe849e42017-05-02 15:49:00 -0400969 return false;
970 }
971
972 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
973 {
974 return false;
975 }
976
977 // No-op if zero primitive count
978 return (primcount > 0);
979}
980
Corentin Wallez0dc97812017-06-22 14:38:44 -0400981bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400982{
983 // Verify there is at least one active attribute with a divisor of zero
984 const State &state = context->getGLState();
985
986 Program *program = state.getProgram();
987
988 const auto &attribs = state.getVertexArray()->getVertexAttributes();
989 const auto &bindings = state.getVertexArray()->getVertexBindings();
990 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
991 {
992 const VertexAttribute &attrib = attribs[attributeIndex];
993 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300994 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400995 {
996 return true;
997 }
998 }
999
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001000 context->handleError(InvalidOperation()
1001 << "At least one attribute must have a divisor of zero.");
Jamie Madillbe849e42017-05-02 15:49:00 -04001002 return false;
1003}
1004
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001005bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
1006{
1007 switch (target)
1008 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001009 case GL_TEXTURE_3D:
1010 case GL_TEXTURE_2D_ARRAY:
1011 return true;
1012 default:
1013 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -04001014 }
1015}
1016
He Yunchao11b038b2016-11-22 21:24:04 +08001017bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
1018{
1019 switch (target)
1020 {
1021 case GL_TEXTURE_2D:
1022 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1023 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1024 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1025 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1026 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1027 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1028 case GL_TEXTURE_3D:
1029 case GL_TEXTURE_2D_ARRAY:
1030 case GL_TEXTURE_2D_MULTISAMPLE:
1031 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001032 case GL_TEXTURE_RECTANGLE_ANGLE:
1033 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +08001034 default:
1035 return false;
1036 }
1037}
1038
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001039bool ValidFramebufferTarget(GLenum target)
1040{
He Yunchaoced53ae2016-11-29 15:00:51 +08001041 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
1042 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -04001043 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001044
1045 switch (target)
1046 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001047 case GL_FRAMEBUFFER:
1048 return true;
1049 case GL_READ_FRAMEBUFFER:
1050 return true;
1051 case GL_DRAW_FRAMEBUFFER:
1052 return true;
1053 default:
1054 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001055 }
1056}
1057
Jamie Madill29639852016-09-02 15:00:09 -04001058bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -05001059{
1060 switch (target)
1061 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001062 case GL_ARRAY_BUFFER:
1063 case GL_ELEMENT_ARRAY_BUFFER:
1064 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -05001065
He Yunchaoced53ae2016-11-29 15:00:51 +08001066 case GL_PIXEL_PACK_BUFFER:
1067 case GL_PIXEL_UNPACK_BUFFER:
1068 return (context->getExtensions().pixelBufferObject ||
1069 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -04001070
He Yunchaoced53ae2016-11-29 15:00:51 +08001071 case GL_COPY_READ_BUFFER:
1072 case GL_COPY_WRITE_BUFFER:
1073 case GL_TRANSFORM_FEEDBACK_BUFFER:
1074 case GL_UNIFORM_BUFFER:
1075 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -05001076
He Yunchaoced53ae2016-11-29 15:00:51 +08001077 case GL_ATOMIC_COUNTER_BUFFER:
1078 case GL_SHADER_STORAGE_BUFFER:
1079 case GL_DRAW_INDIRECT_BUFFER:
1080 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +08001081 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -04001082
He Yunchaoced53ae2016-11-29 15:00:51 +08001083 default:
1084 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -05001085 }
1086}
1087
Jamie Madillc29968b2016-01-20 11:17:23 -05001088bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -04001089{
Jamie Madillc29968b2016-01-20 11:17:23 -05001090 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -04001091 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -04001092 switch (target)
1093 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001094 case GL_TEXTURE_2D:
1095 maxDimension = caps.max2DTextureSize;
1096 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001097 case GL_TEXTURE_CUBE_MAP:
1098 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1099 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1100 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1101 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1102 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1103 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1104 maxDimension = caps.maxCubeMapTextureSize;
1105 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001106 case GL_TEXTURE_RECTANGLE_ANGLE:
1107 return level == 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08001108 case GL_TEXTURE_3D:
1109 maxDimension = caps.max3DTextureSize;
1110 break;
1111 case GL_TEXTURE_2D_ARRAY:
1112 maxDimension = caps.max2DTextureSize;
1113 break;
He Yunchao11b038b2016-11-22 21:24:04 +08001114 case GL_TEXTURE_2D_MULTISAMPLE:
1115 maxDimension = caps.max2DTextureSize;
1116 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08001117 default:
1118 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -04001119 }
1120
Brandon Jones6cad5662017-06-14 13:25:13 -07001121 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -04001122}
1123
Brandon Jones6cad5662017-06-14 13:25:13 -07001124bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -07001125 GLenum target,
1126 GLint level,
1127 GLsizei width,
1128 GLsizei height,
1129 GLsizei depth,
1130 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -04001131{
Brandon Jones6cad5662017-06-14 13:25:13 -07001132 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -04001133 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001134 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -04001135 return false;
1136 }
Austin Kinross08528e12015-10-07 16:24:40 -07001137 // TexSubImage parameters can be NPOT without textureNPOT extension,
1138 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -05001139 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -05001140 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -05001141 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -04001142 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -04001143 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001144 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -04001145 return false;
1146 }
1147
1148 if (!ValidMipLevel(context, target, level))
1149 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001150 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -04001151 return false;
1152 }
1153
1154 return true;
1155}
1156
Geoff Lang0d8b7242015-09-09 14:56:53 -04001157bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
1158{
1159 // List of compressed format that require that the texture size is smaller than or a multiple of
1160 // the compressed block size.
1161 switch (internalFormat)
1162 {
1163 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
1164 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
1165 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
1166 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langfff7a7d2017-06-02 10:39:17 -04001167 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
1168 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
1169 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
1170 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
Minmin Gonge3939b92015-12-01 15:36:51 -08001171 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -08001172 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
1173 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
1174 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1175 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
1176 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
1177 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -04001178 return true;
1179
1180 default:
1181 return false;
1182 }
1183}
1184
Geoff Lang966c9402017-04-18 12:38:27 -04001185bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
1186{
1187 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
1188 (size % blockSize == 0);
1189}
1190
Jamie Madillc29968b2016-01-20 11:17:23 -05001191bool ValidCompressedImageSize(const ValidationContext *context,
1192 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -04001193 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -05001194 GLsizei width,
1195 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -04001196{
Geoff Langca271392017-04-05 12:30:00 -04001197 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -04001198 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -04001199 {
1200 return false;
1201 }
1202
Geoff Lang966c9402017-04-18 12:38:27 -04001203 if (width < 0 || height < 0)
1204 {
1205 return false;
1206 }
1207
1208 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1209 {
1210 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
1211 // block size for level 0 but WebGL disallows this.
1212 bool smallerThanBlockSizeAllowed =
1213 level > 0 || !context->getExtensions().webglCompatibility;
1214
1215 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
1216 smallerThanBlockSizeAllowed) ||
1217 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
1218 smallerThanBlockSizeAllowed))
1219 {
1220 return false;
1221 }
1222 }
1223
1224 return true;
1225}
1226
1227bool ValidCompressedSubImageSize(const ValidationContext *context,
1228 GLenum internalFormat,
1229 GLint xoffset,
1230 GLint yoffset,
1231 GLsizei width,
1232 GLsizei height,
1233 size_t textureWidth,
1234 size_t textureHeight)
1235{
1236 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
1237 if (!formatInfo.compressed)
1238 {
1239 return false;
1240 }
1241
Geoff Lang44ff5a72017-02-03 15:15:43 -05001242 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -04001243 {
1244 return false;
1245 }
1246
Geoff Lang0d8b7242015-09-09 14:56:53 -04001247 if (CompressedTextureFormatRequiresExactSize(internalFormat))
1248 {
Geoff Lang44ff5a72017-02-03 15:15:43 -05001249 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -04001250 yoffset % formatInfo.compressedBlockHeight != 0)
1251 {
1252 return false;
1253 }
1254
1255 // Allowed to either have data that is a multiple of block size or is smaller than the block
1256 // size but fills the entire mip
1257 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
1258 static_cast<size_t>(width) == textureWidth &&
1259 static_cast<size_t>(height) == textureHeight;
1260 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
1261 (height % formatInfo.compressedBlockHeight) == 0;
1262 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -04001263 {
1264 return false;
1265 }
1266 }
1267
Geoff Langd4f180b2013-09-24 13:57:44 -04001268 return true;
1269}
1270
Geoff Langff5b2d52016-09-07 11:32:23 -04001271bool ValidImageDataSize(ValidationContext *context,
1272 GLenum textureTarget,
1273 GLsizei width,
1274 GLsizei height,
1275 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -04001276 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -04001277 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001278 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001279 GLsizei imageSize)
1280{
1281 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
1282 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1283 {
1284 // Checks are not required
1285 return true;
1286 }
1287
1288 // ...the data would be unpacked from the buffer object such that the memory reads required
1289 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -04001290 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
1291 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -04001292 const gl::Extents size(width, height, depth);
1293 const auto &unpack = context->getGLState().getUnpackState();
1294
1295 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1296 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1297 if (endByteOrErr.isError())
1298 {
1299 context->handleError(endByteOrErr.getError());
1300 return false;
1301 }
1302
1303 GLuint endByte = endByteOrErr.getResult();
1304
1305 if (pixelUnpackBuffer)
1306 {
1307 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1308 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1309 checkedEndByte += checkedOffset;
1310
1311 if (!checkedEndByte.IsValid() ||
1312 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1313 {
1314 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001315 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04001316 return false;
1317 }
1318 }
1319 else
1320 {
1321 ASSERT(imageSize >= 0);
1322 if (pixels == nullptr && imageSize != 0)
1323 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001324 context->handleError(InvalidOperation()
1325 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001326 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001327 }
1328
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001329 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001330 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001331 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001332 return false;
1333 }
1334 }
1335
1336 return true;
1337}
1338
Geoff Lang37dde692014-01-31 16:34:54 -05001339bool ValidQueryType(const Context *context, GLenum queryType)
1340{
He Yunchaoced53ae2016-11-29 15:00:51 +08001341 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1342 "GL extension enums not equal.");
1343 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1344 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001345
1346 switch (queryType)
1347 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001348 case GL_ANY_SAMPLES_PASSED:
1349 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1350 return true;
1351 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1352 return (context->getClientMajorVersion() >= 3);
1353 case GL_TIME_ELAPSED_EXT:
1354 return context->getExtensions().disjointTimerQuery;
1355 case GL_COMMANDS_COMPLETED_CHROMIUM:
1356 return context->getExtensions().syncQuery;
1357 default:
1358 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001359 }
1360}
1361
Geoff Lang2d62ab72017-03-23 16:54:40 -04001362bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
1363 GLenum type,
1364 GLboolean normalized,
1365 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001366 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001367 bool pureInteger)
1368{
1369 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001370 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1371 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1372 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1373 // parameter exceeds 255.
1374 constexpr GLsizei kMaxWebGLStride = 255;
1375 if (stride > kMaxWebGLStride)
1376 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001377 context->handleError(InvalidValue()
1378 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001379 return false;
1380 }
1381
1382 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1383 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1384 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1385 // or an INVALID_OPERATION error is generated.
1386 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1387 size_t typeSize = GetVertexFormatTypeSize(internalType);
1388
1389 ASSERT(isPow2(typeSize) && typeSize > 0);
1390 size_t sizeMask = (typeSize - 1);
1391 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1392 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001393 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001394 return false;
1395 }
1396
1397 if ((stride & sizeMask) != 0)
1398 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001399 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001400 return false;
1401 }
1402
1403 return true;
1404}
1405
Jamie Madillef300b12016-10-07 15:12:09 -04001406Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001407{
He Yunchaoced53ae2016-11-29 15:00:51 +08001408 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1409 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1410 // or program object and INVALID_OPERATION if the provided name identifies an object
1411 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001412
Dian Xiang769769a2015-09-09 15:20:08 -07001413 Program *validProgram = context->getProgram(id);
1414
1415 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001416 {
Dian Xiang769769a2015-09-09 15:20:08 -07001417 if (context->getShader(id))
1418 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001419 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001420 }
1421 else
1422 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001423 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001424 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001425 }
Dian Xiang769769a2015-09-09 15:20:08 -07001426
1427 return validProgram;
1428}
1429
Jamie Madillef300b12016-10-07 15:12:09 -04001430Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001431{
1432 // See ValidProgram for spec details.
1433
1434 Shader *validShader = context->getShader(id);
1435
1436 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001437 {
Dian Xiang769769a2015-09-09 15:20:08 -07001438 if (context->getProgram(id))
1439 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001440 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001441 }
1442 else
1443 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001444 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001445 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001446 }
Dian Xiang769769a2015-09-09 15:20:08 -07001447
1448 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001449}
1450
Geoff Langb1196682014-07-23 13:47:29 -04001451bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001452{
1453 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1454 {
1455 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1456
Geoff Langaae65a42014-05-26 12:43:44 -04001457 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001458 {
Martin Radevd178aa42017-07-13 14:03:22 +03001459 context->handleError(
1460 InvalidOperation()
1461 << "attachment index cannot be greater or equal to MAX_COLOR_ATTACHMENTS.");
Geoff Langb1196682014-07-23 13:47:29 -04001462 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001463 }
1464 }
1465 else
1466 {
1467 switch (attachment)
1468 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001469 case GL_DEPTH_ATTACHMENT:
1470 case GL_STENCIL_ATTACHMENT:
1471 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001472
He Yunchaoced53ae2016-11-29 15:00:51 +08001473 case GL_DEPTH_STENCIL_ATTACHMENT:
1474 if (!context->getExtensions().webglCompatibility &&
1475 context->getClientMajorVersion() < 3)
1476 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001477 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001478 return false;
1479 }
1480 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001481
He Yunchaoced53ae2016-11-29 15:00:51 +08001482 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001483 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001484 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001485 }
1486 }
1487
1488 return true;
1489}
1490
Jamie Madille8fb6402017-02-14 17:56:40 -05001491bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001492 GLenum target,
1493 GLsizei samples,
1494 GLenum internalformat,
1495 GLsizei width,
1496 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001497{
1498 switch (target)
1499 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001500 case GL_RENDERBUFFER:
1501 break;
1502 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001503 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001504 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001505 }
1506
1507 if (width < 0 || height < 0 || samples < 0)
1508 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001509 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001510 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001511 }
1512
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001513 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1514 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1515
1516 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001517 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001518 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001519 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001520 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001521 }
1522
1523 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1524 // 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 -08001525 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001526 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1527 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001528 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001529 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001530 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001531 }
1532
Geoff Langaae65a42014-05-26 12:43:44 -04001533 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001534 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001535 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001536 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001537 }
1538
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001539 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001540 if (handle == 0)
1541 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001542 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001543 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001544 }
1545
1546 return true;
1547}
1548
He Yunchaoced53ae2016-11-29 15:00:51 +08001549bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1550 GLenum target,
1551 GLenum attachment,
1552 GLenum renderbuffertarget,
1553 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001554{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001555 if (!ValidFramebufferTarget(target))
1556 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001557 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001558 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001559 }
1560
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001561 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001562
Jamie Madill84115c92015-04-23 15:00:07 -04001563 ASSERT(framebuffer);
1564 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001565 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001566 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001567 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001568 }
1569
Jamie Madillb4472272014-07-03 10:38:55 -04001570 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001571 {
Jamie Madillb4472272014-07-03 10:38:55 -04001572 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001573 }
1574
Jamie Madillab9d82c2014-01-21 16:38:14 -05001575 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1576 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1577 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1578 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1579 if (renderbuffer != 0)
1580 {
1581 if (!context->getRenderbuffer(renderbuffer))
1582 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001583 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001584 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001585 }
1586 }
1587
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001588 return true;
1589}
1590
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001591bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001592 GLint srcX0,
1593 GLint srcY0,
1594 GLint srcX1,
1595 GLint srcY1,
1596 GLint dstX0,
1597 GLint dstY0,
1598 GLint dstX1,
1599 GLint dstY1,
1600 GLbitfield mask,
1601 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001602{
1603 switch (filter)
1604 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001605 case GL_NEAREST:
1606 break;
1607 case GL_LINEAR:
1608 break;
1609 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001610 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001611 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001612 }
1613
1614 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1615 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001616 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001617 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001618 }
1619
1620 if (mask == 0)
1621 {
1622 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1623 // buffers are copied.
1624 return false;
1625 }
1626
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001627 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1628 // color buffer, leaving only nearest being unfiltered from above
1629 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1630 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001631 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001632 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001633 }
1634
Jamie Madill51f40ec2016-06-15 14:06:00 -04001635 const auto &glState = context->getGLState();
1636 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1637 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001638
1639 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001640 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001641 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001642 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001643 }
1644
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001645 if (readFramebuffer->id() == drawFramebuffer->id())
1646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001647 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001648 return false;
1649 }
1650
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001651 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001652 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001653 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001654 return false;
1655 }
1656
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001657 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001658 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001659 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001660 return false;
1661 }
1662
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001663 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001664 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001665 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001666 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001667 }
1668
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001669 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1670
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001671 if (mask & GL_COLOR_BUFFER_BIT)
1672 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001673 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001674 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001675
He Yunchao66a41a22016-12-15 16:45:05 +08001676 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001677 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001678 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001679
Geoff Langa15472a2015-08-11 11:48:03 -04001680 for (size_t drawbufferIdx = 0;
1681 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001682 {
Geoff Langa15472a2015-08-11 11:48:03 -04001683 const FramebufferAttachment *attachment =
1684 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1685 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001686 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001687 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001688
Geoff Langb2f3d052013-08-13 12:49:27 -04001689 // The GL ES 3.0.2 spec (pg 193) states that:
1690 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001691 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1692 // as well
1693 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1694 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001695 // Changes with EXT_color_buffer_float:
1696 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001697 GLenum readComponentType = readFormat.info->componentType;
1698 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001699 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001700 readComponentType == GL_SIGNED_NORMALIZED);
1701 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1702 drawComponentType == GL_SIGNED_NORMALIZED);
1703
1704 if (extensions.colorBufferFloat)
1705 {
1706 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1707 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1708
1709 if (readFixedOrFloat != drawFixedOrFloat)
1710 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001711 context->handleError(InvalidOperation()
1712 << "If the read buffer contains fixed-point or "
1713 "floating-point values, the draw buffer must "
1714 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001715 return false;
1716 }
1717 }
1718 else if (readFixedPoint != drawFixedPoint)
1719 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001720 context->handleError(InvalidOperation()
1721 << "If the read buffer contains fixed-point values, "
1722 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001723 return false;
1724 }
1725
1726 if (readComponentType == GL_UNSIGNED_INT &&
1727 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001728 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001729 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001730 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001731 }
1732
Jamie Madill6163c752015-12-07 16:32:59 -05001733 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001734 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001735 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001736 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001737 }
1738
Jamie Madilla3944d42016-07-22 22:13:26 -04001739 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001740 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001741 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001742 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001743 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001744 }
Geoff Lange4915782017-04-12 15:19:07 -04001745
1746 if (context->getExtensions().webglCompatibility &&
1747 *readColorBuffer == *attachment)
1748 {
1749 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001750 InvalidOperation()
1751 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001752 return false;
1753 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001754 }
1755 }
1756
Jamie Madilla3944d42016-07-22 22:13:26 -04001757 if ((readFormat.info->componentType == GL_INT ||
1758 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1759 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001760 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001761 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001762 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001763 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001764 }
He Yunchao66a41a22016-12-15 16:45:05 +08001765 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1766 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1767 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1768 // situation is an application error that would lead to a crash in ANGLE.
1769 else if (drawFramebuffer->hasEnabledDrawBuffer())
1770 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001771 context->handleError(
1772 InvalidOperation()
1773 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001774 return false;
1775 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001776 }
1777
He Yunchaoced53ae2016-11-29 15:00:51 +08001778 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001779 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1780 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001781 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001782 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001783 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001784 const gl::FramebufferAttachment *readBuffer =
1785 readFramebuffer->getAttachment(attachments[i]);
1786 const gl::FramebufferAttachment *drawBuffer =
1787 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001788
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001789 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001790 {
Kenneth Russell69382852017-07-21 16:38:44 -04001791 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001792 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001793 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001794 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001795 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001796
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001797 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001798 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001799 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001800 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001801 }
Geoff Lange4915782017-04-12 15:19:07 -04001802
1803 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1804 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001805 context->handleError(
1806 InvalidOperation()
1807 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001808 return false;
1809 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001810 }
He Yunchao66a41a22016-12-15 16:45:05 +08001811 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1812 else if (drawBuffer)
1813 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001814 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1815 "depth/stencil attachment of a "
1816 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001817 return false;
1818 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001819 }
1820 }
1821
Martin Radeva3ed4572017-07-27 18:29:37 +03001822 // ANGLE_multiview, Revision 1:
1823 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1824 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1825 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1826 {
1827 context->handleError(InvalidFramebufferOperation()
1828 << "Attempt to read from a multi-view framebuffer.");
1829 return false;
1830 }
1831 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1832 {
1833 context->handleError(InvalidFramebufferOperation()
1834 << "Attempt to write to a multi-view framebuffer.");
1835 return false;
1836 }
1837
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001838 return true;
1839}
1840
Jamie Madill4928b7c2017-06-20 12:57:39 -04001841bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001842 GLint x,
1843 GLint y,
1844 GLsizei width,
1845 GLsizei height,
1846 GLenum format,
1847 GLenum type,
1848 GLsizei bufSize,
1849 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001850 GLsizei *columns,
1851 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001852 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001853{
1854 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001855 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001856 return false;
1857 }
1858
Geoff Lang62fce5b2016-09-30 10:46:35 -04001859 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001860 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001861 {
Geoff Langb1196682014-07-23 13:47:29 -04001862 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001863 }
1864
Geoff Lang62fce5b2016-09-30 10:46:35 -04001865 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001866 {
Geoff Langb1196682014-07-23 13:47:29 -04001867 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001868 }
1869
Jamie Madillc29968b2016-01-20 11:17:23 -05001870 return true;
1871}
1872
1873bool ValidateReadnPixelsEXT(Context *context,
1874 GLint x,
1875 GLint y,
1876 GLsizei width,
1877 GLsizei height,
1878 GLenum format,
1879 GLenum type,
1880 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001881 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001882{
1883 if (bufSize < 0)
1884 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001885 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001886 return false;
1887 }
1888
Geoff Lang62fce5b2016-09-30 10:46:35 -04001889 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001890 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001891}
Jamie Madill26e91952014-03-05 15:01:27 -05001892
Jamie Madill4928b7c2017-06-20 12:57:39 -04001893bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001894 GLint x,
1895 GLint y,
1896 GLsizei width,
1897 GLsizei height,
1898 GLenum format,
1899 GLenum type,
1900 GLsizei bufSize,
1901 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001902 GLsizei *columns,
1903 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001904 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001905{
1906 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001907 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001908 return false;
1909 }
1910
Geoff Lange93daba2017-03-30 13:54:40 -04001911 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1912 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001913 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001914 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001915 }
1916
Geoff Lang62fce5b2016-09-30 10:46:35 -04001917 if (!ValidateRobustBufferSize(context, bufSize, *length))
1918 {
1919 return false;
1920 }
1921
1922 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001923}
1924
Olli Etuaho41997e72016-03-10 13:38:39 +02001925bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001926{
1927 if (!context->getExtensions().occlusionQueryBoolean &&
1928 !context->getExtensions().disjointTimerQuery)
1929 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001930 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001931 return false;
1932 }
1933
Olli Etuaho41997e72016-03-10 13:38:39 +02001934 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001935}
1936
Olli Etuaho41997e72016-03-10 13:38:39 +02001937bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001938{
1939 if (!context->getExtensions().occlusionQueryBoolean &&
1940 !context->getExtensions().disjointTimerQuery)
1941 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001942 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001943 return false;
1944 }
1945
Olli Etuaho41997e72016-03-10 13:38:39 +02001946 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001947}
1948
1949bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001950{
1951 if (!ValidQueryType(context, target))
1952 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001953 context->handleError(InvalidEnum() << "Invalid query target");
Geoff Langb1196682014-07-23 13:47:29 -04001954 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001955 }
1956
1957 if (id == 0)
1958 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001959 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001960 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001961 }
1962
1963 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1964 // of zero, if the active query object name for <target> is non-zero (for the
1965 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1966 // the active query for either target is non-zero), if <id> is the name of an
1967 // existing query object whose type does not match <target>, or if <id> is the
1968 // active query object name for any query type, the error INVALID_OPERATION is
1969 // generated.
1970
1971 // Ensure no other queries are active
1972 // NOTE: If other queries than occlusion are supported, we will need to check
1973 // separately that:
1974 // a) The query ID passed is not the current active query for any target/type
1975 // b) There are no active queries for the requested target (and in the case
1976 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1977 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001978
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001979 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001980 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001981 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001982 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001983 }
1984
1985 Query *queryObject = context->getQuery(id, true, target);
1986
1987 // check that name was obtained with glGenQueries
1988 if (!queryObject)
1989 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001990 context->handleError(InvalidOperation() << "Invalid query id");
Geoff Langb1196682014-07-23 13:47:29 -04001991 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001992 }
1993
1994 // check for type mismatch
1995 if (queryObject->getType() != target)
1996 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001997 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001998 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001999 }
2000
2001 return true;
2002}
2003
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002004bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
2005{
2006 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002007 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002008 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002009 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002010 return false;
2011 }
2012
2013 return ValidateBeginQueryBase(context, target, id);
2014}
2015
2016bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04002017{
2018 if (!ValidQueryType(context, target))
2019 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002020 context->handleError(InvalidEnum() << "Invalid query target");
Geoff Langb1196682014-07-23 13:47:29 -04002021 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002022 }
2023
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002024 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04002025
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002026 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04002027 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002028 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04002029 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04002030 }
2031
Jamie Madill45c785d2014-05-13 14:09:34 -04002032 return true;
2033}
2034
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002035bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
2036{
2037 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002038 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002039 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002040 context->handleError(InvalidOperation() << "Query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002041 return false;
2042 }
2043
2044 return ValidateEndQueryBase(context, target);
2045}
2046
2047bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
2048{
2049 if (!context->getExtensions().disjointTimerQuery)
2050 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002051 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002052 return false;
2053 }
2054
2055 if (target != GL_TIMESTAMP_EXT)
2056 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002057 context->handleError(InvalidEnum() << "Invalid query target");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002058 return false;
2059 }
2060
2061 Query *queryObject = context->getQuery(id, true, target);
2062 if (queryObject == nullptr)
2063 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002064 context->handleError(InvalidOperation() << "Invalid query id");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002065 return false;
2066 }
2067
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002068 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002069 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002070 context->handleError(InvalidOperation() << "Query is active");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002071 return false;
2072 }
2073
2074 return true;
2075}
2076
Geoff Lang2186c382016-10-14 10:54:54 -04002077bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002078{
Geoff Lang2186c382016-10-14 10:54:54 -04002079 if (numParams)
2080 {
2081 *numParams = 0;
2082 }
2083
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002084 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
2085 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002086 context->handleError(InvalidEnum() << "Invalid query type");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002087 return false;
2088 }
2089
2090 switch (pname)
2091 {
2092 case GL_CURRENT_QUERY_EXT:
2093 if (target == GL_TIMESTAMP_EXT)
2094 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002095 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002096 return false;
2097 }
2098 break;
2099 case GL_QUERY_COUNTER_BITS_EXT:
2100 if (!context->getExtensions().disjointTimerQuery ||
2101 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
2102 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002103 context->handleError(InvalidEnum() << "Invalid pname");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002104 return false;
2105 }
2106 break;
2107 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002108 context->handleError(InvalidEnum() << "Invalid pname");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002109 return false;
2110 }
2111
Geoff Lang2186c382016-10-14 10:54:54 -04002112 if (numParams)
2113 {
2114 // All queries return only one value
2115 *numParams = 1;
2116 }
2117
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002118 return true;
2119}
2120
2121bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
2122{
2123 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002124 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002125 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002126 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002127 return false;
2128 }
2129
Geoff Lang2186c382016-10-14 10:54:54 -04002130 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002131}
2132
Geoff Lang2186c382016-10-14 10:54:54 -04002133bool ValidateGetQueryivRobustANGLE(Context *context,
2134 GLenum target,
2135 GLenum pname,
2136 GLsizei bufSize,
2137 GLsizei *length,
2138 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002139{
Geoff Lang2186c382016-10-14 10:54:54 -04002140 if (!ValidateRobustEntryPoint(context, bufSize))
2141 {
2142 return false;
2143 }
2144
2145 if (!ValidateGetQueryivBase(context, target, pname, length))
2146 {
2147 return false;
2148 }
2149
2150 if (!ValidateRobustBufferSize(context, bufSize, *length))
2151 {
2152 return false;
2153 }
2154
2155 return true;
2156}
2157
2158bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
2159{
2160 if (numParams)
2161 {
2162 *numParams = 0;
2163 }
2164
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002165 Query *queryObject = context->getQuery(id, false, GL_NONE);
2166
2167 if (!queryObject)
2168 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002169 context->handleError(InvalidOperation() << "Query does not exist");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002170 return false;
2171 }
2172
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002173 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002174 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002175 context->handleError(InvalidOperation() << "Query currently active");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002176 return false;
2177 }
2178
2179 switch (pname)
2180 {
2181 case GL_QUERY_RESULT_EXT:
2182 case GL_QUERY_RESULT_AVAILABLE_EXT:
2183 break;
2184
2185 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002186 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002187 return false;
2188 }
2189
Geoff Lang2186c382016-10-14 10:54:54 -04002190 if (numParams)
2191 {
2192 *numParams = 1;
2193 }
2194
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002195 return true;
2196}
2197
2198bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
2199{
2200 if (!context->getExtensions().disjointTimerQuery)
2201 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002202 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002203 return false;
2204 }
Geoff Lang2186c382016-10-14 10:54:54 -04002205 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2206}
2207
2208bool ValidateGetQueryObjectivRobustANGLE(Context *context,
2209 GLuint id,
2210 GLenum pname,
2211 GLsizei bufSize,
2212 GLsizei *length,
2213 GLint *params)
2214{
2215 if (!context->getExtensions().disjointTimerQuery)
2216 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002217 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04002218 return false;
2219 }
2220
2221 if (!ValidateRobustEntryPoint(context, bufSize))
2222 {
2223 return false;
2224 }
2225
2226 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2227 {
2228 return false;
2229 }
2230
2231 if (!ValidateRobustBufferSize(context, bufSize, *length))
2232 {
2233 return false;
2234 }
2235
2236 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002237}
2238
2239bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
2240{
2241 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04002242 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002243 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002244 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002245 return false;
2246 }
Geoff Lang2186c382016-10-14 10:54:54 -04002247 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2248}
2249
2250bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
2251 GLuint id,
2252 GLenum pname,
2253 GLsizei bufSize,
2254 GLsizei *length,
2255 GLuint *params)
2256{
2257 if (!context->getExtensions().disjointTimerQuery &&
2258 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2259 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002260 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002261 return false;
2262 }
2263
2264 if (!ValidateRobustEntryPoint(context, bufSize))
2265 {
2266 return false;
2267 }
2268
2269 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2270 {
2271 return false;
2272 }
2273
2274 if (!ValidateRobustBufferSize(context, bufSize, *length))
2275 {
2276 return false;
2277 }
2278
2279 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002280}
2281
2282bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2283{
2284 if (!context->getExtensions().disjointTimerQuery)
2285 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002286 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002287 return false;
2288 }
Geoff Lang2186c382016-10-14 10:54:54 -04002289 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2290}
2291
2292bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2293 GLuint id,
2294 GLenum pname,
2295 GLsizei bufSize,
2296 GLsizei *length,
2297 GLint64 *params)
2298{
2299 if (!context->getExtensions().disjointTimerQuery)
2300 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002301 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002302 return false;
2303 }
2304
2305 if (!ValidateRobustEntryPoint(context, bufSize))
2306 {
2307 return false;
2308 }
2309
2310 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2311 {
2312 return false;
2313 }
2314
2315 if (!ValidateRobustBufferSize(context, bufSize, *length))
2316 {
2317 return false;
2318 }
2319
2320 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002321}
2322
2323bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2324{
2325 if (!context->getExtensions().disjointTimerQuery)
2326 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002327 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002328 return false;
2329 }
Geoff Lang2186c382016-10-14 10:54:54 -04002330 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2331}
2332
2333bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2334 GLuint id,
2335 GLenum pname,
2336 GLsizei bufSize,
2337 GLsizei *length,
2338 GLuint64 *params)
2339{
2340 if (!context->getExtensions().disjointTimerQuery)
2341 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002342 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002343 return false;
2344 }
2345
2346 if (!ValidateRobustEntryPoint(context, bufSize))
2347 {
2348 return false;
2349 }
2350
2351 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2352 {
2353 return false;
2354 }
2355
2356 if (!ValidateRobustBufferSize(context, bufSize, *length))
2357 {
2358 return false;
2359 }
2360
2361 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002362}
2363
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002364bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002365 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002366 GLuint program,
2367 GLint location,
2368 GLsizei count)
2369{
2370 // Check for ES31 program uniform entry points
2371 if (context->getClientVersion() < Version(3, 1))
2372 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002373 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002374 return false;
2375 }
2376
2377 const LinkedUniform *uniform = nullptr;
2378 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002379 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2380 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002381}
2382
Frank Henigmana98a6472017-02-02 21:38:32 -05002383bool ValidateProgramUniform1iv(gl::Context *context,
2384 GLuint program,
2385 GLint location,
2386 GLsizei count,
2387 const GLint *value)
2388{
2389 // Check for ES31 program uniform entry points
2390 if (context->getClientVersion() < Version(3, 1))
2391 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002392 context->handleError(InvalidOperation());
Frank Henigmana98a6472017-02-02 21:38:32 -05002393 return false;
2394 }
2395
2396 const LinkedUniform *uniform = nullptr;
2397 gl::Program *programObject = GetValidProgram(context, program);
2398 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2399 ValidateUniform1ivValue(context, uniform->type, count, value);
2400}
2401
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002402bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002403 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002404 GLuint program,
2405 GLint location,
2406 GLsizei count,
2407 GLboolean transpose)
2408{
2409 // Check for ES31 program uniform entry points
2410 if (context->getClientVersion() < Version(3, 1))
2411 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002412 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002413 return false;
2414 }
2415
2416 const LinkedUniform *uniform = nullptr;
2417 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002418 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2419 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002420}
2421
Jamie Madillc1d770e2017-04-13 17:31:24 -04002422bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002423{
2424 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002425 if (VariableComponentType(valueType) == GL_UNSIGNED_INT && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002427 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002428 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002429 }
2430
Jamie Madill62d31cb2015-09-11 13:25:51 -04002431 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002432 gl::Program *programObject = context->getGLState().getProgram();
2433 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2434 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002435}
2436
Jamie Madillbe849e42017-05-02 15:49:00 -04002437bool ValidateUniform1iv(ValidationContext *context,
2438 GLint location,
2439 GLsizei count,
2440 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002441{
2442 const LinkedUniform *uniform = nullptr;
2443 gl::Program *programObject = context->getGLState().getProgram();
2444 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2445 ValidateUniform1ivValue(context, uniform->type, count, value);
2446}
2447
Jamie Madillc1d770e2017-04-13 17:31:24 -04002448bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002449 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002450 GLint location,
2451 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002452 GLboolean transpose)
2453{
2454 // Check for ES3 uniform entry points
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002455 int rows = VariableRowCount(valueType);
2456 int cols = VariableColumnCount(valueType);
Martin Radev1be913c2016-07-11 17:59:16 +03002457 if (rows != cols && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002458 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002459 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002460 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002461 }
2462
Martin Radev1be913c2016-07-11 17:59:16 +03002463 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002464 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002465 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002466 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002467 }
2468
Jamie Madill62d31cb2015-09-11 13:25:51 -04002469 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002470 gl::Program *programObject = context->getGLState().getProgram();
2471 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2472 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002473}
2474
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002475bool ValidateStateQuery(ValidationContext *context,
2476 GLenum pname,
2477 GLenum *nativeType,
2478 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002479{
2480 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2481 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002482 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002483 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002484 }
2485
Jamie Madill0af26e12015-03-05 19:54:33 -05002486 const Caps &caps = context->getCaps();
2487
Jamie Madill893ab082014-05-16 16:56:10 -04002488 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2489 {
2490 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2491
Jamie Madill0af26e12015-03-05 19:54:33 -05002492 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002493 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002494 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002495 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002496 }
2497 }
2498
2499 switch (pname)
2500 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002501 case GL_TEXTURE_BINDING_2D:
2502 case GL_TEXTURE_BINDING_CUBE_MAP:
2503 case GL_TEXTURE_BINDING_3D:
2504 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002505 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002506 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002507 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2508 if (!context->getExtensions().textureRectangle)
2509 {
2510 context->handleError(InvalidEnum()
2511 << "ANGLE_texture_rectangle extension not present");
2512 return false;
2513 }
2514 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002515 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2516 if (!context->getExtensions().eglStreamConsumerExternal &&
2517 !context->getExtensions().eglImageExternal)
2518 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002519 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2520 "nor GL_OES_EGL_image_external "
2521 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002522 return false;
2523 }
2524 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002525
He Yunchaoced53ae2016-11-29 15:00:51 +08002526 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2527 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002528 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002529 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2530 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002531 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002532 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002533 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002534 }
2535
Jamie Madill51f40ec2016-06-15 14:06:00 -04002536 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2537 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002538
2539 if (framebuffer->getReadBufferState() == GL_NONE)
2540 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002541 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Martin Radev138064f2016-07-15 12:03:41 +03002542 return false;
2543 }
2544
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002545 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002546 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002547 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002548 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002549 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002550 }
2551 }
2552 break;
2553
He Yunchaoced53ae2016-11-29 15:00:51 +08002554 default:
2555 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002556 }
2557
2558 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002559 if (*numParams == 0)
2560 {
2561 return false;
2562 }
2563
2564 return true;
2565}
2566
2567bool ValidateRobustStateQuery(ValidationContext *context,
2568 GLenum pname,
2569 GLsizei bufSize,
2570 GLenum *nativeType,
2571 unsigned int *numParams)
2572{
2573 if (!ValidateRobustEntryPoint(context, bufSize))
2574 {
2575 return false;
2576 }
2577
2578 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2579 {
2580 return false;
2581 }
2582
2583 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002584 {
2585 return false;
2586 }
2587
2588 return true;
2589}
2590
Jamie Madillc29968b2016-01-20 11:17:23 -05002591bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2592 GLenum target,
2593 GLint level,
2594 GLenum internalformat,
2595 bool isSubImage,
2596 GLint xoffset,
2597 GLint yoffset,
2598 GLint zoffset,
2599 GLint x,
2600 GLint y,
2601 GLsizei width,
2602 GLsizei height,
2603 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002604 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002605{
Brandon Jones6cad5662017-06-14 13:25:13 -07002606 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002607 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002608 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2609 return false;
2610 }
2611
2612 if (width < 0 || height < 0)
2613 {
2614 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002615 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002616 }
2617
He Yunchaoced53ae2016-11-29 15:00:51 +08002618 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2619 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002620 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002621 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002622 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002623 }
2624
2625 if (border != 0)
2626 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002627 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002628 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002629 }
2630
2631 if (!ValidMipLevel(context, target, level))
2632 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002633 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002634 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002635 }
2636
Jamie Madill51f40ec2016-06-15 14:06:00 -04002637 const auto &state = context->getGLState();
2638 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002639 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002640 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002641 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002642 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002643 }
2644
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002645 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002647 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002648 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002649 }
2650
Martin Radev138064f2016-07-15 12:03:41 +03002651 if (readFramebuffer->getReadBufferState() == GL_NONE)
2652 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002653 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Martin Radev138064f2016-07-15 12:03:41 +03002654 return false;
2655 }
2656
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002657 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2658 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002659 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002660 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002661 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2662 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002663 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002664 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002665 return false;
2666 }
2667
Martin Radev04e2c3b2017-07-27 16:54:35 +03002668 // ANGLE_multiview spec, Revision 1:
2669 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2670 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2671 // is not NONE.
2672 if (source->getMultiviewLayout() != GL_NONE)
2673 {
2674 context->handleError(InvalidFramebufferOperation()
2675 << "The active read framebuffer object has multiview attachments.");
2676 return false;
2677 }
2678
Geoff Langaae65a42014-05-26 12:43:44 -04002679 const gl::Caps &caps = context->getCaps();
2680
Geoff Langaae65a42014-05-26 12:43:44 -04002681 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002682 switch (target)
2683 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002684 case GL_TEXTURE_2D:
2685 maxDimension = caps.max2DTextureSize;
2686 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002687
He Yunchaoced53ae2016-11-29 15:00:51 +08002688 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2689 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2690 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2691 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2692 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2693 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2694 maxDimension = caps.maxCubeMapTextureSize;
2695 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002696
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002697 case GL_TEXTURE_RECTANGLE_ANGLE:
2698 maxDimension = caps.maxRectangleTextureSize;
2699 break;
2700
He Yunchaoced53ae2016-11-29 15:00:51 +08002701 case GL_TEXTURE_2D_ARRAY:
2702 maxDimension = caps.max2DTextureSize;
2703 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002704
He Yunchaoced53ae2016-11-29 15:00:51 +08002705 case GL_TEXTURE_3D:
2706 maxDimension = caps.max3DTextureSize;
2707 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002708
He Yunchaoced53ae2016-11-29 15:00:51 +08002709 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002710 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002711 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002712 }
2713
Jamie Madillc29968b2016-01-20 11:17:23 -05002714 gl::Texture *texture =
2715 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002716 if (!texture)
2717 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002718 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002719 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002720 }
2721
Geoff Lang69cce582015-09-17 13:20:36 -04002722 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002724 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002725 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002726 }
2727
Geoff Langca271392017-04-05 12:30:00 -04002728 const gl::InternalFormat &formatInfo =
2729 gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002730
Geoff Lang966c9402017-04-18 12:38:27 -04002731 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002732 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002733 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002734 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002735 }
2736
2737 if (isSubImage)
2738 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002739 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2740 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2741 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002743 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002744 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002745 }
2746 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002747 else
2748 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002749 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002750 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002751 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002752 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002753 }
2754
Geoff Langeb66a6e2016-10-31 13:06:12 -04002755 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002756 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002757 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002758 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002759 }
2760
2761 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002762 if (static_cast<int>(width) > maxLevelDimension ||
2763 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002764 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002765 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002766 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002767 }
2768 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002769
Jamie Madill0c8abca2016-07-22 20:21:26 -04002770 if (textureFormatOut)
2771 {
2772 *textureFormatOut = texture->getFormat(target, level);
2773 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002774
2775 // Detect texture copying feedback loops for WebGL.
2776 if (context->getExtensions().webglCompatibility)
2777 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002778 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002779 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002780 context->handleError(InvalidOperation() << "Texture copying feedback loop formed "
2781 "between Framebuffer and specified "
2782 "Texture level.");
Jamie Madillf695a3a2017-01-11 17:36:35 -05002783 return false;
2784 }
2785 }
2786
Jamie Madill560a8d82014-05-21 13:06:20 -04002787 return true;
2788}
2789
Jiajia Qind9671222016-11-29 16:30:31 +08002790bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002791{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002792 switch (mode)
2793 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002794 case GL_POINTS:
2795 case GL_LINES:
2796 case GL_LINE_LOOP:
2797 case GL_LINE_STRIP:
2798 case GL_TRIANGLES:
2799 case GL_TRIANGLE_STRIP:
2800 case GL_TRIANGLE_FAN:
2801 break;
2802 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002803 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002804 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002805 }
2806
Jamie Madill250d33f2014-06-06 17:09:03 -04002807 if (count < 0)
2808 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002809 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002810 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002811 }
2812
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002813 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002814
Jamie Madill250d33f2014-06-06 17:09:03 -04002815 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002816 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002817 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002818 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002819 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002820 }
2821
Jamie Madillcbcde722017-01-06 14:50:00 -05002822 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2823 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002824 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002825 const Extensions &extensions = context->getExtensions();
2826 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002827 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002828 const FramebufferAttachment *dsAttachment =
2829 framebuffer->getStencilOrDepthStencilAttachment();
2830 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002831 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002832 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002833
2834 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2835 bool differentWritemasks =
2836 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2837 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2838 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2839 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2840
2841 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002842 {
Martin Radevffe754b2017-07-31 10:38:07 +03002843 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002844 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002845 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2846 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002847 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002848 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002849 return false;
2850 }
Jamie Madillac528012014-06-20 13:21:23 -04002851 }
2852
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002853 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002854 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002855 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002856 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002857 }
2858
Geoff Lang7dd2e102014-11-10 15:19:26 -05002859 gl::Program *program = state.getProgram();
2860 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002861 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002862 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002863 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002864 }
2865
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002866 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002867 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002868 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002869 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002870 }
2871
Martin Radevffe754b2017-07-31 10:38:07 +03002872 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002873 {
Martin Radev7e69f762017-07-27 14:54:13 +03002874 const int programNumViews = program->getNumViews();
2875 const int framebufferNumViews = framebuffer->getNumViews();
2876 if (programNumViews != -1 && framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002877 {
2878 context->handleError(InvalidOperation() << "The number of views in the active program "
2879 "and draw framebuffer does not match.");
2880 return false;
2881 }
Martin Radev7e69f762017-07-27 14:54:13 +03002882
2883 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2884 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2885 framebufferNumViews > 1)
2886 {
2887 context->handleError(InvalidOperation()
2888 << "There is an active transform feedback object "
2889 "when the number of views in the active draw "
2890 "framebuffer is greater than 1.");
2891 return false;
2892 }
Martin Radevffe754b2017-07-31 10:38:07 +03002893
2894 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2895 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2896 {
2897 context->handleError(InvalidOperation() << "There is an active query for target "
2898 "GL_TIME_ELAPSED_EXT when the number of "
2899 "views in the active draw framebuffer is "
2900 "greater than 1.");
2901 return false;
2902 }
Martin Radev7cf61662017-07-26 17:10:53 +03002903 }
2904
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002905 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002906 for (unsigned int uniformBlockIndex = 0;
2907 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002908 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002909 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002910 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002911 const OffsetBindingPointer<Buffer> &uniformBuffer =
2912 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002913
Geoff Lang5d124a62015-09-15 13:03:27 -04002914 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002915 {
2916 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002917 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002918 InvalidOperation()
2919 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002920 return false;
2921 }
2922
Geoff Lang5d124a62015-09-15 13:03:27 -04002923 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002924 if (uniformBufferSize == 0)
2925 {
2926 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002927 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002928 }
2929
Jamie Madill62d31cb2015-09-11 13:25:51 -04002930 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002931 {
2932 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002933 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002934 InvalidOperation()
2935 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002936 return false;
2937 }
2938 }
2939
Geoff Lange0cff192017-05-30 13:04:56 -04002940 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002941 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002942 {
Geoff Lange0cff192017-05-30 13:04:56 -04002943 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002944 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2945 {
2946 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002947 InvalidOperation()
2948 << "Rendering feedback loop formed between Framebuffer and active Texture.");
Jamie Madilla4595b82017-01-11 17:36:34 -05002949 return false;
2950 }
Geoff Lange0cff192017-05-30 13:04:56 -04002951
Geoff Lang9ab5b822017-05-30 16:19:23 -04002952 // Detect that the vertex shader input types match the attribute types
2953 if (!ValidateVertexShaderAttributeTypeMatch(context))
2954 {
2955 return false;
2956 }
2957
Geoff Lange0cff192017-05-30 13:04:56 -04002958 // Detect that the color buffer types match the fragment shader output types
2959 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2960 {
2961 return false;
2962 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002963 }
2964
Jamie Madill250d33f2014-06-06 17:09:03 -04002965 // No-op if zero count
2966 return (count > 0);
2967}
2968
Jamie Madillc1d770e2017-04-13 17:31:24 -04002969bool ValidateDrawArraysCommon(ValidationContext *context,
2970 GLenum mode,
2971 GLint first,
2972 GLsizei count,
2973 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002974{
Jamie Madillfd716582014-06-06 17:09:04 -04002975 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002976 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002977 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002978 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002979 }
2980
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002981 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002982 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002983 if (curTransformFeedback && curTransformFeedback->isActive() &&
2984 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002985 {
2986 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002987 // that does not match the current transform feedback object's draw mode (if transform
2988 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002989 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002990 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002991 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002992 }
2993
Jiajia Qind9671222016-11-29 16:30:31 +08002994 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002995 {
2996 return false;
2997 }
2998
Corentin Wallez71168a02016-12-19 15:11:18 -08002999 // Check the computation of maxVertex doesn't overflow.
3000 // - first < 0 or count < 0 have been checked as an error condition
3001 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
3002 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
3003 ASSERT(count > 0 && first >= 0);
3004 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
3005 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05003006 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003007 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05003008 return false;
3009 }
3010
Corentin Wallez71168a02016-12-19 15:11:18 -08003011 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04003012 {
3013 return false;
3014 }
3015
3016 return true;
3017}
3018
He Yunchaoced53ae2016-11-29 15:00:51 +08003019bool ValidateDrawArraysInstanced(Context *context,
3020 GLenum mode,
3021 GLint first,
3022 GLsizei count,
3023 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003024{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003025 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
Geoff Lang87a93302014-09-16 13:29:43 -04003026}
3027
He Yunchaoced53ae2016-11-29 15:00:51 +08003028bool ValidateDrawArraysInstancedANGLE(Context *context,
3029 GLenum mode,
3030 GLint first,
3031 GLsizei count,
3032 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003033{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003034 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003035 {
3036 return false;
3037 }
3038
Corentin Wallez0dc97812017-06-22 14:38:44 -04003039 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003040}
3041
Jiajia Qind9671222016-11-29 16:30:31 +08003042bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04003043{
Jamie Madill250d33f2014-06-06 17:09:03 -04003044 switch (type)
3045 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003046 case GL_UNSIGNED_BYTE:
3047 case GL_UNSIGNED_SHORT:
3048 break;
3049 case GL_UNSIGNED_INT:
3050 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
3051 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003052 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08003053 return false;
3054 }
3055 break;
3056 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003057 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08003058 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003059 }
3060
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003061 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003062
3063 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08003064 if (curTransformFeedback && curTransformFeedback->isActive() &&
3065 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04003066 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003067 // It is an invalid operation to call DrawElements, DrawRangeElements or
3068 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04003069 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003070 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003071 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003072 }
3073
Jiajia Qind9671222016-11-29 16:30:31 +08003074 return true;
3075}
3076
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003077bool ValidateDrawElementsCommon(ValidationContext *context,
3078 GLenum mode,
3079 GLsizei count,
3080 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003081 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003082 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08003083{
3084 if (!ValidateDrawElementsBase(context, type))
3085 return false;
3086
3087 const State &state = context->getGLState();
3088
Corentin Wallez170efbf2017-05-02 13:45:01 -04003089 if (!ValidateDrawBase(context, mode, count))
3090 {
3091 return false;
3092 }
3093
Jamie Madill250d33f2014-06-06 17:09:03 -04003094 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04003095 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04003096 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003097 context->handleError(InvalidOperation() << "Index buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -04003098 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04003099 }
3100
He Yunchaoced53ae2016-11-29 15:00:51 +08003101 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04003102 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04003103
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003104 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
3105
3106 if (context->getExtensions().webglCompatibility)
3107 {
3108 ASSERT(isPow2(typeBytes) && typeBytes > 0);
3109 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
3110 {
3111 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3112 // The offset arguments to drawElements and [...], must be a multiple of the size of the
3113 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003114 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003115 return false;
3116 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003117
3118 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
3119 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
3120 // error is generated.
3121 if (reinterpret_cast<intptr_t>(indices) < 0)
3122 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003123 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003124 return false;
3125 }
Geoff Langfeb8c682017-02-13 16:07:35 -05003126 }
3127
3128 if (context->getExtensions().webglCompatibility ||
3129 !context->getGLState().areClientArraysEnabled())
3130 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003131 if (!elementArrayBuffer && count > 0)
3132 {
3133 // [WebGL 1.0] Section 6.2 No Client Side Arrays
3134 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
3135 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07003136 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05003137 return false;
3138 }
3139 }
3140
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003141 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04003142 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003143 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04003144 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003145 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
3146 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
3147 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
3148 constexpr uint64_t kMaxTypeSize = 8;
3149 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
3150 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
3151 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003152
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003153 uint64_t typeSize = typeBytes;
3154 uint64_t elementCount = static_cast<uint64_t>(count);
3155 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
3156
3157 // Doing the multiplication here is overflow-safe
3158 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
3159
3160 // The offset can be any value, check for overflows
3161 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
3162 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003163 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003164 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003165 return false;
3166 }
3167
Corentin Wallezfe9306a2017-02-01 17:41:05 -05003168 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
3169 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003170 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003171 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05003172 return false;
3173 }
3174 }
3175 else if (!indices)
3176 {
3177 // This is an application error that would normally result in a crash,
3178 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003179 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04003180 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04003181 }
Jamie Madillae3000b2014-08-25 15:47:51 -04003182 }
3183
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003184 // Use the parameter buffer to retrieve and cache the index range.
Jamie Madill2b976812014-08-25 15:47:49 -04003185 // TODO: offer fast path, with disabled index validation.
3186 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003187 const auto &params = context->getParams<HasIndexRange>();
3188 const auto &indexRangeOpt = params.getIndexRange();
3189 if (!indexRangeOpt.valid())
Jamie Madill2b976812014-08-25 15:47:49 -04003190 {
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003191 // Unexpected error.
3192 return false;
Jamie Madill2b976812014-08-25 15:47:49 -04003193 }
3194
Jamie Madille79b1e12015-11-04 16:36:37 -05003195 // If we use an index greater than our maximum supported index range, return an error.
3196 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
3197 // return an error if possible here.
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003198 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
Jamie Madille79b1e12015-11-04 16:36:37 -05003199 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003200 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
Jamie Madille79b1e12015-11-04 16:36:37 -05003201 return false;
3202 }
3203
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003204 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
3205 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04003206 {
3207 return false;
3208 }
3209
Geoff Lang3edfe032015-09-04 16:38:24 -04003210 // No op if there are no real indices in the index data (all are primitive restart).
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003211 return (indexRangeOpt.value().vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04003212}
3213
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003214bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
3215 GLenum mode,
3216 GLsizei count,
3217 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003218 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003219 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04003220{
Corentin Wallez0dc97812017-06-22 14:38:44 -04003221 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04003222}
3223
Geoff Lang3edfe032015-09-04 16:38:24 -04003224bool ValidateDrawElementsInstancedANGLE(Context *context,
3225 GLenum mode,
3226 GLsizei count,
3227 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003228 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003229 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04003230{
Corentin Wallez170efbf2017-05-02 13:45:01 -04003231 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04003232 {
3233 return false;
3234 }
3235
Corentin Wallez0dc97812017-06-22 14:38:44 -04003236 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04003237}
3238
He Yunchaoced53ae2016-11-29 15:00:51 +08003239bool ValidateFramebufferTextureBase(Context *context,
3240 GLenum target,
3241 GLenum attachment,
3242 GLuint texture,
3243 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003244{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003245 if (!ValidFramebufferTarget(target))
3246 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003247 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003248 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003249 }
3250
3251 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003252 {
3253 return false;
3254 }
3255
Jamie Madill55ec3b12014-07-03 10:38:57 -04003256 if (texture != 0)
3257 {
3258 gl::Texture *tex = context->getTexture(texture);
3259
Jamie Madillbe849e42017-05-02 15:49:00 -04003260 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003261 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003262 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003263 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003264 }
3265
3266 if (level < 0)
3267 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003268 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003269 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003270 }
3271 }
3272
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003273 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003274 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003275
Jamie Madill84115c92015-04-23 15:00:07 -04003276 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003277 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003278 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003279 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003280 }
3281
3282 return true;
3283}
3284
Geoff Langb1196682014-07-23 13:47:29 -04003285bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003286{
3287 if (program == 0)
3288 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003289 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003290 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003291 }
3292
Dian Xiang769769a2015-09-09 15:20:08 -07003293 gl::Program *programObject = GetValidProgram(context, program);
3294 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003295 {
3296 return false;
3297 }
3298
Jamie Madill0063c512014-08-25 15:47:53 -04003299 if (!programObject || !programObject->isLinked())
3300 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003301 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003302 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003303 }
3304
Geoff Lang7dd2e102014-11-10 15:19:26 -05003305 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003306 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003307 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003308 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003309 }
3310
Jamie Madill0063c512014-08-25 15:47:53 -04003311 return true;
3312}
3313
Geoff Langf41d0ee2016-10-07 13:04:23 -04003314static bool ValidateSizedGetUniform(Context *context,
3315 GLuint program,
3316 GLint location,
3317 GLsizei bufSize,
3318 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003319{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003320 if (length)
3321 {
3322 *length = 0;
3323 }
3324
Jamie Madill78f41802014-08-25 15:47:55 -04003325 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003326 {
Jamie Madill78f41802014-08-25 15:47:55 -04003327 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003328 }
3329
Geoff Langf41d0ee2016-10-07 13:04:23 -04003330 if (bufSize < 0)
3331 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003332 context->handleError(InvalidValue() << "bufSize cannot be negative.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003333 return false;
3334 }
3335
Jamie Madilla502c742014-08-28 17:19:13 -04003336 gl::Program *programObject = context->getProgram(program);
3337 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003338
Jamie Madill78f41802014-08-25 15:47:55 -04003339 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003340 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003341 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003342 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003343 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003344 context->handleError(InvalidOperation()
3345 << "bufSize of at least " << requiredBytes << " is required.");
Geoff Langb1196682014-07-23 13:47:29 -04003346 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003347 }
3348
Geoff Langf41d0ee2016-10-07 13:04:23 -04003349 if (length)
3350 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003351 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003352 }
3353
Jamie Madill0063c512014-08-25 15:47:53 -04003354 return true;
3355}
3356
He Yunchaoced53ae2016-11-29 15:00:51 +08003357bool ValidateGetnUniformfvEXT(Context *context,
3358 GLuint program,
3359 GLint location,
3360 GLsizei bufSize,
3361 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003362{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003363 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003364}
3365
He Yunchaoced53ae2016-11-29 15:00:51 +08003366bool ValidateGetnUniformivEXT(Context *context,
3367 GLuint program,
3368 GLint location,
3369 GLsizei bufSize,
3370 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003371{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003372 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3373}
3374
3375bool ValidateGetUniformfvRobustANGLE(Context *context,
3376 GLuint program,
3377 GLint location,
3378 GLsizei bufSize,
3379 GLsizei *length,
3380 GLfloat *params)
3381{
3382 if (!ValidateRobustEntryPoint(context, bufSize))
3383 {
3384 return false;
3385 }
3386
3387 // bufSize is validated in ValidateSizedGetUniform
3388 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3389}
3390
3391bool ValidateGetUniformivRobustANGLE(Context *context,
3392 GLuint program,
3393 GLint location,
3394 GLsizei bufSize,
3395 GLsizei *length,
3396 GLint *params)
3397{
3398 if (!ValidateRobustEntryPoint(context, bufSize))
3399 {
3400 return false;
3401 }
3402
3403 // bufSize is validated in ValidateSizedGetUniform
3404 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3405}
3406
3407bool ValidateGetUniformuivRobustANGLE(Context *context,
3408 GLuint program,
3409 GLint location,
3410 GLsizei bufSize,
3411 GLsizei *length,
3412 GLuint *params)
3413{
3414 if (!ValidateRobustEntryPoint(context, bufSize))
3415 {
3416 return false;
3417 }
3418
3419 if (context->getClientMajorVersion() < 3)
3420 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003421 context->handleError(InvalidOperation() << "Entry point requires at least OpenGL ES 3.0.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003422 return false;
3423 }
3424
3425 // bufSize is validated in ValidateSizedGetUniform
3426 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003427}
3428
He Yunchaoced53ae2016-11-29 15:00:51 +08003429bool ValidateDiscardFramebufferBase(Context *context,
3430 GLenum target,
3431 GLsizei numAttachments,
3432 const GLenum *attachments,
3433 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003434{
3435 if (numAttachments < 0)
3436 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003437 context->handleError(InvalidValue() << "numAttachments must not be less than zero");
Austin Kinross08332632015-05-05 13:35:47 -07003438 return false;
3439 }
3440
3441 for (GLsizei i = 0; i < numAttachments; ++i)
3442 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003443 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003444 {
3445 if (defaultFramebuffer)
3446 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003447 context->handleError(InvalidEnum()
3448 << "Invalid attachment when the default framebuffer is bound");
Austin Kinross08332632015-05-05 13:35:47 -07003449 return false;
3450 }
3451
3452 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3453 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003454 context->handleError(InvalidOperation() << "Requested color attachment is "
3455 "greater than the maximum supported "
3456 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003457 return false;
3458 }
3459 }
3460 else
3461 {
3462 switch (attachments[i])
3463 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003464 case GL_DEPTH_ATTACHMENT:
3465 case GL_STENCIL_ATTACHMENT:
3466 case GL_DEPTH_STENCIL_ATTACHMENT:
3467 if (defaultFramebuffer)
3468 {
3469 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003470 InvalidEnum()
3471 << "Invalid attachment when the default framebuffer is bound");
He Yunchaoced53ae2016-11-29 15:00:51 +08003472 return false;
3473 }
3474 break;
3475 case GL_COLOR:
3476 case GL_DEPTH:
3477 case GL_STENCIL:
3478 if (!defaultFramebuffer)
3479 {
3480 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003481 InvalidEnum()
3482 << "Invalid attachment when the default framebuffer is not bound");
He Yunchaoced53ae2016-11-29 15:00:51 +08003483 return false;
3484 }
3485 break;
3486 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003487 context->handleError(InvalidEnum() << "Invalid attachment");
Austin Kinross08332632015-05-05 13:35:47 -07003488 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003489 }
3490 }
3491 }
3492
3493 return true;
3494}
3495
Austin Kinross6ee1e782015-05-29 17:05:37 -07003496bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3497{
3498 // Note that debug marker calls must not set error state
3499
3500 if (length < 0)
3501 {
3502 return false;
3503 }
3504
3505 if (marker == nullptr)
3506 {
3507 return false;
3508 }
3509
3510 return true;
3511}
3512
3513bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3514{
3515 // Note that debug marker calls must not set error state
3516
3517 if (length < 0)
3518 {
3519 return false;
3520 }
3521
3522 if (length > 0 && marker == nullptr)
3523 {
3524 return false;
3525 }
3526
3527 return true;
3528}
3529
Geoff Langdcab33b2015-07-21 13:03:16 -04003530bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003531 GLenum target,
3532 egl::Image *image)
3533{
Geoff Langa8406172015-07-21 16:53:39 -04003534 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3535 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003536 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003537 return false;
3538 }
3539
3540 switch (target)
3541 {
3542 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003543 if (!context->getExtensions().eglImage)
3544 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003545 context->handleError(InvalidEnum()
3546 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003547 }
3548 break;
3549
3550 case GL_TEXTURE_EXTERNAL_OES:
3551 if (!context->getExtensions().eglImageExternal)
3552 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003553 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3554 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003555 }
Geoff Langa8406172015-07-21 16:53:39 -04003556 break;
3557
3558 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003559 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003560 return false;
3561 }
3562
Jamie Madill61e16b42017-06-19 11:13:23 -04003563 ASSERT(context->getCurrentDisplay());
3564 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003565 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003566 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003567 return false;
3568 }
3569
3570 if (image->getSamples() > 0)
3571 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003572 context->handleError(InvalidOperation()
3573 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003574 return false;
3575 }
3576
Geoff Langca271392017-04-05 12:30:00 -04003577 const TextureCaps &textureCaps =
3578 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003579 if (!textureCaps.texturable)
3580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003581 context->handleError(InvalidOperation()
3582 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003583 return false;
3584 }
3585
Geoff Langdcab33b2015-07-21 13:03:16 -04003586 return true;
3587}
3588
3589bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003590 GLenum target,
3591 egl::Image *image)
3592{
Geoff Langa8406172015-07-21 16:53:39 -04003593 if (!context->getExtensions().eglImage)
3594 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003595 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003596 return false;
3597 }
3598
3599 switch (target)
3600 {
3601 case GL_RENDERBUFFER:
3602 break;
3603
3604 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003605 context->handleError(InvalidEnum() << "invalid renderbuffer target.");
Geoff Langa8406172015-07-21 16:53:39 -04003606 return false;
3607 }
3608
Jamie Madill61e16b42017-06-19 11:13:23 -04003609 ASSERT(context->getCurrentDisplay());
3610 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003611 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003612 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003613 return false;
3614 }
3615
Geoff Langca271392017-04-05 12:30:00 -04003616 const TextureCaps &textureCaps =
3617 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003618 if (!textureCaps.renderable)
3619 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003620 context->handleError(InvalidOperation()
3621 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003622 return false;
3623 }
3624
Geoff Langdcab33b2015-07-21 13:03:16 -04003625 return true;
3626}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003627
3628bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3629{
Geoff Lang36167ab2015-12-07 10:27:14 -05003630 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003631 {
3632 // The default VAO should always exist
3633 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003634 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003635 return false;
3636 }
3637
3638 return true;
3639}
3640
Geoff Langc5629752015-12-07 16:29:04 -05003641bool ValidateProgramBinaryBase(Context *context,
3642 GLuint program,
3643 GLenum binaryFormat,
3644 const void *binary,
3645 GLint length)
3646{
3647 Program *programObject = GetValidProgram(context, program);
3648 if (programObject == nullptr)
3649 {
3650 return false;
3651 }
3652
3653 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3654 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3655 programBinaryFormats.end())
3656 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003657 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003658 return false;
3659 }
3660
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003661 if (context->hasActiveTransformFeedback(program))
3662 {
3663 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003664 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3665 "is associated with an active transform "
3666 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003667 return false;
3668 }
3669
Geoff Langc5629752015-12-07 16:29:04 -05003670 return true;
3671}
3672
3673bool ValidateGetProgramBinaryBase(Context *context,
3674 GLuint program,
3675 GLsizei bufSize,
3676 GLsizei *length,
3677 GLenum *binaryFormat,
3678 void *binary)
3679{
3680 Program *programObject = GetValidProgram(context, program);
3681 if (programObject == nullptr)
3682 {
3683 return false;
3684 }
3685
3686 if (!programObject->isLinked())
3687 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003688 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003689 return false;
3690 }
3691
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003692 if (context->getCaps().programBinaryFormats.empty())
3693 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003694 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003695 return false;
3696 }
3697
Geoff Langc5629752015-12-07 16:29:04 -05003698 return true;
3699}
Jamie Madillc29968b2016-01-20 11:17:23 -05003700
Jamie Madillc29968b2016-01-20 11:17:23 -05003701bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3702{
3703 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
3704 if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3705 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003706 context->handleError(InvalidValue()
3707 << "n must be non-negative and no greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003708 return false;
3709 }
3710
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003711 ASSERT(context->getGLState().getDrawFramebuffer());
3712 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003713 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3714
3715 // This should come first before the check for the default frame buffer
3716 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3717 // rather than INVALID_OPERATION
3718 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3719 {
3720 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3721
3722 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003723 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3724 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003725 {
3726 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003727 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3728 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3729 // 3.1 is still a bit ambiguous about the error, but future specs are
3730 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003731 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003732 return false;
3733 }
3734 else if (bufs[colorAttachment] >= maxColorAttachment)
3735 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003736 context->handleError(InvalidOperation()
3737 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003738 return false;
3739 }
3740 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3741 frameBufferId != 0)
3742 {
3743 // INVALID_OPERATION-GL is bound to buffer and ith argument
3744 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003745 context->handleError(InvalidOperation()
3746 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003747 return false;
3748 }
3749 }
3750
3751 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3752 // and n is not 1 or bufs is bound to value other than BACK and NONE
3753 if (frameBufferId == 0)
3754 {
3755 if (n != 1)
3756 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003757 context->handleError(InvalidOperation()
3758 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003759 return false;
3760 }
3761
3762 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3763 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003764 context->handleError(
3765 InvalidOperation()
3766 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003767 return false;
3768 }
3769 }
3770
3771 return true;
3772}
3773
Geoff Lang496c02d2016-10-20 11:38:11 -07003774bool ValidateGetBufferPointervBase(Context *context,
3775 GLenum target,
3776 GLenum pname,
3777 GLsizei *length,
3778 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003779{
Geoff Lang496c02d2016-10-20 11:38:11 -07003780 if (length)
3781 {
3782 *length = 0;
3783 }
3784
3785 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3786 {
3787 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003788 InvalidOperation()
3789 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003790 return false;
3791 }
3792
Olli Etuaho4f667482016-03-30 15:56:35 +03003793 if (!ValidBufferTarget(context, target))
3794 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003795 context->handleError(InvalidEnum() << "Buffer target not valid: 0x" << std::hex
3796 << std::uppercase << target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003797 return false;
3798 }
3799
Geoff Lang496c02d2016-10-20 11:38:11 -07003800 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003801 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003802 case GL_BUFFER_MAP_POINTER:
3803 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003804
Geoff Lang496c02d2016-10-20 11:38:11 -07003805 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003806 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003807 return false;
3808 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003809
3810 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3811 // target bound to zero generate an INVALID_OPERATION error."
3812 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003813 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003814 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003815 context->handleError(InvalidOperation()
3816 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003817 return false;
3818 }
3819
Geoff Lang496c02d2016-10-20 11:38:11 -07003820 if (length)
3821 {
3822 *length = 1;
3823 }
3824
Olli Etuaho4f667482016-03-30 15:56:35 +03003825 return true;
3826}
3827
3828bool ValidateUnmapBufferBase(Context *context, GLenum target)
3829{
3830 if (!ValidBufferTarget(context, target))
3831 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003832 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003833 return false;
3834 }
3835
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003836 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003837
3838 if (buffer == nullptr || !buffer->isMapped())
3839 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003840 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003841 return false;
3842 }
3843
3844 return true;
3845}
3846
3847bool ValidateMapBufferRangeBase(Context *context,
3848 GLenum target,
3849 GLintptr offset,
3850 GLsizeiptr length,
3851 GLbitfield access)
3852{
3853 if (!ValidBufferTarget(context, target))
3854 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003855 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003856 return false;
3857 }
3858
Brandon Jones6cad5662017-06-14 13:25:13 -07003859 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003860 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003861 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3862 return false;
3863 }
3864
3865 if (length < 0)
3866 {
3867 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003868 return false;
3869 }
3870
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003871 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003872
3873 if (!buffer)
3874 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003875 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003876 return false;
3877 }
3878
3879 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003880 CheckedNumeric<size_t> checkedOffset(offset);
3881 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003882
Jamie Madille2e406c2016-06-02 13:04:10 -04003883 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003884 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003885 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003886 return false;
3887 }
3888
3889 // Check for invalid bits in the mask
3890 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3891 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3892 GL_MAP_UNSYNCHRONIZED_BIT;
3893
3894 if (access & ~(allAccessBits))
3895 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003896 context->handleError(InvalidValue()
3897 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003898 return false;
3899 }
3900
3901 if (length == 0)
3902 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003903 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003904 return false;
3905 }
3906
3907 if (buffer->isMapped())
3908 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003909 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003910 return false;
3911 }
3912
3913 // Check for invalid bit combinations
3914 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3915 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003916 context->handleError(InvalidOperation()
3917 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003918 return false;
3919 }
3920
3921 GLbitfield writeOnlyBits =
3922 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3923
3924 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3925 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003926 context->handleError(InvalidOperation()
3927 << "Invalid access bits when mapping buffer for reading: 0x"
3928 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003929 return false;
3930 }
3931
3932 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3933 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003934 context->handleError(
3935 InvalidOperation()
3936 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003937 return false;
3938 }
3939 return true;
3940}
3941
3942bool ValidateFlushMappedBufferRangeBase(Context *context,
3943 GLenum target,
3944 GLintptr offset,
3945 GLsizeiptr length)
3946{
Brandon Jones6cad5662017-06-14 13:25:13 -07003947 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003948 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003949 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3950 return false;
3951 }
3952
3953 if (length < 0)
3954 {
3955 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003956 return false;
3957 }
3958
3959 if (!ValidBufferTarget(context, target))
3960 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003961 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003962 return false;
3963 }
3964
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003965 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003966
3967 if (buffer == nullptr)
3968 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003969 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003970 return false;
3971 }
3972
3973 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3974 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003975 context->handleError(InvalidOperation()
3976 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003977 return false;
3978 }
3979
3980 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003981 CheckedNumeric<size_t> checkedOffset(offset);
3982 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003983
Jamie Madille2e406c2016-06-02 13:04:10 -04003984 if (!checkedSize.IsValid() ||
3985 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003986 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003987 context->handleError(InvalidValue()
3988 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003989 return false;
3990 }
3991
3992 return true;
3993}
3994
Olli Etuaho41997e72016-03-10 13:38:39 +02003995bool ValidateGenOrDelete(Context *context, GLint n)
3996{
3997 if (n < 0)
3998 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003999 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02004000 return false;
4001 }
4002 return true;
4003}
4004
Geoff Langff5b2d52016-09-07 11:32:23 -04004005bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4006{
4007 if (!context->getExtensions().robustClientMemory)
4008 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004009 context->handleError(InvalidOperation()
4010 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004011 return false;
4012 }
4013
4014 if (bufSize < 0)
4015 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004016 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004017 return false;
4018 }
4019
4020 return true;
4021}
4022
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004023bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4024{
4025 if (bufSize < numParams)
4026 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004027 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4028 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004029 return false;
4030 }
4031
4032 return true;
4033}
4034
Jamie Madillbe849e42017-05-02 15:49:00 -04004035bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
4036 GLenum target,
4037 GLenum attachment,
4038 GLenum pname,
4039 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004040{
Geoff Langff5b2d52016-09-07 11:32:23 -04004041 if (!ValidFramebufferTarget(target))
4042 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004043 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004044 return false;
4045 }
4046
4047 int clientVersion = context->getClientMajorVersion();
4048
4049 switch (pname)
4050 {
4051 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4052 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4053 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4054 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4055 break;
4056
Martin Radeve5285d22017-07-14 16:23:53 +03004057 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4058 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4059 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4060 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4061 if (clientVersion < 3 || !context->getExtensions().multiview)
4062 {
4063 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4064 return false;
4065 }
4066 break;
4067
Geoff Langff5b2d52016-09-07 11:32:23 -04004068 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4069 if (clientVersion < 3 && !context->getExtensions().sRGB)
4070 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004071 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004072 return false;
4073 }
4074 break;
4075
4076 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4077 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4078 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4079 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4080 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4081 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4082 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4083 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4084 if (clientVersion < 3)
4085 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004086 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004087 return false;
4088 }
4089 break;
4090
4091 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004092 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004093 return false;
4094 }
4095
4096 // Determine if the attachment is a valid enum
4097 switch (attachment)
4098 {
4099 case GL_BACK:
4100 case GL_FRONT:
4101 case GL_DEPTH:
4102 case GL_STENCIL:
4103 case GL_DEPTH_STENCIL_ATTACHMENT:
4104 if (clientVersion < 3)
4105 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004106 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004107 return false;
4108 }
4109 break;
4110
4111 case GL_DEPTH_ATTACHMENT:
4112 case GL_STENCIL_ATTACHMENT:
4113 break;
4114
4115 default:
4116 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4117 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4118 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004119 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004120 return false;
4121 }
4122 break;
4123 }
4124
4125 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4126 ASSERT(framebuffer);
4127
4128 if (framebuffer->id() == 0)
4129 {
4130 if (clientVersion < 3)
4131 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004132 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004133 return false;
4134 }
4135
4136 switch (attachment)
4137 {
4138 case GL_BACK:
4139 case GL_DEPTH:
4140 case GL_STENCIL:
4141 break;
4142
4143 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004144 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FramebufferInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004145 return false;
4146 }
4147 }
4148 else
4149 {
4150 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4151 {
4152 // Valid attachment query
4153 }
4154 else
4155 {
4156 switch (attachment)
4157 {
4158 case GL_DEPTH_ATTACHMENT:
4159 case GL_STENCIL_ATTACHMENT:
4160 break;
4161
4162 case GL_DEPTH_STENCIL_ATTACHMENT:
4163 if (!framebuffer->hasValidDepthStencil())
4164 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004165 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004166 return false;
4167 }
4168 break;
4169
4170 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004171 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FramebufferInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004172 return false;
4173 }
4174 }
4175 }
4176
4177 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4178 if (attachmentObject)
4179 {
4180 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4181 attachmentObject->type() == GL_TEXTURE ||
4182 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4183
4184 switch (pname)
4185 {
4186 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4187 if (attachmentObject->type() != GL_RENDERBUFFER &&
4188 attachmentObject->type() != GL_TEXTURE)
4189 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004190 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004191 return false;
4192 }
4193 break;
4194
4195 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4196 if (attachmentObject->type() != GL_TEXTURE)
4197 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004198 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004199 return false;
4200 }
4201 break;
4202
4203 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4204 if (attachmentObject->type() != GL_TEXTURE)
4205 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004206 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004207 return false;
4208 }
4209 break;
4210
4211 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4212 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4213 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004214 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FramebufferInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004215 return false;
4216 }
4217 break;
4218
4219 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4220 if (attachmentObject->type() != GL_TEXTURE)
4221 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004222 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004223 return false;
4224 }
4225 break;
4226
4227 default:
4228 break;
4229 }
4230 }
4231 else
4232 {
4233 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4234 // is NONE, then querying any other pname will generate INVALID_ENUM.
4235
4236 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4237 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4238 // INVALID_OPERATION for all other pnames
4239
4240 switch (pname)
4241 {
4242 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4243 break;
4244
4245 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4246 if (clientVersion < 3)
4247 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004248 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
4249 InvalidRenderbufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004250 return false;
4251 }
4252 break;
4253
4254 default:
4255 if (clientVersion < 3)
4256 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004257 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
4258 InvalidRenderbufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004259 return false;
4260 }
4261 else
4262 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004263 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
4264 InvalidRenderbufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004265 return false;
4266 }
4267 }
4268 }
4269
Martin Radeve5285d22017-07-14 16:23:53 +03004270 if (numParams)
4271 {
4272 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4273 {
4274 // Only when the viewport offsets are queried we can have a varying number of output
4275 // parameters.
4276 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4277 *numParams = numViews * 2;
4278 }
4279 else
4280 {
4281 // For all other queries we can have only one output parameter.
4282 *numParams = 1;
4283 }
4284 }
4285
Geoff Langff5b2d52016-09-07 11:32:23 -04004286 return true;
4287}
4288
4289bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4290 GLenum target,
4291 GLenum attachment,
4292 GLenum pname,
4293 GLsizei bufSize,
4294 GLsizei *numParams)
4295{
4296 if (!ValidateRobustEntryPoint(context, bufSize))
4297 {
4298 return false;
4299 }
4300
Jamie Madillbe849e42017-05-02 15:49:00 -04004301 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4302 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004303 {
4304 return false;
4305 }
4306
4307 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4308 {
4309 return false;
4310 }
4311
4312 return true;
4313}
4314
Geoff Langff5b2d52016-09-07 11:32:23 -04004315bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4316 GLenum target,
4317 GLenum pname,
4318 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004319 GLsizei *length,
4320 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004321{
4322 if (!ValidateRobustEntryPoint(context, bufSize))
4323 {
4324 return false;
4325 }
4326
Geoff Langebebe1c2016-10-14 12:01:31 -04004327 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004328 {
4329 return false;
4330 }
4331
Geoff Langebebe1c2016-10-14 12:01:31 -04004332 if (!ValidateRobustBufferSize(context, bufSize, *length))
4333 {
4334 return false;
4335 }
4336
4337 return true;
4338}
4339
4340bool ValidateGetBufferParameteri64v(ValidationContext *context,
4341 GLenum target,
4342 GLenum pname,
4343 GLint64 *params)
4344{
4345 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4346}
4347
4348bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4349 GLenum target,
4350 GLenum pname,
4351 GLsizei bufSize,
4352 GLsizei *length,
4353 GLint64 *params)
4354{
4355 if (!ValidateRobustEntryPoint(context, bufSize))
4356 {
4357 return false;
4358 }
4359
4360 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4361 {
4362 return false;
4363 }
4364
4365 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004366 {
4367 return false;
4368 }
4369
4370 return true;
4371}
4372
Jamie Madillbe849e42017-05-02 15:49:00 -04004373bool ValidateGetProgramivBase(ValidationContext *context,
4374 GLuint program,
4375 GLenum pname,
4376 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004377{
4378 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004379 if (numParams)
4380 {
4381 *numParams = 1;
4382 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004383
4384 Program *programObject = GetValidProgram(context, program);
4385 if (!programObject)
4386 {
4387 return false;
4388 }
4389
4390 switch (pname)
4391 {
4392 case GL_DELETE_STATUS:
4393 case GL_LINK_STATUS:
4394 case GL_VALIDATE_STATUS:
4395 case GL_INFO_LOG_LENGTH:
4396 case GL_ATTACHED_SHADERS:
4397 case GL_ACTIVE_ATTRIBUTES:
4398 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4399 case GL_ACTIVE_UNIFORMS:
4400 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4401 break;
4402
4403 case GL_PROGRAM_BINARY_LENGTH:
4404 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4405 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004406 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4407 "requires GL_OES_get_program_binary or "
4408 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004409 return false;
4410 }
4411 break;
4412
4413 case GL_ACTIVE_UNIFORM_BLOCKS:
4414 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4415 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4416 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4417 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4418 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4419 if (context->getClientMajorVersion() < 3)
4420 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004421 context->handleError(InvalidEnum() << "Querying requires at least ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004422 return false;
4423 }
4424 break;
4425
Yunchao He61afff12017-03-14 15:34:03 +08004426 case GL_PROGRAM_SEPARABLE:
4427 if (context->getClientVersion() < Version(3, 1))
4428 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004429 context->handleError(InvalidEnum() << "Querying requires at least ES 3.1.");
Yunchao He61afff12017-03-14 15:34:03 +08004430 return false;
4431 }
4432 break;
4433
Geoff Langff5b2d52016-09-07 11:32:23 -04004434 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004435 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004436 return false;
4437 }
4438
4439 return true;
4440}
4441
4442bool ValidateGetProgramivRobustANGLE(Context *context,
4443 GLuint program,
4444 GLenum pname,
4445 GLsizei bufSize,
4446 GLsizei *numParams)
4447{
4448 if (!ValidateRobustEntryPoint(context, bufSize))
4449 {
4450 return false;
4451 }
4452
Jamie Madillbe849e42017-05-02 15:49:00 -04004453 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004454 {
4455 return false;
4456 }
4457
4458 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4459 {
4460 return false;
4461 }
4462
4463 return true;
4464}
4465
Geoff Lang740d9022016-10-07 11:20:52 -04004466bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4467 GLenum target,
4468 GLenum pname,
4469 GLsizei bufSize,
4470 GLsizei *length,
4471 GLint *params)
4472{
4473 if (!ValidateRobustEntryPoint(context, bufSize))
4474 {
4475 return false;
4476 }
4477
4478 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4479 {
4480 return false;
4481 }
4482
4483 if (!ValidateRobustBufferSize(context, bufSize, *length))
4484 {
4485 return false;
4486 }
4487
4488 return true;
4489}
4490
Geoff Langd7d0ed32016-10-07 11:33:51 -04004491bool ValidateGetShaderivRobustANGLE(Context *context,
4492 GLuint shader,
4493 GLenum pname,
4494 GLsizei bufSize,
4495 GLsizei *length,
4496 GLint *params)
4497{
4498 if (!ValidateRobustEntryPoint(context, bufSize))
4499 {
4500 return false;
4501 }
4502
4503 if (!ValidateGetShaderivBase(context, shader, pname, length))
4504 {
4505 return false;
4506 }
4507
4508 if (!ValidateRobustBufferSize(context, bufSize, *length))
4509 {
4510 return false;
4511 }
4512
4513 return true;
4514}
4515
Geoff Langc1984ed2016-10-07 12:41:00 -04004516bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4517 GLenum target,
4518 GLenum pname,
4519 GLsizei bufSize,
4520 GLsizei *length,
4521 GLfloat *params)
4522{
4523 if (!ValidateRobustEntryPoint(context, bufSize))
4524 {
4525 return false;
4526 }
4527
4528 if (!ValidateGetTexParameterBase(context, target, pname, length))
4529 {
4530 return false;
4531 }
4532
4533 if (!ValidateRobustBufferSize(context, bufSize, *length))
4534 {
4535 return false;
4536 }
4537
4538 return true;
4539}
4540
Geoff Langc1984ed2016-10-07 12:41:00 -04004541bool ValidateGetTexParameterivRobustANGLE(Context *context,
4542 GLenum target,
4543 GLenum pname,
4544 GLsizei bufSize,
4545 GLsizei *length,
4546 GLint *params)
4547{
4548 if (!ValidateRobustEntryPoint(context, bufSize))
4549 {
4550 return false;
4551 }
4552
4553 if (!ValidateGetTexParameterBase(context, target, pname, length))
4554 {
4555 return false;
4556 }
4557
4558 if (!ValidateRobustBufferSize(context, bufSize, *length))
4559 {
4560 return false;
4561 }
4562
4563 return true;
4564}
4565
Geoff Langc1984ed2016-10-07 12:41:00 -04004566bool ValidateTexParameterfvRobustANGLE(Context *context,
4567 GLenum target,
4568 GLenum pname,
4569 GLsizei bufSize,
4570 const GLfloat *params)
4571{
4572 if (!ValidateRobustEntryPoint(context, bufSize))
4573 {
4574 return false;
4575 }
4576
4577 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4578}
4579
Geoff Langc1984ed2016-10-07 12:41:00 -04004580bool ValidateTexParameterivRobustANGLE(Context *context,
4581 GLenum target,
4582 GLenum pname,
4583 GLsizei bufSize,
4584 const GLint *params)
4585{
4586 if (!ValidateRobustEntryPoint(context, bufSize))
4587 {
4588 return false;
4589 }
4590
4591 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4592}
4593
4594bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4595{
4596 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4597}
4598
4599bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4600 GLuint sampler,
4601 GLenum pname,
4602 GLuint bufSize,
4603 GLsizei *length,
4604 GLfloat *params)
4605{
4606 if (!ValidateRobustEntryPoint(context, bufSize))
4607 {
4608 return false;
4609 }
4610
4611 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4612 {
4613 return false;
4614 }
4615
4616 if (!ValidateRobustBufferSize(context, bufSize, *length))
4617 {
4618 return false;
4619 }
4620
4621 return true;
4622}
4623
4624bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4625{
4626 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4627}
4628
4629bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4630 GLuint sampler,
4631 GLenum pname,
4632 GLuint bufSize,
4633 GLsizei *length,
4634 GLint *params)
4635{
4636 if (!ValidateRobustEntryPoint(context, bufSize))
4637 {
4638 return false;
4639 }
4640
4641 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4642 {
4643 return false;
4644 }
4645
4646 if (!ValidateRobustBufferSize(context, bufSize, *length))
4647 {
4648 return false;
4649 }
4650
4651 return true;
4652}
4653
4654bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4655{
4656 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4657}
4658
4659bool ValidateSamplerParameterfv(Context *context,
4660 GLuint sampler,
4661 GLenum pname,
4662 const GLfloat *params)
4663{
4664 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4665}
4666
4667bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4668 GLuint sampler,
4669 GLenum pname,
4670 GLsizei bufSize,
4671 const GLfloat *params)
4672{
4673 if (!ValidateRobustEntryPoint(context, bufSize))
4674 {
4675 return false;
4676 }
4677
4678 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4679}
4680
4681bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4682{
4683 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4684}
4685
4686bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4687{
4688 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4689}
4690
4691bool ValidateSamplerParameterivRobustANGLE(Context *context,
4692 GLuint sampler,
4693 GLenum pname,
4694 GLsizei bufSize,
4695 const GLint *params)
4696{
4697 if (!ValidateRobustEntryPoint(context, bufSize))
4698 {
4699 return false;
4700 }
4701
4702 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4703}
4704
Geoff Lang0b031062016-10-13 14:30:04 -04004705bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4706 GLuint index,
4707 GLenum pname,
4708 GLsizei bufSize,
4709 GLsizei *length,
4710 GLfloat *params)
4711{
4712 if (!ValidateRobustEntryPoint(context, bufSize))
4713 {
4714 return false;
4715 }
4716
4717 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4718 {
4719 return false;
4720 }
4721
4722 if (!ValidateRobustBufferSize(context, bufSize, *length))
4723 {
4724 return false;
4725 }
4726
4727 return true;
4728}
4729
Geoff Lang0b031062016-10-13 14:30:04 -04004730bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4731 GLuint index,
4732 GLenum pname,
4733 GLsizei bufSize,
4734 GLsizei *length,
4735 GLint *params)
4736{
4737 if (!ValidateRobustEntryPoint(context, bufSize))
4738 {
4739 return false;
4740 }
4741
4742 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4743 {
4744 return false;
4745 }
4746
4747 if (!ValidateRobustBufferSize(context, bufSize, *length))
4748 {
4749 return false;
4750 }
4751
4752 return true;
4753}
4754
Geoff Lang0b031062016-10-13 14:30:04 -04004755bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4756 GLuint index,
4757 GLenum pname,
4758 GLsizei bufSize,
4759 GLsizei *length,
4760 void **pointer)
4761{
4762 if (!ValidateRobustEntryPoint(context, bufSize))
4763 {
4764 return false;
4765 }
4766
4767 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4768 {
4769 return false;
4770 }
4771
4772 if (!ValidateRobustBufferSize(context, bufSize, *length))
4773 {
4774 return false;
4775 }
4776
4777 return true;
4778}
4779
4780bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
4781{
4782 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4783}
4784
4785bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4786 GLuint index,
4787 GLenum pname,
4788 GLsizei bufSize,
4789 GLsizei *length,
4790 GLint *params)
4791{
4792 if (!ValidateRobustEntryPoint(context, bufSize))
4793 {
4794 return false;
4795 }
4796
4797 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4798 {
4799 return false;
4800 }
4801
4802 if (!ValidateRobustBufferSize(context, bufSize, *length))
4803 {
4804 return false;
4805 }
4806
4807 return true;
4808}
4809
4810bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
4811{
4812 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4813}
4814
4815bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4816 GLuint index,
4817 GLenum pname,
4818 GLsizei bufSize,
4819 GLsizei *length,
4820 GLuint *params)
4821{
4822 if (!ValidateRobustEntryPoint(context, bufSize))
4823 {
4824 return false;
4825 }
4826
4827 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4828 {
4829 return false;
4830 }
4831
4832 if (!ValidateRobustBufferSize(context, bufSize, *length))
4833 {
4834 return false;
4835 }
4836
4837 return true;
4838}
4839
Geoff Lang6899b872016-10-14 11:30:13 -04004840bool ValidateGetActiveUniformBlockiv(Context *context,
4841 GLuint program,
4842 GLuint uniformBlockIndex,
4843 GLenum pname,
4844 GLint *params)
4845{
4846 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
4847}
4848
4849bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4850 GLuint program,
4851 GLuint uniformBlockIndex,
4852 GLenum pname,
4853 GLsizei bufSize,
4854 GLsizei *length,
4855 GLint *params)
4856{
4857 if (!ValidateRobustEntryPoint(context, bufSize))
4858 {
4859 return false;
4860 }
4861
4862 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4863 {
4864 return false;
4865 }
4866
4867 if (!ValidateRobustBufferSize(context, bufSize, *length))
4868 {
4869 return false;
4870 }
4871
4872 return true;
4873}
4874
Geoff Lang0a9661f2016-10-20 10:59:20 -07004875bool ValidateGetInternalFormativ(Context *context,
4876 GLenum target,
4877 GLenum internalformat,
4878 GLenum pname,
4879 GLsizei bufSize,
4880 GLint *params)
4881{
4882 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4883 nullptr);
4884}
4885
4886bool ValidateGetInternalFormativRobustANGLE(Context *context,
4887 GLenum target,
4888 GLenum internalformat,
4889 GLenum pname,
4890 GLsizei bufSize,
4891 GLsizei *length,
4892 GLint *params)
4893{
4894 if (!ValidateRobustEntryPoint(context, bufSize))
4895 {
4896 return false;
4897 }
4898
4899 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4900 {
4901 return false;
4902 }
4903
4904 if (!ValidateRobustBufferSize(context, bufSize, *length))
4905 {
4906 return false;
4907 }
4908
4909 return true;
4910}
4911
Shao80957d92017-02-20 21:25:59 +08004912bool ValidateVertexFormatBase(ValidationContext *context,
4913 GLuint attribIndex,
4914 GLint size,
4915 GLenum type,
4916 GLboolean pureInteger)
4917{
4918 const Caps &caps = context->getCaps();
4919 if (attribIndex >= caps.maxVertexAttributes)
4920 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004921 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Shao80957d92017-02-20 21:25:59 +08004922 return false;
4923 }
4924
4925 if (size < 1 || size > 4)
4926 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004927 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004928 return false;
Shao80957d92017-02-20 21:25:59 +08004929 }
4930
4931 switch (type)
4932 {
4933 case GL_BYTE:
4934 case GL_UNSIGNED_BYTE:
4935 case GL_SHORT:
4936 case GL_UNSIGNED_SHORT:
4937 break;
4938
4939 case GL_INT:
4940 case GL_UNSIGNED_INT:
4941 if (context->getClientMajorVersion() < 3)
4942 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004943 context->handleError(InvalidEnum()
4944 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004945 return false;
4946 }
4947 break;
4948
4949 case GL_FIXED:
4950 case GL_FLOAT:
4951 if (pureInteger)
4952 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004953 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004954 return false;
4955 }
4956 break;
4957
4958 case GL_HALF_FLOAT:
4959 if (context->getClientMajorVersion() < 3)
4960 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004961 context->handleError(InvalidEnum()
4962 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004963 return false;
4964 }
4965 if (pureInteger)
4966 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004967 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004968 return false;
4969 }
4970 break;
4971
4972 case GL_INT_2_10_10_10_REV:
4973 case GL_UNSIGNED_INT_2_10_10_10_REV:
4974 if (context->getClientMajorVersion() < 3)
4975 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004976 context->handleError(InvalidEnum()
4977 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004978 return false;
4979 }
4980 if (pureInteger)
4981 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004982 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004983 return false;
4984 }
4985 if (size != 4)
4986 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004987 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4988 "UNSIGNED_INT_2_10_10_10_REV and "
4989 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004990 return false;
4991 }
4992 break;
4993
4994 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004995 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004996 return false;
4997 }
4998
4999 return true;
5000}
5001
Geoff Lang76e65652017-03-27 14:58:02 -04005002// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5003// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5004// specified clear value and the type of a buffer that is being cleared generates an
5005// INVALID_OPERATION error instead of producing undefined results
5006bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
5007 GLint drawbuffer,
5008 const GLenum *validComponentTypes,
5009 size_t validComponentTypeCount)
5010{
5011 const FramebufferAttachment *attachment =
5012 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5013 if (attachment)
5014 {
5015 GLenum componentType = attachment->getFormat().info->componentType;
5016 const GLenum *end = validComponentTypes + validComponentTypeCount;
5017 if (std::find(validComponentTypes, end, componentType) == end)
5018 {
5019 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005020 InvalidOperation()
5021 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005022 return false;
5023 }
5024 }
5025
5026 return true;
5027}
5028
Corentin Wallezb2931602017-04-11 15:58:57 -04005029bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
5030 GLsizei imageSize,
5031 GLsizei dataSize)
5032{
5033 if (!ValidateRobustEntryPoint(context, dataSize))
5034 {
5035 return false;
5036 }
5037
5038 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
5039 if (pixelUnpackBuffer == nullptr)
5040 {
5041 if (dataSize < imageSize)
5042 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005043 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005044 }
5045 }
5046 return true;
5047}
5048
Jamie Madillbe849e42017-05-02 15:49:00 -04005049bool ValidateGetBufferParameterBase(ValidationContext *context,
5050 GLenum target,
5051 GLenum pname,
5052 bool pointerVersion,
5053 GLsizei *numParams)
5054{
5055 if (numParams)
5056 {
5057 *numParams = 0;
5058 }
5059
5060 if (!ValidBufferTarget(context, target))
5061 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005062 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005063 return false;
5064 }
5065
5066 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5067 if (!buffer)
5068 {
5069 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005070 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005071 return false;
5072 }
5073
5074 const Extensions &extensions = context->getExtensions();
5075
5076 switch (pname)
5077 {
5078 case GL_BUFFER_USAGE:
5079 case GL_BUFFER_SIZE:
5080 break;
5081
5082 case GL_BUFFER_ACCESS_OES:
5083 if (!extensions.mapBuffer)
5084 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005085 context->handleError(InvalidEnum()
5086 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005087 return false;
5088 }
5089 break;
5090
5091 case GL_BUFFER_MAPPED:
5092 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5093 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5094 !extensions.mapBufferRange)
5095 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005096 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5097 "GL_OES_mapbuffer or "
5098 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005099 return false;
5100 }
5101 break;
5102
5103 case GL_BUFFER_MAP_POINTER:
5104 if (!pointerVersion)
5105 {
5106 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005107 InvalidEnum()
5108 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005109 return false;
5110 }
5111 break;
5112
5113 case GL_BUFFER_ACCESS_FLAGS:
5114 case GL_BUFFER_MAP_OFFSET:
5115 case GL_BUFFER_MAP_LENGTH:
5116 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5117 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005118 context->handleError(InvalidEnum()
5119 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005120 return false;
5121 }
5122 break;
5123
5124 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005125 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005126 return false;
5127 }
5128
5129 // All buffer parameter queries return one value.
5130 if (numParams)
5131 {
5132 *numParams = 1;
5133 }
5134
5135 return true;
5136}
5137
5138bool ValidateGetRenderbufferParameterivBase(Context *context,
5139 GLenum target,
5140 GLenum pname,
5141 GLsizei *length)
5142{
5143 if (length)
5144 {
5145 *length = 0;
5146 }
5147
5148 if (target != GL_RENDERBUFFER)
5149 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005150 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005151 return false;
5152 }
5153
5154 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5155 if (renderbuffer == nullptr)
5156 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005157 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005158 return false;
5159 }
5160
5161 switch (pname)
5162 {
5163 case GL_RENDERBUFFER_WIDTH:
5164 case GL_RENDERBUFFER_HEIGHT:
5165 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5166 case GL_RENDERBUFFER_RED_SIZE:
5167 case GL_RENDERBUFFER_GREEN_SIZE:
5168 case GL_RENDERBUFFER_BLUE_SIZE:
5169 case GL_RENDERBUFFER_ALPHA_SIZE:
5170 case GL_RENDERBUFFER_DEPTH_SIZE:
5171 case GL_RENDERBUFFER_STENCIL_SIZE:
5172 break;
5173
5174 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5175 if (!context->getExtensions().framebufferMultisample)
5176 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005177 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005178 return false;
5179 }
5180 break;
5181
5182 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005183 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005184 return false;
5185 }
5186
5187 if (length)
5188 {
5189 *length = 1;
5190 }
5191 return true;
5192}
5193
5194bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5195{
5196 if (length)
5197 {
5198 *length = 0;
5199 }
5200
5201 if (GetValidShader(context, shader) == nullptr)
5202 {
5203 return false;
5204 }
5205
5206 switch (pname)
5207 {
5208 case GL_SHADER_TYPE:
5209 case GL_DELETE_STATUS:
5210 case GL_COMPILE_STATUS:
5211 case GL_INFO_LOG_LENGTH:
5212 case GL_SHADER_SOURCE_LENGTH:
5213 break;
5214
5215 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5216 if (!context->getExtensions().translatedShaderSource)
5217 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005218 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005219 return false;
5220 }
5221 break;
5222
5223 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005224 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005225 return false;
5226 }
5227
5228 if (length)
5229 {
5230 *length = 1;
5231 }
5232 return true;
5233}
5234
5235bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
5236{
5237 if (length)
5238 {
5239 *length = 0;
5240 }
5241
5242 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5243 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005244 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005245 return false;
5246 }
5247
5248 if (context->getTargetTexture(target) == nullptr)
5249 {
5250 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005251 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005252 return false;
5253 }
5254
5255 switch (pname)
5256 {
5257 case GL_TEXTURE_MAG_FILTER:
5258 case GL_TEXTURE_MIN_FILTER:
5259 case GL_TEXTURE_WRAP_S:
5260 case GL_TEXTURE_WRAP_T:
5261 break;
5262
5263 case GL_TEXTURE_USAGE_ANGLE:
5264 if (!context->getExtensions().textureUsage)
5265 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005266 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005267 return false;
5268 }
5269 break;
5270
5271 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5272 if (!context->getExtensions().textureFilterAnisotropic)
5273 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005274 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005275 return false;
5276 }
5277 break;
5278
5279 case GL_TEXTURE_IMMUTABLE_FORMAT:
5280 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5281 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005282 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005283 return false;
5284 }
5285 break;
5286
5287 case GL_TEXTURE_WRAP_R:
5288 case GL_TEXTURE_IMMUTABLE_LEVELS:
5289 case GL_TEXTURE_SWIZZLE_R:
5290 case GL_TEXTURE_SWIZZLE_G:
5291 case GL_TEXTURE_SWIZZLE_B:
5292 case GL_TEXTURE_SWIZZLE_A:
5293 case GL_TEXTURE_BASE_LEVEL:
5294 case GL_TEXTURE_MAX_LEVEL:
5295 case GL_TEXTURE_MIN_LOD:
5296 case GL_TEXTURE_MAX_LOD:
5297 case GL_TEXTURE_COMPARE_MODE:
5298 case GL_TEXTURE_COMPARE_FUNC:
5299 if (context->getClientMajorVersion() < 3)
5300 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005301 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005302 return false;
5303 }
5304 break;
5305
5306 case GL_TEXTURE_SRGB_DECODE_EXT:
5307 if (!context->getExtensions().textureSRGBDecode)
5308 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005309 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005310 return false;
5311 }
5312 break;
5313
5314 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005315 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005316 return false;
5317 }
5318
5319 if (length)
5320 {
5321 *length = 1;
5322 }
5323 return true;
5324}
5325
5326bool ValidateGetVertexAttribBase(Context *context,
5327 GLuint index,
5328 GLenum pname,
5329 GLsizei *length,
5330 bool pointer,
5331 bool pureIntegerEntryPoint)
5332{
5333 if (length)
5334 {
5335 *length = 0;
5336 }
5337
5338 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5339 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005340 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005341 return false;
5342 }
5343
5344 if (index >= context->getCaps().maxVertexAttributes)
5345 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005346 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Jamie Madillbe849e42017-05-02 15:49:00 -04005347 return false;
5348 }
5349
5350 if (pointer)
5351 {
5352 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5353 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005354 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005355 return false;
5356 }
5357 }
5358 else
5359 {
5360 switch (pname)
5361 {
5362 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5363 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5364 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5365 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5366 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5367 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5368 case GL_CURRENT_VERTEX_ATTRIB:
5369 break;
5370
5371 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5372 static_assert(
5373 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5374 "ANGLE extension enums not equal to GL enums.");
5375 if (context->getClientMajorVersion() < 3 &&
5376 !context->getExtensions().instancedArrays)
5377 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005378 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5379 "requires OpenGL ES 3.0 or "
5380 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005381 return false;
5382 }
5383 break;
5384
5385 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5386 if (context->getClientMajorVersion() < 3)
5387 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005388 context->handleError(
5389 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005390 return false;
5391 }
5392 break;
5393
5394 case GL_VERTEX_ATTRIB_BINDING:
5395 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5396 if (context->getClientVersion() < ES_3_1)
5397 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005398 context->handleError(InvalidEnum()
5399 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005400 return false;
5401 }
5402 break;
5403
5404 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005405 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005406 return false;
5407 }
5408 }
5409
5410 if (length)
5411 {
5412 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5413 {
5414 *length = 4;
5415 }
5416 else
5417 {
5418 *length = 1;
5419 }
5420 }
5421
5422 return true;
5423}
5424
Jamie Madill4928b7c2017-06-20 12:57:39 -04005425bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005426 GLint x,
5427 GLint y,
5428 GLsizei width,
5429 GLsizei height,
5430 GLenum format,
5431 GLenum type,
5432 GLsizei bufSize,
5433 GLsizei *length,
5434 GLsizei *columns,
5435 GLsizei *rows,
5436 void *pixels)
5437{
5438 if (length != nullptr)
5439 {
5440 *length = 0;
5441 }
5442 if (rows != nullptr)
5443 {
5444 *rows = 0;
5445 }
5446 if (columns != nullptr)
5447 {
5448 *columns = 0;
5449 }
5450
5451 if (width < 0 || height < 0)
5452 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005453 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005454 return false;
5455 }
5456
5457 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5458
5459 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5460 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005461 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005462 return false;
5463 }
5464
5465 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5466 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005467 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005468 return false;
5469 }
5470
5471 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5472 ASSERT(framebuffer);
5473
5474 if (framebuffer->getReadBufferState() == GL_NONE)
5475 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005476 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Jamie Madillbe849e42017-05-02 15:49:00 -04005477 return false;
5478 }
5479
5480 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5481 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5482 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5483 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5484 // situation is an application error that would lead to a crash in ANGLE.
5485 if (readBuffer == nullptr)
5486 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005487 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005488 return false;
5489 }
5490
Martin Radev28031682017-07-28 14:47:56 +03005491 // ANGLE_multiview, Revision 1:
5492 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5493 // current read framebuffer is not NONE.
5494 if (readBuffer->getMultiviewLayout() != GL_NONE)
5495 {
5496 context->handleError(InvalidFramebufferOperation()
5497 << "Attempting to read from a multi-view framebuffer.");
5498 return false;
5499 }
5500
Geoff Lang280ba992017-04-18 16:30:58 -04005501 if (context->getExtensions().webglCompatibility)
5502 {
5503 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5504 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5505 // and type before validating the combination of format and type. However, the
5506 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5507 // verifies that GL_INVALID_OPERATION is generated.
5508 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5509 // dEQP/WebGL.
5510 if (!ValidReadPixelsFormatEnum(context, format))
5511 {
5512 context->handleError(InvalidEnum() << "Invalid read format.");
5513 return false;
5514 }
5515
5516 if (!ValidReadPixelsTypeEnum(context, type))
5517 {
5518 context->handleError(InvalidEnum() << "Invalid read type.");
5519 return false;
5520 }
5521 }
5522
Jamie Madill4928b7c2017-06-20 12:57:39 -04005523 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5524 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005525 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5526
5527 bool validFormatTypeCombination =
5528 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5529
5530 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5531 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005532 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005533 return false;
5534 }
5535
5536 // Check for pixel pack buffer related API errors
5537 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5538 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5539 {
5540 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005541 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005542 return false;
5543 }
5544
5545 // .. the data would be packed to the buffer object such that the memory writes required
5546 // would exceed the data store size.
5547 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5548 const gl::Extents size(width, height, 1);
5549 const auto &pack = context->getGLState().getPackState();
5550
5551 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5552 if (endByteOrErr.isError())
5553 {
5554 context->handleError(endByteOrErr.getError());
5555 return false;
5556 }
5557
5558 size_t endByte = endByteOrErr.getResult();
5559 if (bufSize >= 0)
5560 {
5561 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5562 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005563 context->handleError(InvalidOperation()
5564 << "bufSize must be at least " << endByte << " bytes.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005565 return false;
5566 }
5567 }
5568
5569 if (pixelPackBuffer != nullptr)
5570 {
5571 CheckedNumeric<size_t> checkedEndByte(endByte);
5572 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5573 checkedEndByte += checkedOffset;
5574
5575 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5576 {
5577 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005578 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005579 return false;
5580 }
5581 }
5582
5583 if (pixelPackBuffer == nullptr && length != nullptr)
5584 {
5585 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5586 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005587 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005588 return false;
5589 }
5590
5591 *length = static_cast<GLsizei>(endByte);
5592 }
5593
5594 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5595 angle::CheckedNumeric<int> clippedExtent(length);
5596 if (start < 0)
5597 {
5598 // "subtract" the area that is less than 0
5599 clippedExtent += start;
5600 }
5601
5602 const int readExtent = start + length;
5603 if (readExtent > bufferSize)
5604 {
5605 // Subtract the region to the right of the read buffer
5606 clippedExtent -= (readExtent - bufferSize);
5607 }
5608
5609 if (!clippedExtent.IsValid())
5610 {
5611 return 0;
5612 }
5613
5614 return std::max(clippedExtent.ValueOrDie(), 0);
5615 };
5616
5617 if (columns != nullptr)
5618 {
5619 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5620 }
5621
5622 if (rows != nullptr)
5623 {
5624 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5625 }
5626
5627 return true;
5628}
5629
5630template <typename ParamType>
5631bool ValidateTexParameterBase(Context *context,
5632 GLenum target,
5633 GLenum pname,
5634 GLsizei bufSize,
5635 const ParamType *params)
5636{
5637 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5638 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005639 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005640 return false;
5641 }
5642
5643 if (context->getTargetTexture(target) == nullptr)
5644 {
5645 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005646 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005647 return false;
5648 }
5649
5650 const GLsizei minBufSize = 1;
5651 if (bufSize >= 0 && bufSize < minBufSize)
5652 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005653 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005654 return false;
5655 }
5656
5657 switch (pname)
5658 {
5659 case GL_TEXTURE_WRAP_R:
5660 case GL_TEXTURE_SWIZZLE_R:
5661 case GL_TEXTURE_SWIZZLE_G:
5662 case GL_TEXTURE_SWIZZLE_B:
5663 case GL_TEXTURE_SWIZZLE_A:
5664 case GL_TEXTURE_BASE_LEVEL:
5665 case GL_TEXTURE_MAX_LEVEL:
5666 case GL_TEXTURE_COMPARE_MODE:
5667 case GL_TEXTURE_COMPARE_FUNC:
5668 case GL_TEXTURE_MIN_LOD:
5669 case GL_TEXTURE_MAX_LOD:
5670 if (context->getClientMajorVersion() < 3)
5671 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005672 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005673 return false;
5674 }
5675 if (target == GL_TEXTURE_EXTERNAL_OES &&
5676 !context->getExtensions().eglImageExternalEssl3)
5677 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005678 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5679 "available without "
5680 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005681 return false;
5682 }
5683 break;
5684
5685 default:
5686 break;
5687 }
5688
JiangYizhou4cff8d62017-07-06 14:54:09 +08005689 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5690 {
5691 switch (pname)
5692 {
5693 case GL_TEXTURE_MIN_FILTER:
5694 case GL_TEXTURE_MAG_FILTER:
5695 case GL_TEXTURE_WRAP_S:
5696 case GL_TEXTURE_WRAP_T:
5697 case GL_TEXTURE_WRAP_R:
5698 case GL_TEXTURE_MIN_LOD:
5699 case GL_TEXTURE_MAX_LOD:
5700 case GL_TEXTURE_COMPARE_MODE:
5701 case GL_TEXTURE_COMPARE_FUNC:
5702 context->handleError(InvalidEnum()
5703 << "Invalid parameter for 2D multisampled textures.");
5704 return false;
5705 }
5706 }
5707
Jamie Madillbe849e42017-05-02 15:49:00 -04005708 switch (pname)
5709 {
5710 case GL_TEXTURE_WRAP_S:
5711 case GL_TEXTURE_WRAP_T:
5712 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005713 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005714 bool restrictedWrapModes =
5715 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5716 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5717 {
5718 return false;
5719 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005720 }
5721 break;
5722
5723 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005724 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005725 bool restrictedMinFilter =
5726 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5727 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5728 {
5729 return false;
5730 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005731 }
5732 break;
5733
5734 case GL_TEXTURE_MAG_FILTER:
5735 if (!ValidateTextureMagFilterValue(context, params))
5736 {
5737 return false;
5738 }
5739 break;
5740
5741 case GL_TEXTURE_USAGE_ANGLE:
5742 switch (ConvertToGLenum(params[0]))
5743 {
5744 case GL_NONE:
5745 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5746 break;
5747
5748 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005749 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005750 return false;
5751 }
5752 break;
5753
5754 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5755 if (!context->getExtensions().textureFilterAnisotropic)
5756 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005757 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005758 return false;
5759 }
5760
5761 // we assume the parameter passed to this validation method is truncated, not rounded
5762 if (params[0] < 1)
5763 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005764 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005765 return false;
5766 }
5767 break;
5768
5769 case GL_TEXTURE_MIN_LOD:
5770 case GL_TEXTURE_MAX_LOD:
5771 // any value is permissible
5772 break;
5773
5774 case GL_TEXTURE_COMPARE_MODE:
5775 if (!ValidateTextureCompareModeValue(context, params))
5776 {
5777 return false;
5778 }
5779 break;
5780
5781 case GL_TEXTURE_COMPARE_FUNC:
5782 if (!ValidateTextureCompareFuncValue(context, params))
5783 {
5784 return false;
5785 }
5786 break;
5787
5788 case GL_TEXTURE_SWIZZLE_R:
5789 case GL_TEXTURE_SWIZZLE_G:
5790 case GL_TEXTURE_SWIZZLE_B:
5791 case GL_TEXTURE_SWIZZLE_A:
5792 switch (ConvertToGLenum(params[0]))
5793 {
5794 case GL_RED:
5795 case GL_GREEN:
5796 case GL_BLUE:
5797 case GL_ALPHA:
5798 case GL_ZERO:
5799 case GL_ONE:
5800 break;
5801
5802 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005803 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005804 return false;
5805 }
5806 break;
5807
5808 case GL_TEXTURE_BASE_LEVEL:
5809 if (params[0] < 0)
5810 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005811 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005812 return false;
5813 }
5814 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5815 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005816 context->handleError(InvalidOperation()
5817 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005818 return false;
5819 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005820 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5821 {
5822 context->handleError(InvalidOperation()
5823 << "Base level must be 0 for multisampled textures.");
5824 return false;
5825 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005826 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5827 {
5828 context->handleError(InvalidOperation()
5829 << "Base level must be 0 for rectangle textures.");
5830 return false;
5831 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005832 break;
5833
5834 case GL_TEXTURE_MAX_LEVEL:
5835 if (params[0] < 0)
5836 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005837 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005838 return false;
5839 }
5840 break;
5841
5842 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5843 if (context->getClientVersion() < Version(3, 1))
5844 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005845 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005846 return false;
5847 }
5848 switch (ConvertToGLenum(params[0]))
5849 {
5850 case GL_DEPTH_COMPONENT:
5851 case GL_STENCIL_INDEX:
5852 break;
5853
5854 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005855 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005856 return false;
5857 }
5858 break;
5859
5860 case GL_TEXTURE_SRGB_DECODE_EXT:
5861 if (!ValidateTextureSRGBDecodeValue(context, params))
5862 {
5863 return false;
5864 }
5865 break;
5866
5867 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005868 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005869 return false;
5870 }
5871
5872 return true;
5873}
5874
5875template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5876template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5877
Jamie Madillc29968b2016-01-20 11:17:23 -05005878} // namespace gl