blob: f0432d86bef91770a0f37a8be86c5e32600e2f5c [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 }
Geoff Lang79f71042017-08-14 16:43:43 -04003939
3940 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003941}
3942
3943bool ValidateFlushMappedBufferRangeBase(Context *context,
3944 GLenum target,
3945 GLintptr offset,
3946 GLsizeiptr length)
3947{
Brandon Jones6cad5662017-06-14 13:25:13 -07003948 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003949 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003950 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3951 return false;
3952 }
3953
3954 if (length < 0)
3955 {
3956 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003957 return false;
3958 }
3959
3960 if (!ValidBufferTarget(context, target))
3961 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003962 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003963 return false;
3964 }
3965
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003966 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003967
3968 if (buffer == nullptr)
3969 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003970 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003971 return false;
3972 }
3973
3974 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3975 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003976 context->handleError(InvalidOperation()
3977 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003978 return false;
3979 }
3980
3981 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003982 CheckedNumeric<size_t> checkedOffset(offset);
3983 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003984
Jamie Madille2e406c2016-06-02 13:04:10 -04003985 if (!checkedSize.IsValid() ||
3986 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003987 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003988 context->handleError(InvalidValue()
3989 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003990 return false;
3991 }
3992
3993 return true;
3994}
3995
Olli Etuaho41997e72016-03-10 13:38:39 +02003996bool ValidateGenOrDelete(Context *context, GLint n)
3997{
3998 if (n < 0)
3999 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004000 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02004001 return false;
4002 }
4003 return true;
4004}
4005
Geoff Langff5b2d52016-09-07 11:32:23 -04004006bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
4007{
4008 if (!context->getExtensions().robustClientMemory)
4009 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004010 context->handleError(InvalidOperation()
4011 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004012 return false;
4013 }
4014
4015 if (bufSize < 0)
4016 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004017 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04004018 return false;
4019 }
4020
4021 return true;
4022}
4023
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004024bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
4025{
4026 if (bufSize < numParams)
4027 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004028 context->handleError(InvalidOperation() << numParams << " parameters are required but "
4029 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04004030 return false;
4031 }
4032
4033 return true;
4034}
4035
Jamie Madillbe849e42017-05-02 15:49:00 -04004036bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
4037 GLenum target,
4038 GLenum attachment,
4039 GLenum pname,
4040 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004041{
Geoff Langff5b2d52016-09-07 11:32:23 -04004042 if (!ValidFramebufferTarget(target))
4043 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004044 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004045 return false;
4046 }
4047
4048 int clientVersion = context->getClientMajorVersion();
4049
4050 switch (pname)
4051 {
4052 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4053 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4054 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4055 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4056 break;
4057
Martin Radeve5285d22017-07-14 16:23:53 +03004058 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
4059 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
4060 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
4061 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
4062 if (clientVersion < 3 || !context->getExtensions().multiview)
4063 {
4064 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
4065 return false;
4066 }
4067 break;
4068
Geoff Langff5b2d52016-09-07 11:32:23 -04004069 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
4070 if (clientVersion < 3 && !context->getExtensions().sRGB)
4071 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004072 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004073 return false;
4074 }
4075 break;
4076
4077 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
4078 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
4079 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
4080 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
4081 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
4082 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
4083 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4084 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4085 if (clientVersion < 3)
4086 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004087 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004088 return false;
4089 }
4090 break;
4091
4092 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004093 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004094 return false;
4095 }
4096
4097 // Determine if the attachment is a valid enum
4098 switch (attachment)
4099 {
4100 case GL_BACK:
4101 case GL_FRONT:
4102 case GL_DEPTH:
4103 case GL_STENCIL:
4104 case GL_DEPTH_STENCIL_ATTACHMENT:
4105 if (clientVersion < 3)
4106 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004107 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004108 return false;
4109 }
4110 break;
4111
4112 case GL_DEPTH_ATTACHMENT:
4113 case GL_STENCIL_ATTACHMENT:
4114 break;
4115
4116 default:
4117 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
4118 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
4119 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004120 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04004121 return false;
4122 }
4123 break;
4124 }
4125
4126 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
4127 ASSERT(framebuffer);
4128
4129 if (framebuffer->id() == 0)
4130 {
4131 if (clientVersion < 3)
4132 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004133 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04004134 return false;
4135 }
4136
4137 switch (attachment)
4138 {
4139 case GL_BACK:
4140 case GL_DEPTH:
4141 case GL_STENCIL:
4142 break;
4143
4144 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004145 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FramebufferInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004146 return false;
4147 }
4148 }
4149 else
4150 {
4151 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
4152 {
4153 // Valid attachment query
4154 }
4155 else
4156 {
4157 switch (attachment)
4158 {
4159 case GL_DEPTH_ATTACHMENT:
4160 case GL_STENCIL_ATTACHMENT:
4161 break;
4162
4163 case GL_DEPTH_STENCIL_ATTACHMENT:
4164 if (!framebuffer->hasValidDepthStencil())
4165 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004166 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04004167 return false;
4168 }
4169 break;
4170
4171 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004172 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FramebufferInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004173 return false;
4174 }
4175 }
4176 }
4177
4178 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
4179 if (attachmentObject)
4180 {
4181 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
4182 attachmentObject->type() == GL_TEXTURE ||
4183 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
4184
4185 switch (pname)
4186 {
4187 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4188 if (attachmentObject->type() != GL_RENDERBUFFER &&
4189 attachmentObject->type() != GL_TEXTURE)
4190 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004191 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004192 return false;
4193 }
4194 break;
4195
4196 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
4197 if (attachmentObject->type() != GL_TEXTURE)
4198 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004199 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004200 return false;
4201 }
4202 break;
4203
4204 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
4205 if (attachmentObject->type() != GL_TEXTURE)
4206 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004207 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004208 return false;
4209 }
4210 break;
4211
4212 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
4213 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
4214 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004215 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FramebufferInvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004216 return false;
4217 }
4218 break;
4219
4220 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
4221 if (attachmentObject->type() != GL_TEXTURE)
4222 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004223 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04004224 return false;
4225 }
4226 break;
4227
4228 default:
4229 break;
4230 }
4231 }
4232 else
4233 {
4234 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4235 // is NONE, then querying any other pname will generate INVALID_ENUM.
4236
4237 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4238 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4239 // INVALID_OPERATION for all other pnames
4240
4241 switch (pname)
4242 {
4243 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4244 break;
4245
4246 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4247 if (clientVersion < 3)
4248 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004249 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
4250 InvalidRenderbufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004251 return false;
4252 }
4253 break;
4254
4255 default:
4256 if (clientVersion < 3)
4257 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004258 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
4259 InvalidRenderbufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004260 return false;
4261 }
4262 else
4263 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004264 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
4265 InvalidRenderbufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004266 return false;
4267 }
4268 }
4269 }
4270
Martin Radeve5285d22017-07-14 16:23:53 +03004271 if (numParams)
4272 {
4273 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4274 {
4275 // Only when the viewport offsets are queried we can have a varying number of output
4276 // parameters.
4277 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4278 *numParams = numViews * 2;
4279 }
4280 else
4281 {
4282 // For all other queries we can have only one output parameter.
4283 *numParams = 1;
4284 }
4285 }
4286
Geoff Langff5b2d52016-09-07 11:32:23 -04004287 return true;
4288}
4289
4290bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4291 GLenum target,
4292 GLenum attachment,
4293 GLenum pname,
4294 GLsizei bufSize,
4295 GLsizei *numParams)
4296{
4297 if (!ValidateRobustEntryPoint(context, bufSize))
4298 {
4299 return false;
4300 }
4301
Jamie Madillbe849e42017-05-02 15:49:00 -04004302 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4303 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004304 {
4305 return false;
4306 }
4307
4308 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4309 {
4310 return false;
4311 }
4312
4313 return true;
4314}
4315
Geoff Langff5b2d52016-09-07 11:32:23 -04004316bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4317 GLenum target,
4318 GLenum pname,
4319 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004320 GLsizei *length,
4321 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004322{
4323 if (!ValidateRobustEntryPoint(context, bufSize))
4324 {
4325 return false;
4326 }
4327
Geoff Langebebe1c2016-10-14 12:01:31 -04004328 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004329 {
4330 return false;
4331 }
4332
Geoff Langebebe1c2016-10-14 12:01:31 -04004333 if (!ValidateRobustBufferSize(context, bufSize, *length))
4334 {
4335 return false;
4336 }
4337
4338 return true;
4339}
4340
4341bool ValidateGetBufferParameteri64v(ValidationContext *context,
4342 GLenum target,
4343 GLenum pname,
4344 GLint64 *params)
4345{
4346 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4347}
4348
4349bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4350 GLenum target,
4351 GLenum pname,
4352 GLsizei bufSize,
4353 GLsizei *length,
4354 GLint64 *params)
4355{
4356 if (!ValidateRobustEntryPoint(context, bufSize))
4357 {
4358 return false;
4359 }
4360
4361 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4362 {
4363 return false;
4364 }
4365
4366 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004367 {
4368 return false;
4369 }
4370
4371 return true;
4372}
4373
Jamie Madillbe849e42017-05-02 15:49:00 -04004374bool ValidateGetProgramivBase(ValidationContext *context,
4375 GLuint program,
4376 GLenum pname,
4377 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004378{
4379 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004380 if (numParams)
4381 {
4382 *numParams = 1;
4383 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004384
4385 Program *programObject = GetValidProgram(context, program);
4386 if (!programObject)
4387 {
4388 return false;
4389 }
4390
4391 switch (pname)
4392 {
4393 case GL_DELETE_STATUS:
4394 case GL_LINK_STATUS:
4395 case GL_VALIDATE_STATUS:
4396 case GL_INFO_LOG_LENGTH:
4397 case GL_ATTACHED_SHADERS:
4398 case GL_ACTIVE_ATTRIBUTES:
4399 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4400 case GL_ACTIVE_UNIFORMS:
4401 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4402 break;
4403
4404 case GL_PROGRAM_BINARY_LENGTH:
4405 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4406 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004407 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4408 "requires GL_OES_get_program_binary or "
4409 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004410 return false;
4411 }
4412 break;
4413
4414 case GL_ACTIVE_UNIFORM_BLOCKS:
4415 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4416 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4417 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4418 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4419 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4420 if (context->getClientMajorVersion() < 3)
4421 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004422 context->handleError(InvalidEnum() << "Querying requires at least ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004423 return false;
4424 }
4425 break;
4426
Yunchao He61afff12017-03-14 15:34:03 +08004427 case GL_PROGRAM_SEPARABLE:
4428 if (context->getClientVersion() < Version(3, 1))
4429 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004430 context->handleError(InvalidEnum() << "Querying requires at least ES 3.1.");
Yunchao He61afff12017-03-14 15:34:03 +08004431 return false;
4432 }
4433 break;
4434
Geoff Langff5b2d52016-09-07 11:32:23 -04004435 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004436 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004437 return false;
4438 }
4439
4440 return true;
4441}
4442
4443bool ValidateGetProgramivRobustANGLE(Context *context,
4444 GLuint program,
4445 GLenum pname,
4446 GLsizei bufSize,
4447 GLsizei *numParams)
4448{
4449 if (!ValidateRobustEntryPoint(context, bufSize))
4450 {
4451 return false;
4452 }
4453
Jamie Madillbe849e42017-05-02 15:49:00 -04004454 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004455 {
4456 return false;
4457 }
4458
4459 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4460 {
4461 return false;
4462 }
4463
4464 return true;
4465}
4466
Geoff Lang740d9022016-10-07 11:20:52 -04004467bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4468 GLenum target,
4469 GLenum pname,
4470 GLsizei bufSize,
4471 GLsizei *length,
4472 GLint *params)
4473{
4474 if (!ValidateRobustEntryPoint(context, bufSize))
4475 {
4476 return false;
4477 }
4478
4479 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4480 {
4481 return false;
4482 }
4483
4484 if (!ValidateRobustBufferSize(context, bufSize, *length))
4485 {
4486 return false;
4487 }
4488
4489 return true;
4490}
4491
Geoff Langd7d0ed32016-10-07 11:33:51 -04004492bool ValidateGetShaderivRobustANGLE(Context *context,
4493 GLuint shader,
4494 GLenum pname,
4495 GLsizei bufSize,
4496 GLsizei *length,
4497 GLint *params)
4498{
4499 if (!ValidateRobustEntryPoint(context, bufSize))
4500 {
4501 return false;
4502 }
4503
4504 if (!ValidateGetShaderivBase(context, shader, pname, length))
4505 {
4506 return false;
4507 }
4508
4509 if (!ValidateRobustBufferSize(context, bufSize, *length))
4510 {
4511 return false;
4512 }
4513
4514 return true;
4515}
4516
Geoff Langc1984ed2016-10-07 12:41:00 -04004517bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4518 GLenum target,
4519 GLenum pname,
4520 GLsizei bufSize,
4521 GLsizei *length,
4522 GLfloat *params)
4523{
4524 if (!ValidateRobustEntryPoint(context, bufSize))
4525 {
4526 return false;
4527 }
4528
4529 if (!ValidateGetTexParameterBase(context, target, pname, length))
4530 {
4531 return false;
4532 }
4533
4534 if (!ValidateRobustBufferSize(context, bufSize, *length))
4535 {
4536 return false;
4537 }
4538
4539 return true;
4540}
4541
Geoff Langc1984ed2016-10-07 12:41:00 -04004542bool ValidateGetTexParameterivRobustANGLE(Context *context,
4543 GLenum target,
4544 GLenum pname,
4545 GLsizei bufSize,
4546 GLsizei *length,
4547 GLint *params)
4548{
4549 if (!ValidateRobustEntryPoint(context, bufSize))
4550 {
4551 return false;
4552 }
4553
4554 if (!ValidateGetTexParameterBase(context, target, pname, length))
4555 {
4556 return false;
4557 }
4558
4559 if (!ValidateRobustBufferSize(context, bufSize, *length))
4560 {
4561 return false;
4562 }
4563
4564 return true;
4565}
4566
Geoff Langc1984ed2016-10-07 12:41:00 -04004567bool ValidateTexParameterfvRobustANGLE(Context *context,
4568 GLenum target,
4569 GLenum pname,
4570 GLsizei bufSize,
4571 const GLfloat *params)
4572{
4573 if (!ValidateRobustEntryPoint(context, bufSize))
4574 {
4575 return false;
4576 }
4577
4578 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4579}
4580
Geoff Langc1984ed2016-10-07 12:41:00 -04004581bool ValidateTexParameterivRobustANGLE(Context *context,
4582 GLenum target,
4583 GLenum pname,
4584 GLsizei bufSize,
4585 const GLint *params)
4586{
4587 if (!ValidateRobustEntryPoint(context, bufSize))
4588 {
4589 return false;
4590 }
4591
4592 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4593}
4594
4595bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4596{
4597 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4598}
4599
4600bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4601 GLuint sampler,
4602 GLenum pname,
4603 GLuint bufSize,
4604 GLsizei *length,
4605 GLfloat *params)
4606{
4607 if (!ValidateRobustEntryPoint(context, bufSize))
4608 {
4609 return false;
4610 }
4611
4612 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4613 {
4614 return false;
4615 }
4616
4617 if (!ValidateRobustBufferSize(context, bufSize, *length))
4618 {
4619 return false;
4620 }
4621
4622 return true;
4623}
4624
4625bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4626{
4627 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4628}
4629
4630bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4631 GLuint sampler,
4632 GLenum pname,
4633 GLuint bufSize,
4634 GLsizei *length,
4635 GLint *params)
4636{
4637 if (!ValidateRobustEntryPoint(context, bufSize))
4638 {
4639 return false;
4640 }
4641
4642 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4643 {
4644 return false;
4645 }
4646
4647 if (!ValidateRobustBufferSize(context, bufSize, *length))
4648 {
4649 return false;
4650 }
4651
4652 return true;
4653}
4654
4655bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4656{
4657 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4658}
4659
4660bool ValidateSamplerParameterfv(Context *context,
4661 GLuint sampler,
4662 GLenum pname,
4663 const GLfloat *params)
4664{
4665 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4666}
4667
4668bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4669 GLuint sampler,
4670 GLenum pname,
4671 GLsizei bufSize,
4672 const GLfloat *params)
4673{
4674 if (!ValidateRobustEntryPoint(context, bufSize))
4675 {
4676 return false;
4677 }
4678
4679 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4680}
4681
4682bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4683{
4684 return ValidateSamplerParameterBase(context, sampler, pname, -1, &param);
4685}
4686
4687bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4688{
4689 return ValidateSamplerParameterBase(context, sampler, pname, -1, params);
4690}
4691
4692bool ValidateSamplerParameterivRobustANGLE(Context *context,
4693 GLuint sampler,
4694 GLenum pname,
4695 GLsizei bufSize,
4696 const GLint *params)
4697{
4698 if (!ValidateRobustEntryPoint(context, bufSize))
4699 {
4700 return false;
4701 }
4702
4703 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4704}
4705
Geoff Lang0b031062016-10-13 14:30:04 -04004706bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4707 GLuint index,
4708 GLenum pname,
4709 GLsizei bufSize,
4710 GLsizei *length,
4711 GLfloat *params)
4712{
4713 if (!ValidateRobustEntryPoint(context, bufSize))
4714 {
4715 return false;
4716 }
4717
4718 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4719 {
4720 return false;
4721 }
4722
4723 if (!ValidateRobustBufferSize(context, bufSize, *length))
4724 {
4725 return false;
4726 }
4727
4728 return true;
4729}
4730
Geoff Lang0b031062016-10-13 14:30:04 -04004731bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4732 GLuint index,
4733 GLenum pname,
4734 GLsizei bufSize,
4735 GLsizei *length,
4736 GLint *params)
4737{
4738 if (!ValidateRobustEntryPoint(context, bufSize))
4739 {
4740 return false;
4741 }
4742
4743 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4744 {
4745 return false;
4746 }
4747
4748 if (!ValidateRobustBufferSize(context, bufSize, *length))
4749 {
4750 return false;
4751 }
4752
4753 return true;
4754}
4755
Geoff Lang0b031062016-10-13 14:30:04 -04004756bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4757 GLuint index,
4758 GLenum pname,
4759 GLsizei bufSize,
4760 GLsizei *length,
4761 void **pointer)
4762{
4763 if (!ValidateRobustEntryPoint(context, bufSize))
4764 {
4765 return false;
4766 }
4767
4768 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4769 {
4770 return false;
4771 }
4772
4773 if (!ValidateRobustBufferSize(context, bufSize, *length))
4774 {
4775 return false;
4776 }
4777
4778 return true;
4779}
4780
4781bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
4782{
4783 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4784}
4785
4786bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4787 GLuint index,
4788 GLenum pname,
4789 GLsizei bufSize,
4790 GLsizei *length,
4791 GLint *params)
4792{
4793 if (!ValidateRobustEntryPoint(context, bufSize))
4794 {
4795 return false;
4796 }
4797
4798 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4799 {
4800 return false;
4801 }
4802
4803 if (!ValidateRobustBufferSize(context, bufSize, *length))
4804 {
4805 return false;
4806 }
4807
4808 return true;
4809}
4810
4811bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
4812{
4813 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4814}
4815
4816bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4817 GLuint index,
4818 GLenum pname,
4819 GLsizei bufSize,
4820 GLsizei *length,
4821 GLuint *params)
4822{
4823 if (!ValidateRobustEntryPoint(context, bufSize))
4824 {
4825 return false;
4826 }
4827
4828 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4829 {
4830 return false;
4831 }
4832
4833 if (!ValidateRobustBufferSize(context, bufSize, *length))
4834 {
4835 return false;
4836 }
4837
4838 return true;
4839}
4840
Geoff Lang6899b872016-10-14 11:30:13 -04004841bool ValidateGetActiveUniformBlockiv(Context *context,
4842 GLuint program,
4843 GLuint uniformBlockIndex,
4844 GLenum pname,
4845 GLint *params)
4846{
4847 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
4848}
4849
4850bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4851 GLuint program,
4852 GLuint uniformBlockIndex,
4853 GLenum pname,
4854 GLsizei bufSize,
4855 GLsizei *length,
4856 GLint *params)
4857{
4858 if (!ValidateRobustEntryPoint(context, bufSize))
4859 {
4860 return false;
4861 }
4862
4863 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4864 {
4865 return false;
4866 }
4867
4868 if (!ValidateRobustBufferSize(context, bufSize, *length))
4869 {
4870 return false;
4871 }
4872
4873 return true;
4874}
4875
Geoff Lang0a9661f2016-10-20 10:59:20 -07004876bool ValidateGetInternalFormativ(Context *context,
4877 GLenum target,
4878 GLenum internalformat,
4879 GLenum pname,
4880 GLsizei bufSize,
4881 GLint *params)
4882{
4883 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4884 nullptr);
4885}
4886
4887bool ValidateGetInternalFormativRobustANGLE(Context *context,
4888 GLenum target,
4889 GLenum internalformat,
4890 GLenum pname,
4891 GLsizei bufSize,
4892 GLsizei *length,
4893 GLint *params)
4894{
4895 if (!ValidateRobustEntryPoint(context, bufSize))
4896 {
4897 return false;
4898 }
4899
4900 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4901 {
4902 return false;
4903 }
4904
4905 if (!ValidateRobustBufferSize(context, bufSize, *length))
4906 {
4907 return false;
4908 }
4909
4910 return true;
4911}
4912
Shao80957d92017-02-20 21:25:59 +08004913bool ValidateVertexFormatBase(ValidationContext *context,
4914 GLuint attribIndex,
4915 GLint size,
4916 GLenum type,
4917 GLboolean pureInteger)
4918{
4919 const Caps &caps = context->getCaps();
4920 if (attribIndex >= caps.maxVertexAttributes)
4921 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004922 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Shao80957d92017-02-20 21:25:59 +08004923 return false;
4924 }
4925
4926 if (size < 1 || size > 4)
4927 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004928 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004929 return false;
Shao80957d92017-02-20 21:25:59 +08004930 }
4931
4932 switch (type)
4933 {
4934 case GL_BYTE:
4935 case GL_UNSIGNED_BYTE:
4936 case GL_SHORT:
4937 case GL_UNSIGNED_SHORT:
4938 break;
4939
4940 case GL_INT:
4941 case GL_UNSIGNED_INT:
4942 if (context->getClientMajorVersion() < 3)
4943 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004944 context->handleError(InvalidEnum()
4945 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004946 return false;
4947 }
4948 break;
4949
4950 case GL_FIXED:
4951 case GL_FLOAT:
4952 if (pureInteger)
4953 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004954 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004955 return false;
4956 }
4957 break;
4958
4959 case GL_HALF_FLOAT:
4960 if (context->getClientMajorVersion() < 3)
4961 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004962 context->handleError(InvalidEnum()
4963 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004964 return false;
4965 }
4966 if (pureInteger)
4967 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004968 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004969 return false;
4970 }
4971 break;
4972
4973 case GL_INT_2_10_10_10_REV:
4974 case GL_UNSIGNED_INT_2_10_10_10_REV:
4975 if (context->getClientMajorVersion() < 3)
4976 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004977 context->handleError(InvalidEnum()
4978 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004979 return false;
4980 }
4981 if (pureInteger)
4982 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004983 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004984 return false;
4985 }
4986 if (size != 4)
4987 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004988 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4989 "UNSIGNED_INT_2_10_10_10_REV and "
4990 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004991 return false;
4992 }
4993 break;
4994
4995 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004996 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004997 return false;
4998 }
4999
5000 return true;
5001}
5002
Geoff Lang76e65652017-03-27 14:58:02 -04005003// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
5004// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
5005// specified clear value and the type of a buffer that is being cleared generates an
5006// INVALID_OPERATION error instead of producing undefined results
5007bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
5008 GLint drawbuffer,
5009 const GLenum *validComponentTypes,
5010 size_t validComponentTypeCount)
5011{
5012 const FramebufferAttachment *attachment =
5013 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
5014 if (attachment)
5015 {
5016 GLenum componentType = attachment->getFormat().info->componentType;
5017 const GLenum *end = validComponentTypes + validComponentTypeCount;
5018 if (std::find(validComponentTypes, end, componentType) == end)
5019 {
5020 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005021 InvalidOperation()
5022 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04005023 return false;
5024 }
5025 }
5026
5027 return true;
5028}
5029
Corentin Wallezb2931602017-04-11 15:58:57 -04005030bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
5031 GLsizei imageSize,
5032 GLsizei dataSize)
5033{
5034 if (!ValidateRobustEntryPoint(context, dataSize))
5035 {
5036 return false;
5037 }
5038
5039 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
5040 if (pixelUnpackBuffer == nullptr)
5041 {
5042 if (dataSize < imageSize)
5043 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005044 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04005045 }
5046 }
5047 return true;
5048}
5049
Jamie Madillbe849e42017-05-02 15:49:00 -04005050bool ValidateGetBufferParameterBase(ValidationContext *context,
5051 GLenum target,
5052 GLenum pname,
5053 bool pointerVersion,
5054 GLsizei *numParams)
5055{
5056 if (numParams)
5057 {
5058 *numParams = 0;
5059 }
5060
5061 if (!ValidBufferTarget(context, target))
5062 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005063 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04005064 return false;
5065 }
5066
5067 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
5068 if (!buffer)
5069 {
5070 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07005071 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005072 return false;
5073 }
5074
5075 const Extensions &extensions = context->getExtensions();
5076
5077 switch (pname)
5078 {
5079 case GL_BUFFER_USAGE:
5080 case GL_BUFFER_SIZE:
5081 break;
5082
5083 case GL_BUFFER_ACCESS_OES:
5084 if (!extensions.mapBuffer)
5085 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005086 context->handleError(InvalidEnum()
5087 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005088 return false;
5089 }
5090 break;
5091
5092 case GL_BUFFER_MAPPED:
5093 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
5094 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
5095 !extensions.mapBufferRange)
5096 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005097 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
5098 "GL_OES_mapbuffer or "
5099 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005100 return false;
5101 }
5102 break;
5103
5104 case GL_BUFFER_MAP_POINTER:
5105 if (!pointerVersion)
5106 {
5107 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005108 InvalidEnum()
5109 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005110 return false;
5111 }
5112 break;
5113
5114 case GL_BUFFER_ACCESS_FLAGS:
5115 case GL_BUFFER_MAP_OFFSET:
5116 case GL_BUFFER_MAP_LENGTH:
5117 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
5118 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005119 context->handleError(InvalidEnum()
5120 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005121 return false;
5122 }
5123 break;
5124
5125 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005126 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005127 return false;
5128 }
5129
5130 // All buffer parameter queries return one value.
5131 if (numParams)
5132 {
5133 *numParams = 1;
5134 }
5135
5136 return true;
5137}
5138
5139bool ValidateGetRenderbufferParameterivBase(Context *context,
5140 GLenum target,
5141 GLenum pname,
5142 GLsizei *length)
5143{
5144 if (length)
5145 {
5146 *length = 0;
5147 }
5148
5149 if (target != GL_RENDERBUFFER)
5150 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005151 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005152 return false;
5153 }
5154
5155 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
5156 if (renderbuffer == nullptr)
5157 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005158 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005159 return false;
5160 }
5161
5162 switch (pname)
5163 {
5164 case GL_RENDERBUFFER_WIDTH:
5165 case GL_RENDERBUFFER_HEIGHT:
5166 case GL_RENDERBUFFER_INTERNAL_FORMAT:
5167 case GL_RENDERBUFFER_RED_SIZE:
5168 case GL_RENDERBUFFER_GREEN_SIZE:
5169 case GL_RENDERBUFFER_BLUE_SIZE:
5170 case GL_RENDERBUFFER_ALPHA_SIZE:
5171 case GL_RENDERBUFFER_DEPTH_SIZE:
5172 case GL_RENDERBUFFER_STENCIL_SIZE:
5173 break;
5174
5175 case GL_RENDERBUFFER_SAMPLES_ANGLE:
5176 if (!context->getExtensions().framebufferMultisample)
5177 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005178 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005179 return false;
5180 }
5181 break;
5182
5183 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005184 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005185 return false;
5186 }
5187
5188 if (length)
5189 {
5190 *length = 1;
5191 }
5192 return true;
5193}
5194
5195bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
5196{
5197 if (length)
5198 {
5199 *length = 0;
5200 }
5201
5202 if (GetValidShader(context, shader) == nullptr)
5203 {
5204 return false;
5205 }
5206
5207 switch (pname)
5208 {
5209 case GL_SHADER_TYPE:
5210 case GL_DELETE_STATUS:
5211 case GL_COMPILE_STATUS:
5212 case GL_INFO_LOG_LENGTH:
5213 case GL_SHADER_SOURCE_LENGTH:
5214 break;
5215
5216 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
5217 if (!context->getExtensions().translatedShaderSource)
5218 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005219 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005220 return false;
5221 }
5222 break;
5223
5224 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005225 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005226 return false;
5227 }
5228
5229 if (length)
5230 {
5231 *length = 1;
5232 }
5233 return true;
5234}
5235
5236bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
5237{
5238 if (length)
5239 {
5240 *length = 0;
5241 }
5242
5243 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5244 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005245 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005246 return false;
5247 }
5248
5249 if (context->getTargetTexture(target) == nullptr)
5250 {
5251 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005252 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005253 return false;
5254 }
5255
5256 switch (pname)
5257 {
5258 case GL_TEXTURE_MAG_FILTER:
5259 case GL_TEXTURE_MIN_FILTER:
5260 case GL_TEXTURE_WRAP_S:
5261 case GL_TEXTURE_WRAP_T:
5262 break;
5263
5264 case GL_TEXTURE_USAGE_ANGLE:
5265 if (!context->getExtensions().textureUsage)
5266 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005267 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005268 return false;
5269 }
5270 break;
5271
5272 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5273 if (!context->getExtensions().textureFilterAnisotropic)
5274 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005275 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005276 return false;
5277 }
5278 break;
5279
5280 case GL_TEXTURE_IMMUTABLE_FORMAT:
5281 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
5282 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005283 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04005284 return false;
5285 }
5286 break;
5287
5288 case GL_TEXTURE_WRAP_R:
5289 case GL_TEXTURE_IMMUTABLE_LEVELS:
5290 case GL_TEXTURE_SWIZZLE_R:
5291 case GL_TEXTURE_SWIZZLE_G:
5292 case GL_TEXTURE_SWIZZLE_B:
5293 case GL_TEXTURE_SWIZZLE_A:
5294 case GL_TEXTURE_BASE_LEVEL:
5295 case GL_TEXTURE_MAX_LEVEL:
5296 case GL_TEXTURE_MIN_LOD:
5297 case GL_TEXTURE_MAX_LOD:
5298 case GL_TEXTURE_COMPARE_MODE:
5299 case GL_TEXTURE_COMPARE_FUNC:
5300 if (context->getClientMajorVersion() < 3)
5301 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005302 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005303 return false;
5304 }
5305 break;
5306
5307 case GL_TEXTURE_SRGB_DECODE_EXT:
5308 if (!context->getExtensions().textureSRGBDecode)
5309 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005310 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005311 return false;
5312 }
5313 break;
5314
5315 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005316 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005317 return false;
5318 }
5319
5320 if (length)
5321 {
5322 *length = 1;
5323 }
5324 return true;
5325}
5326
5327bool ValidateGetVertexAttribBase(Context *context,
5328 GLuint index,
5329 GLenum pname,
5330 GLsizei *length,
5331 bool pointer,
5332 bool pureIntegerEntryPoint)
5333{
5334 if (length)
5335 {
5336 *length = 0;
5337 }
5338
5339 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5340 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005341 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005342 return false;
5343 }
5344
5345 if (index >= context->getCaps().maxVertexAttributes)
5346 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005347 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMax);
Jamie Madillbe849e42017-05-02 15:49:00 -04005348 return false;
5349 }
5350
5351 if (pointer)
5352 {
5353 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5354 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005355 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005356 return false;
5357 }
5358 }
5359 else
5360 {
5361 switch (pname)
5362 {
5363 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5364 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5365 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5366 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5367 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5368 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5369 case GL_CURRENT_VERTEX_ATTRIB:
5370 break;
5371
5372 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5373 static_assert(
5374 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5375 "ANGLE extension enums not equal to GL enums.");
5376 if (context->getClientMajorVersion() < 3 &&
5377 !context->getExtensions().instancedArrays)
5378 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005379 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5380 "requires OpenGL ES 3.0 or "
5381 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005382 return false;
5383 }
5384 break;
5385
5386 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5387 if (context->getClientMajorVersion() < 3)
5388 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005389 context->handleError(
5390 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005391 return false;
5392 }
5393 break;
5394
5395 case GL_VERTEX_ATTRIB_BINDING:
5396 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5397 if (context->getClientVersion() < ES_3_1)
5398 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005399 context->handleError(InvalidEnum()
5400 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005401 return false;
5402 }
5403 break;
5404
5405 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005406 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005407 return false;
5408 }
5409 }
5410
5411 if (length)
5412 {
5413 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5414 {
5415 *length = 4;
5416 }
5417 else
5418 {
5419 *length = 1;
5420 }
5421 }
5422
5423 return true;
5424}
5425
Jamie Madill4928b7c2017-06-20 12:57:39 -04005426bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005427 GLint x,
5428 GLint y,
5429 GLsizei width,
5430 GLsizei height,
5431 GLenum format,
5432 GLenum type,
5433 GLsizei bufSize,
5434 GLsizei *length,
5435 GLsizei *columns,
5436 GLsizei *rows,
5437 void *pixels)
5438{
5439 if (length != nullptr)
5440 {
5441 *length = 0;
5442 }
5443 if (rows != nullptr)
5444 {
5445 *rows = 0;
5446 }
5447 if (columns != nullptr)
5448 {
5449 *columns = 0;
5450 }
5451
5452 if (width < 0 || height < 0)
5453 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005454 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005455 return false;
5456 }
5457
5458 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5459
5460 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5461 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005462 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005463 return false;
5464 }
5465
5466 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5467 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005468 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005469 return false;
5470 }
5471
5472 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5473 ASSERT(framebuffer);
5474
5475 if (framebuffer->getReadBufferState() == GL_NONE)
5476 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005477 context->handleError(InvalidOperation() << "Read buffer is GL_NONE");
Jamie Madillbe849e42017-05-02 15:49:00 -04005478 return false;
5479 }
5480
5481 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5482 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5483 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5484 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5485 // situation is an application error that would lead to a crash in ANGLE.
5486 if (readBuffer == nullptr)
5487 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005488 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005489 return false;
5490 }
5491
Martin Radev28031682017-07-28 14:47:56 +03005492 // ANGLE_multiview, Revision 1:
5493 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5494 // current read framebuffer is not NONE.
5495 if (readBuffer->getMultiviewLayout() != GL_NONE)
5496 {
5497 context->handleError(InvalidFramebufferOperation()
5498 << "Attempting to read from a multi-view framebuffer.");
5499 return false;
5500 }
5501
Geoff Lang280ba992017-04-18 16:30:58 -04005502 if (context->getExtensions().webglCompatibility)
5503 {
5504 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5505 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5506 // and type before validating the combination of format and type. However, the
5507 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5508 // verifies that GL_INVALID_OPERATION is generated.
5509 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5510 // dEQP/WebGL.
5511 if (!ValidReadPixelsFormatEnum(context, format))
5512 {
5513 context->handleError(InvalidEnum() << "Invalid read format.");
5514 return false;
5515 }
5516
5517 if (!ValidReadPixelsTypeEnum(context, type))
5518 {
5519 context->handleError(InvalidEnum() << "Invalid read type.");
5520 return false;
5521 }
5522 }
5523
Jamie Madill4928b7c2017-06-20 12:57:39 -04005524 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5525 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005526 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5527
5528 bool validFormatTypeCombination =
5529 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5530
5531 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5532 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005533 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005534 return false;
5535 }
5536
5537 // Check for pixel pack buffer related API errors
5538 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5539 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5540 {
5541 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005542 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005543 return false;
5544 }
5545
5546 // .. the data would be packed to the buffer object such that the memory writes required
5547 // would exceed the data store size.
5548 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5549 const gl::Extents size(width, height, 1);
5550 const auto &pack = context->getGLState().getPackState();
5551
5552 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5553 if (endByteOrErr.isError())
5554 {
5555 context->handleError(endByteOrErr.getError());
5556 return false;
5557 }
5558
5559 size_t endByte = endByteOrErr.getResult();
5560 if (bufSize >= 0)
5561 {
5562 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5563 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005564 context->handleError(InvalidOperation()
5565 << "bufSize must be at least " << endByte << " bytes.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005566 return false;
5567 }
5568 }
5569
5570 if (pixelPackBuffer != nullptr)
5571 {
5572 CheckedNumeric<size_t> checkedEndByte(endByte);
5573 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5574 checkedEndByte += checkedOffset;
5575
5576 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5577 {
5578 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005579 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005580 return false;
5581 }
5582 }
5583
5584 if (pixelPackBuffer == nullptr && length != nullptr)
5585 {
5586 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5587 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005588 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005589 return false;
5590 }
5591
5592 *length = static_cast<GLsizei>(endByte);
5593 }
5594
5595 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5596 angle::CheckedNumeric<int> clippedExtent(length);
5597 if (start < 0)
5598 {
5599 // "subtract" the area that is less than 0
5600 clippedExtent += start;
5601 }
5602
5603 const int readExtent = start + length;
5604 if (readExtent > bufferSize)
5605 {
5606 // Subtract the region to the right of the read buffer
5607 clippedExtent -= (readExtent - bufferSize);
5608 }
5609
5610 if (!clippedExtent.IsValid())
5611 {
5612 return 0;
5613 }
5614
5615 return std::max(clippedExtent.ValueOrDie(), 0);
5616 };
5617
5618 if (columns != nullptr)
5619 {
5620 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5621 }
5622
5623 if (rows != nullptr)
5624 {
5625 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5626 }
5627
5628 return true;
5629}
5630
5631template <typename ParamType>
5632bool ValidateTexParameterBase(Context *context,
5633 GLenum target,
5634 GLenum pname,
5635 GLsizei bufSize,
5636 const ParamType *params)
5637{
5638 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5639 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005640 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005641 return false;
5642 }
5643
5644 if (context->getTargetTexture(target) == nullptr)
5645 {
5646 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005647 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005648 return false;
5649 }
5650
5651 const GLsizei minBufSize = 1;
5652 if (bufSize >= 0 && bufSize < minBufSize)
5653 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005654 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005655 return false;
5656 }
5657
5658 switch (pname)
5659 {
5660 case GL_TEXTURE_WRAP_R:
5661 case GL_TEXTURE_SWIZZLE_R:
5662 case GL_TEXTURE_SWIZZLE_G:
5663 case GL_TEXTURE_SWIZZLE_B:
5664 case GL_TEXTURE_SWIZZLE_A:
5665 case GL_TEXTURE_BASE_LEVEL:
5666 case GL_TEXTURE_MAX_LEVEL:
5667 case GL_TEXTURE_COMPARE_MODE:
5668 case GL_TEXTURE_COMPARE_FUNC:
5669 case GL_TEXTURE_MIN_LOD:
5670 case GL_TEXTURE_MAX_LOD:
5671 if (context->getClientMajorVersion() < 3)
5672 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005673 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005674 return false;
5675 }
5676 if (target == GL_TEXTURE_EXTERNAL_OES &&
5677 !context->getExtensions().eglImageExternalEssl3)
5678 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005679 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5680 "available without "
5681 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005682 return false;
5683 }
5684 break;
5685
5686 default:
5687 break;
5688 }
5689
JiangYizhou4cff8d62017-07-06 14:54:09 +08005690 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5691 {
5692 switch (pname)
5693 {
5694 case GL_TEXTURE_MIN_FILTER:
5695 case GL_TEXTURE_MAG_FILTER:
5696 case GL_TEXTURE_WRAP_S:
5697 case GL_TEXTURE_WRAP_T:
5698 case GL_TEXTURE_WRAP_R:
5699 case GL_TEXTURE_MIN_LOD:
5700 case GL_TEXTURE_MAX_LOD:
5701 case GL_TEXTURE_COMPARE_MODE:
5702 case GL_TEXTURE_COMPARE_FUNC:
5703 context->handleError(InvalidEnum()
5704 << "Invalid parameter for 2D multisampled textures.");
5705 return false;
5706 }
5707 }
5708
Jamie Madillbe849e42017-05-02 15:49:00 -04005709 switch (pname)
5710 {
5711 case GL_TEXTURE_WRAP_S:
5712 case GL_TEXTURE_WRAP_T:
5713 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005714 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005715 bool restrictedWrapModes =
5716 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5717 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5718 {
5719 return false;
5720 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005721 }
5722 break;
5723
5724 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005725 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005726 bool restrictedMinFilter =
5727 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5728 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5729 {
5730 return false;
5731 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005732 }
5733 break;
5734
5735 case GL_TEXTURE_MAG_FILTER:
5736 if (!ValidateTextureMagFilterValue(context, params))
5737 {
5738 return false;
5739 }
5740 break;
5741
5742 case GL_TEXTURE_USAGE_ANGLE:
5743 switch (ConvertToGLenum(params[0]))
5744 {
5745 case GL_NONE:
5746 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5747 break;
5748
5749 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005750 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005751 return false;
5752 }
5753 break;
5754
5755 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5756 if (!context->getExtensions().textureFilterAnisotropic)
5757 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005758 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005759 return false;
5760 }
5761
5762 // we assume the parameter passed to this validation method is truncated, not rounded
5763 if (params[0] < 1)
5764 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005765 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005766 return false;
5767 }
5768 break;
5769
5770 case GL_TEXTURE_MIN_LOD:
5771 case GL_TEXTURE_MAX_LOD:
5772 // any value is permissible
5773 break;
5774
5775 case GL_TEXTURE_COMPARE_MODE:
5776 if (!ValidateTextureCompareModeValue(context, params))
5777 {
5778 return false;
5779 }
5780 break;
5781
5782 case GL_TEXTURE_COMPARE_FUNC:
5783 if (!ValidateTextureCompareFuncValue(context, params))
5784 {
5785 return false;
5786 }
5787 break;
5788
5789 case GL_TEXTURE_SWIZZLE_R:
5790 case GL_TEXTURE_SWIZZLE_G:
5791 case GL_TEXTURE_SWIZZLE_B:
5792 case GL_TEXTURE_SWIZZLE_A:
5793 switch (ConvertToGLenum(params[0]))
5794 {
5795 case GL_RED:
5796 case GL_GREEN:
5797 case GL_BLUE:
5798 case GL_ALPHA:
5799 case GL_ZERO:
5800 case GL_ONE:
5801 break;
5802
5803 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005804 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005805 return false;
5806 }
5807 break;
5808
5809 case GL_TEXTURE_BASE_LEVEL:
5810 if (params[0] < 0)
5811 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005812 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005813 return false;
5814 }
5815 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5816 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005817 context->handleError(InvalidOperation()
5818 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005819 return false;
5820 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005821 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5822 {
5823 context->handleError(InvalidOperation()
5824 << "Base level must be 0 for multisampled textures.");
5825 return false;
5826 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005827 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5828 {
5829 context->handleError(InvalidOperation()
5830 << "Base level must be 0 for rectangle textures.");
5831 return false;
5832 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005833 break;
5834
5835 case GL_TEXTURE_MAX_LEVEL:
5836 if (params[0] < 0)
5837 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005838 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005839 return false;
5840 }
5841 break;
5842
5843 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5844 if (context->getClientVersion() < Version(3, 1))
5845 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005846 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005847 return false;
5848 }
5849 switch (ConvertToGLenum(params[0]))
5850 {
5851 case GL_DEPTH_COMPONENT:
5852 case GL_STENCIL_INDEX:
5853 break;
5854
5855 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005856 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005857 return false;
5858 }
5859 break;
5860
5861 case GL_TEXTURE_SRGB_DECODE_EXT:
5862 if (!ValidateTextureSRGBDecodeValue(context, params))
5863 {
5864 return false;
5865 }
5866 break;
5867
5868 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005869 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005870 return false;
5871 }
5872
5873 return true;
5874}
5875
5876template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5877template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5878
Jamie Madillc29968b2016-01-20 11:17:23 -05005879} // namespace gl