blob: df3092d448e6add84402b99bb7c653eaef43e794 [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.
Brandon Jonesafa75152017-07-21 13:11:29 -070073 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
Corentin Wallezfd456442016-12-21 17:57:00 -050074 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050075 }
Corentin Wallezfd456442016-12-21 17:57:00 -050076 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040077 {
78 // This is an application error that would normally result in a crash,
79 // but we catch it and return an error
Brandon Jonesafa75152017-07-21 13:11:29 -070080 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
Jamie Madill1ca74672015-07-21 15:14:11 -040081 return false;
82 }
Corentin Wallezfd456442016-12-21 17:57:00 -050083 continue;
84 }
85
Corentin Wallez672f7f32017-06-15 17:42:17 -040086 // This needs to come after the check for client arrays as even unused attributes cannot use
87 // client-side arrays
88 if (!program->isAttribLocationActive(attributeIndex))
89 {
90 continue;
91 }
92
Corentin Wallezfd456442016-12-21 17:57:00 -050093 // If we're drawing zero vertices, we have enough data.
94 if (vertexCount <= 0 || primcount <= 0)
95 {
96 continue;
97 }
98
99 GLint maxVertexElement = 0;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300100 GLuint divisor = binding.getDivisor();
101 if (divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500102 {
103 maxVertexElement = maxVertex;
104 }
105 else
106 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300107 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500108 }
109
110 // We do manual overflow checks here instead of using safe_math.h because it was
111 // a bottleneck. Thanks to some properties of GL we know inequalities that can
112 // help us make the overflow checks faster.
113
114 // The max possible attribSize is 16 for a vector of 4 32 bit values.
115 constexpr uint64_t kMaxAttribSize = 16;
116 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
117 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
118
119 // We know attribStride is given as a GLsizei which is typedefed to int.
120 // We also know an upper bound for attribSize.
121 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800122 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500123 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
124 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
125
126 // Computing the max offset using uint64_t without attrib.offset is overflow
127 // safe. Note: Last vertex element does not take the full stride!
128 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
129 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
130
131 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800132 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
133 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500134 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700135 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500136 return false;
137 }
138 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
139
140 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
141 // We can return INVALID_OPERATION if our vertex attribute does not have
142 // enough backing data.
143 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
144 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700145 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500146 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400147 }
148 }
149
150 return true;
151}
152
Geoff Lang280ba992017-04-18 16:30:58 -0400153bool ValidReadPixelsTypeEnum(ValidationContext *context, GLenum type)
154{
155 switch (type)
156 {
157 // Types referenced in Table 3.4 of the ES 2.0.25 spec
158 case GL_UNSIGNED_BYTE:
159 case GL_UNSIGNED_SHORT_4_4_4_4:
160 case GL_UNSIGNED_SHORT_5_5_5_1:
161 case GL_UNSIGNED_SHORT_5_6_5:
162 return context->getClientVersion() >= ES_2_0;
163
164 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
165 case GL_BYTE:
166 case GL_INT:
167 case GL_SHORT:
168 case GL_UNSIGNED_INT:
169 case GL_UNSIGNED_INT_10F_11F_11F_REV:
170 case GL_UNSIGNED_INT_24_8:
171 case GL_UNSIGNED_INT_2_10_10_10_REV:
172 case GL_UNSIGNED_INT_5_9_9_9_REV:
173 case GL_UNSIGNED_SHORT:
174 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
175 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
176 return context->getClientVersion() >= ES_3_0;
177
178 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400179 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
180 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400181
182 case GL_HALF_FLOAT:
183 return context->getClientVersion() >= ES_3_0 ||
184 context->getExtensions().textureHalfFloat;
185
186 case GL_HALF_FLOAT_OES:
187 return context->getExtensions().colorBufferHalfFloat;
188
189 default:
190 return false;
191 }
192}
193
194bool ValidReadPixelsFormatEnum(ValidationContext *context, GLenum format)
195{
196 switch (format)
197 {
198 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
199 case GL_RGBA:
200 case GL_RGB:
201 case GL_ALPHA:
202 return context->getClientVersion() >= ES_2_0;
203
204 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
205 case GL_RG:
206 case GL_RED:
207 case GL_RGBA_INTEGER:
208 case GL_RGB_INTEGER:
209 case GL_RG_INTEGER:
210 case GL_RED_INTEGER:
211 return context->getClientVersion() >= ES_3_0;
212
213 case GL_SRGB_ALPHA_EXT:
214 case GL_SRGB_EXT:
215 return context->getExtensions().sRGB;
216
217 case GL_BGRA_EXT:
218 return context->getExtensions().readFormatBGRA;
219
220 default:
221 return false;
222 }
223}
224
Geoff Langf607c602016-09-21 11:46:48 -0400225bool ValidReadPixelsFormatType(ValidationContext *context,
226 GLenum framebufferComponentType,
227 GLenum format,
228 GLenum type)
229{
230 switch (framebufferComponentType)
231 {
232 case GL_UNSIGNED_NORMALIZED:
233 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
234 // ReadPixels with BGRA even if the extension is not present
235 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
236 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
237 type == GL_UNSIGNED_BYTE);
238
239 case GL_SIGNED_NORMALIZED:
240 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
241
242 case GL_INT:
243 return (format == GL_RGBA_INTEGER && type == GL_INT);
244
245 case GL_UNSIGNED_INT:
246 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
247
248 case GL_FLOAT:
249 return (format == GL_RGBA && type == GL_FLOAT);
250
251 default:
252 UNREACHABLE();
253 return false;
254 }
255}
256
Geoff Langc1984ed2016-10-07 12:41:00 -0400257template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400258bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400259{
260 switch (ConvertToGLenum(params[0]))
261 {
262 case GL_CLAMP_TO_EDGE:
263 break;
264
265 case GL_REPEAT:
266 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400267 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400268 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400269 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700270 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400271 return false;
272 }
273 break;
274
275 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700276 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400277 return false;
278 }
279
280 return true;
281}
282
283template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400284bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400285{
286 switch (ConvertToGLenum(params[0]))
287 {
288 case GL_NEAREST:
289 case GL_LINEAR:
290 break;
291
292 case GL_NEAREST_MIPMAP_NEAREST:
293 case GL_LINEAR_MIPMAP_NEAREST:
294 case GL_NEAREST_MIPMAP_LINEAR:
295 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400296 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400297 {
298 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700299 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400300 return false;
301 }
302 break;
303
304 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700305 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400306 return false;
307 }
308
309 return true;
310}
311
312template <typename ParamType>
313bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
314{
315 switch (ConvertToGLenum(params[0]))
316 {
317 case GL_NEAREST:
318 case GL_LINEAR:
319 break;
320
321 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700322 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400323 return false;
324 }
325
326 return true;
327}
328
329template <typename ParamType>
330bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
331{
332 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
333 switch (ConvertToGLenum(params[0]))
334 {
335 case GL_NONE:
336 case GL_COMPARE_REF_TO_TEXTURE:
337 break;
338
339 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700340 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400341 return false;
342 }
343
344 return true;
345}
346
347template <typename ParamType>
348bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
349{
350 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
351 switch (ConvertToGLenum(params[0]))
352 {
353 case GL_LEQUAL:
354 case GL_GEQUAL:
355 case GL_LESS:
356 case GL_GREATER:
357 case GL_EQUAL:
358 case GL_NOTEQUAL:
359 case GL_ALWAYS:
360 case GL_NEVER:
361 break;
362
363 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700364 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400365 return false;
366 }
367
368 return true;
369}
370
371template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700372bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
373{
374 if (!context->getExtensions().textureSRGBDecode)
375 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700376 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700377 return false;
378 }
379
380 switch (ConvertToGLenum(params[0]))
381 {
382 case GL_DECODE_EXT:
383 case GL_SKIP_DECODE_EXT:
384 break;
385
386 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700387 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700388 return false;
389 }
390
391 return true;
392}
393
Jamie Madillc1d770e2017-04-13 17:31:24 -0400394bool ValidateUniformCommonBase(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500395 gl::Program *program,
396 GLint location,
397 GLsizei count,
398 const LinkedUniform **uniformOut)
399{
400 // TODO(Jiajia): Add image uniform check in future.
401 if (count < 0)
402 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700403 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500404 return false;
405 }
406
Brandon Jones6cad5662017-06-14 13:25:13 -0700407 if (!program)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500408 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700409 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
410 return false;
411 }
412
413 if (!program->isLinked())
414 {
415 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500416 return false;
417 }
418
419 if (location == -1)
420 {
421 // Silently ignore the uniform command
422 return false;
423 }
424
425 const auto &uniformLocations = program->getUniformLocations();
Jamie Madillbe849e42017-05-02 15:49:00 -0400426 size_t castedLocation = static_cast<size_t>(location);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500427 if (castedLocation >= uniformLocations.size())
428 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500429 context->handleError(InvalidOperation() << "Invalid uniform location");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500430 return false;
431 }
432
433 const auto &uniformLocation = uniformLocations[castedLocation];
434 if (uniformLocation.ignored)
435 {
436 // Silently ignore the uniform command
437 return false;
438 }
439
440 if (!uniformLocation.used)
441 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500442 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500443 return false;
444 }
445
446 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
447
448 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
449 if (!uniform.isArray() && count > 1)
450 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500451 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500452 return false;
453 }
454
455 *uniformOut = &uniform;
456 return true;
457}
458
Frank Henigman999b0fd2017-02-02 21:45:55 -0500459bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -0500460 GLenum uniformType,
461 GLsizei count,
462 const GLint *value)
463{
464 // Value type is GL_INT, because we only get here from glUniform1i{v}.
465 // It is compatible with INT or BOOL.
466 // Do these cheap tests first, for a little extra speed.
467 if (GL_INT == uniformType || GL_BOOL == uniformType)
468 {
469 return true;
470 }
471
472 if (IsSamplerType(uniformType))
473 {
Frank Henigman999b0fd2017-02-02 21:45:55 -0500474 // Check that the values are in range.
475 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
476 for (GLsizei i = 0; i < count; ++i)
477 {
478 if (value[i] < 0 || value[i] >= max)
479 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500480 context->handleError(InvalidValue() << "sampler uniform value out of range");
Frank Henigman999b0fd2017-02-02 21:45:55 -0500481 return false;
482 }
483 }
Frank Henigmana98a6472017-02-02 21:38:32 -0500484 return true;
485 }
486
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500487 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmana98a6472017-02-02 21:38:32 -0500488 return false;
489}
490
Jamie Madillc1d770e2017-04-13 17:31:24 -0400491bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500492{
493 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -0500494 // Do the cheaper test first, for a little extra speed.
495 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500496 {
497 return true;
498 }
499
Brandon Jonesafa75152017-07-21 13:11:29 -0700500 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500501 return false;
502}
503
Jamie Madillc1d770e2017-04-13 17:31:24 -0400504bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500505{
506 // Check that the value type is compatible with uniform type.
507 if (valueType == uniformType)
508 {
509 return true;
510 }
511
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500512 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500513 return false;
514}
515
Geoff Lange0cff192017-05-30 13:04:56 -0400516bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
517{
518 const Program *program = context->getGLState().getProgram();
519 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
520
521 const auto &programOutputTypes = program->getOutputVariableTypes();
522 for (size_t drawBufferIdx = 0; drawBufferIdx < programOutputTypes.size(); drawBufferIdx++)
523 {
524 GLenum outputType = programOutputTypes[drawBufferIdx];
525 GLenum inputType = framebuffer->getDrawbufferWriteType(drawBufferIdx);
526 if (outputType != GL_NONE && inputType != GL_NONE && inputType != outputType)
527 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500528 context->handleError(InvalidOperation() << "Fragment shader output type does not "
529 "match the bound framebuffer attachment "
530 "type.");
Geoff Lange0cff192017-05-30 13:04:56 -0400531 return false;
532 }
533 }
534
535 return true;
536}
537
Geoff Lang9ab5b822017-05-30 16:19:23 -0400538bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
539{
540 const Program *program = context->getGLState().getProgram();
541 const VertexArray *vao = context->getGLState().getVertexArray();
542
543 for (const auto &shaderAttribute : program->getAttributes())
544 {
Geoff Lang69df2422017-07-05 12:42:31 -0400545 // gl_VertexID and gl_InstanceID are active attributes but don't have a bound attribute.
546 if (shaderAttribute.isBuiltIn())
547 {
548 continue;
549 }
550
Geoff Lang9ab5b822017-05-30 16:19:23 -0400551 GLenum shaderInputType = VariableComponentType(shaderAttribute.type);
552
553 const auto &attrib = vao->getVertexAttribute(shaderAttribute.location);
554 const auto &currentValue =
555 context->getGLState().getVertexAttribCurrentValue(shaderAttribute.location);
556 GLenum vertexType = attrib.enabled ? GetVertexAttributeBaseType(attrib) : currentValue.Type;
557
558 if (shaderInputType != GL_NONE && vertexType != GL_NONE && shaderInputType != vertexType)
559 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500560 context->handleError(InvalidOperation() << "Vertex shader input type does not "
561 "match the type of the bound vertex "
562 "attribute.");
Geoff Lang9ab5b822017-05-30 16:19:23 -0400563 return false;
564 }
565 }
566
567 return true;
568}
569
Geoff Langf41a7152016-09-19 15:11:17 -0400570} // anonymous namespace
571
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500572bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400573{
Jamie Madilld7460c72014-01-21 16:38:14 -0500574 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400575 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800576 case GL_TEXTURE_2D:
577 case GL_TEXTURE_CUBE_MAP:
578 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400579
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400580 case GL_TEXTURE_RECTANGLE_ANGLE:
581 return context->getExtensions().textureRectangle;
582
He Yunchaoced53ae2016-11-29 15:00:51 +0800583 case GL_TEXTURE_3D:
584 case GL_TEXTURE_2D_ARRAY:
585 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500586
He Yunchaoced53ae2016-11-29 15:00:51 +0800587 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800588 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400589
He Yunchaoced53ae2016-11-29 15:00:51 +0800590 default:
591 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500592 }
Jamie Madill35d15012013-10-07 10:46:37 -0400593}
594
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500595bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
596{
597 switch (target)
598 {
599 case GL_TEXTURE_2D:
600 case GL_TEXTURE_CUBE_MAP:
601 return true;
602
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400603 case GL_TEXTURE_RECTANGLE_ANGLE:
604 return context->getExtensions().textureRectangle;
605
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500606 default:
607 return false;
608 }
609}
610
611bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
612{
613 switch (target)
614 {
615 case GL_TEXTURE_3D:
616 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300617 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500618
619 default:
620 return false;
621 }
622}
623
Ian Ewellbda75592016-04-18 17:25:54 -0400624// Most texture GL calls are not compatible with external textures, so we have a separate validation
625// function for use in the GL calls that do
626bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
627{
628 return (target == GL_TEXTURE_EXTERNAL_OES) &&
629 (context->getExtensions().eglImageExternal ||
630 context->getExtensions().eglStreamConsumerExternal);
631}
632
Shannon Woods4dfed832014-03-17 20:03:39 -0400633// This function differs from ValidTextureTarget in that the target must be
634// usable as the destination of a 2D operation-- so a cube face is valid, but
635// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400636// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500637bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400638{
639 switch (target)
640 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800641 case GL_TEXTURE_2D:
642 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
643 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
644 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
645 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
646 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
647 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
648 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400649 case GL_TEXTURE_RECTANGLE_ANGLE:
650 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800651 default:
652 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500653 }
654}
655
Jamie Madillbe849e42017-05-02 15:49:00 -0400656bool ValidateDrawElementsInstancedBase(ValidationContext *context,
657 GLenum mode,
658 GLsizei count,
659 GLenum type,
660 const GLvoid *indices,
661 GLsizei primcount)
662{
663 if (primcount < 0)
664 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700665 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400666 return false;
667 }
668
669 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
670 {
671 return false;
672 }
673
674 // No-op zero primitive count
675 return (primcount > 0);
676}
677
678bool ValidateDrawArraysInstancedBase(Context *context,
679 GLenum mode,
680 GLint first,
681 GLsizei count,
682 GLsizei primcount)
683{
684 if (primcount < 0)
685 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700686 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400687 return false;
688 }
689
690 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
691 {
692 return false;
693 }
694
695 // No-op if zero primitive count
696 return (primcount > 0);
697}
698
Corentin Wallez0dc97812017-06-22 14:38:44 -0400699bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400700{
701 // Verify there is at least one active attribute with a divisor of zero
702 const State &state = context->getGLState();
703
704 Program *program = state.getProgram();
705
706 const auto &attribs = state.getVertexArray()->getVertexAttributes();
707 const auto &bindings = state.getVertexArray()->getVertexBindings();
708 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
709 {
710 const VertexAttribute &attrib = attribs[attributeIndex];
711 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300712 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400713 {
714 return true;
715 }
716 }
717
Brandon Jonesafa75152017-07-21 13:11:29 -0700718 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400719 return false;
720}
721
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500722bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
723{
724 switch (target)
725 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800726 case GL_TEXTURE_3D:
727 case GL_TEXTURE_2D_ARRAY:
728 return true;
729 default:
730 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400731 }
732}
733
He Yunchao11b038b2016-11-22 21:24:04 +0800734bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
735{
736 switch (target)
737 {
738 case GL_TEXTURE_2D:
739 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
740 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
741 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
742 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
743 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
744 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
745 case GL_TEXTURE_3D:
746 case GL_TEXTURE_2D_ARRAY:
747 case GL_TEXTURE_2D_MULTISAMPLE:
748 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400749 case GL_TEXTURE_RECTANGLE_ANGLE:
750 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800751 default:
752 return false;
753 }
754}
755
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500756bool ValidFramebufferTarget(GLenum target)
757{
He Yunchaoced53ae2016-11-29 15:00:51 +0800758 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
759 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400760 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500761
762 switch (target)
763 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800764 case GL_FRAMEBUFFER:
765 return true;
766 case GL_READ_FRAMEBUFFER:
767 return true;
768 case GL_DRAW_FRAMEBUFFER:
769 return true;
770 default:
771 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500772 }
773}
774
Jamie Madill29639852016-09-02 15:00:09 -0400775bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -0500776{
777 switch (target)
778 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800779 case GL_ARRAY_BUFFER:
780 case GL_ELEMENT_ARRAY_BUFFER:
781 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -0500782
He Yunchaoced53ae2016-11-29 15:00:51 +0800783 case GL_PIXEL_PACK_BUFFER:
784 case GL_PIXEL_UNPACK_BUFFER:
785 return (context->getExtensions().pixelBufferObject ||
786 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -0400787
He Yunchaoced53ae2016-11-29 15:00:51 +0800788 case GL_COPY_READ_BUFFER:
789 case GL_COPY_WRITE_BUFFER:
790 case GL_TRANSFORM_FEEDBACK_BUFFER:
791 case GL_UNIFORM_BUFFER:
792 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -0500793
He Yunchaoced53ae2016-11-29 15:00:51 +0800794 case GL_ATOMIC_COUNTER_BUFFER:
795 case GL_SHADER_STORAGE_BUFFER:
796 case GL_DRAW_INDIRECT_BUFFER:
797 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800798 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -0400799
He Yunchaoced53ae2016-11-29 15:00:51 +0800800 default:
801 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -0500802 }
803}
804
Jamie Madillc29968b2016-01-20 11:17:23 -0500805bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400806{
Jamie Madillc29968b2016-01-20 11:17:23 -0500807 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400808 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -0400809 switch (target)
810 {
Jamie Madillc29968b2016-01-20 11:17:23 -0500811 case GL_TEXTURE_2D:
812 maxDimension = caps.max2DTextureSize;
813 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800814 case GL_TEXTURE_CUBE_MAP:
815 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
816 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
817 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
818 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
819 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
820 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
821 maxDimension = caps.maxCubeMapTextureSize;
822 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400823 case GL_TEXTURE_RECTANGLE_ANGLE:
824 return level == 0;
He Yunchaoced53ae2016-11-29 15:00:51 +0800825 case GL_TEXTURE_3D:
826 maxDimension = caps.max3DTextureSize;
827 break;
828 case GL_TEXTURE_2D_ARRAY:
829 maxDimension = caps.max2DTextureSize;
830 break;
He Yunchao11b038b2016-11-22 21:24:04 +0800831 case GL_TEXTURE_2D_MULTISAMPLE:
832 maxDimension = caps.max2DTextureSize;
833 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800834 default:
835 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400836 }
837
Brandon Jones6cad5662017-06-14 13:25:13 -0700838 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400839}
840
Brandon Jones6cad5662017-06-14 13:25:13 -0700841bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -0700842 GLenum target,
843 GLint level,
844 GLsizei width,
845 GLsizei height,
846 GLsizei depth,
847 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400848{
Brandon Jones6cad5662017-06-14 13:25:13 -0700849 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400850 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700851 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400852 return false;
853 }
Austin Kinross08528e12015-10-07 16:24:40 -0700854 // TexSubImage parameters can be NPOT without textureNPOT extension,
855 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500856 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500857 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500858 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400859 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400860 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700861 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400862 return false;
863 }
864
865 if (!ValidMipLevel(context, target, level))
866 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700867 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400868 return false;
869 }
870
871 return true;
872}
873
Geoff Lang0d8b7242015-09-09 14:56:53 -0400874bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
875{
876 // List of compressed format that require that the texture size is smaller than or a multiple of
877 // the compressed block size.
878 switch (internalFormat)
879 {
880 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
881 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
882 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
883 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langfff7a7d2017-06-02 10:39:17 -0400884 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
885 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
886 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
887 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
Minmin Gonge3939b92015-12-01 15:36:51 -0800888 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800889 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
890 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
891 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
892 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
893 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
894 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -0400895 return true;
896
897 default:
898 return false;
899 }
900}
901
Geoff Lang966c9402017-04-18 12:38:27 -0400902bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
903{
904 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
905 (size % blockSize == 0);
906}
907
Jamie Madillc29968b2016-01-20 11:17:23 -0500908bool ValidCompressedImageSize(const ValidationContext *context,
909 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400910 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500911 GLsizei width,
912 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400913{
Geoff Langca271392017-04-05 12:30:00 -0400914 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400915 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400916 {
917 return false;
918 }
919
Geoff Lang966c9402017-04-18 12:38:27 -0400920 if (width < 0 || height < 0)
921 {
922 return false;
923 }
924
925 if (CompressedTextureFormatRequiresExactSize(internalFormat))
926 {
927 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
928 // block size for level 0 but WebGL disallows this.
929 bool smallerThanBlockSizeAllowed =
930 level > 0 || !context->getExtensions().webglCompatibility;
931
932 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
933 smallerThanBlockSizeAllowed) ||
934 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
935 smallerThanBlockSizeAllowed))
936 {
937 return false;
938 }
939 }
940
941 return true;
942}
943
944bool ValidCompressedSubImageSize(const ValidationContext *context,
945 GLenum internalFormat,
946 GLint xoffset,
947 GLint yoffset,
948 GLsizei width,
949 GLsizei height,
950 size_t textureWidth,
951 size_t textureHeight)
952{
953 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
954 if (!formatInfo.compressed)
955 {
956 return false;
957 }
958
Geoff Lang44ff5a72017-02-03 15:15:43 -0500959 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400960 {
961 return false;
962 }
963
Geoff Lang0d8b7242015-09-09 14:56:53 -0400964 if (CompressedTextureFormatRequiresExactSize(internalFormat))
965 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500966 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400967 yoffset % formatInfo.compressedBlockHeight != 0)
968 {
969 return false;
970 }
971
972 // Allowed to either have data that is a multiple of block size or is smaller than the block
973 // size but fills the entire mip
974 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
975 static_cast<size_t>(width) == textureWidth &&
976 static_cast<size_t>(height) == textureHeight;
977 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
978 (height % formatInfo.compressedBlockHeight) == 0;
979 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400980 {
981 return false;
982 }
983 }
984
Geoff Langd4f180b2013-09-24 13:57:44 -0400985 return true;
986}
987
Geoff Langff5b2d52016-09-07 11:32:23 -0400988bool ValidImageDataSize(ValidationContext *context,
989 GLenum textureTarget,
990 GLsizei width,
991 GLsizei height,
992 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400993 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400994 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400995 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400996 GLsizei imageSize)
997{
998 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
999 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1000 {
1001 // Checks are not required
1002 return true;
1003 }
1004
1005 // ...the data would be unpacked from the buffer object such that the memory reads required
1006 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -04001007 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
1008 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -04001009 const gl::Extents size(width, height, depth);
1010 const auto &unpack = context->getGLState().getUnpackState();
1011
1012 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1013 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1014 if (endByteOrErr.isError())
1015 {
1016 context->handleError(endByteOrErr.getError());
1017 return false;
1018 }
1019
1020 GLuint endByte = endByteOrErr.getResult();
1021
1022 if (pixelUnpackBuffer)
1023 {
1024 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1025 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1026 checkedEndByte += checkedOffset;
1027
1028 if (!checkedEndByte.IsValid() ||
1029 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1030 {
1031 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001032 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04001033 return false;
1034 }
1035 }
1036 else
1037 {
1038 ASSERT(imageSize >= 0);
1039 if (pixels == nullptr && imageSize != 0)
1040 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001041 context->handleError(InvalidOperation()
1042 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001043 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001044 }
1045
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001046 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001047 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001048 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001049 return false;
1050 }
1051 }
1052
1053 return true;
1054}
1055
Geoff Lang37dde692014-01-31 16:34:54 -05001056bool ValidQueryType(const Context *context, GLenum queryType)
1057{
He Yunchaoced53ae2016-11-29 15:00:51 +08001058 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1059 "GL extension enums not equal.");
1060 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1061 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001062
1063 switch (queryType)
1064 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001065 case GL_ANY_SAMPLES_PASSED:
1066 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1067 return true;
1068 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1069 return (context->getClientMajorVersion() >= 3);
1070 case GL_TIME_ELAPSED_EXT:
1071 return context->getExtensions().disjointTimerQuery;
1072 case GL_COMMANDS_COMPLETED_CHROMIUM:
1073 return context->getExtensions().syncQuery;
1074 default:
1075 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001076 }
1077}
1078
Geoff Lang2d62ab72017-03-23 16:54:40 -04001079bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
1080 GLenum type,
1081 GLboolean normalized,
1082 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001083 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001084 bool pureInteger)
1085{
1086 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001087 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1088 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1089 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1090 // parameter exceeds 255.
1091 constexpr GLsizei kMaxWebGLStride = 255;
1092 if (stride > kMaxWebGLStride)
1093 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001094 context->handleError(InvalidValue()
1095 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001096 return false;
1097 }
1098
1099 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1100 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1101 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1102 // or an INVALID_OPERATION error is generated.
1103 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1104 size_t typeSize = GetVertexFormatTypeSize(internalType);
1105
1106 ASSERT(isPow2(typeSize) && typeSize > 0);
1107 size_t sizeMask = (typeSize - 1);
1108 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1109 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001110 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001111 return false;
1112 }
1113
1114 if ((stride & sizeMask) != 0)
1115 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001116 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001117 return false;
1118 }
1119
1120 return true;
1121}
1122
Jamie Madillef300b12016-10-07 15:12:09 -04001123Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001124{
He Yunchaoced53ae2016-11-29 15:00:51 +08001125 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1126 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1127 // or program object and INVALID_OPERATION if the provided name identifies an object
1128 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001129
Dian Xiang769769a2015-09-09 15:20:08 -07001130 Program *validProgram = context->getProgram(id);
1131
1132 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001133 {
Dian Xiang769769a2015-09-09 15:20:08 -07001134 if (context->getShader(id))
1135 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001136 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001137 }
1138 else
1139 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001140 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001141 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001142 }
Dian Xiang769769a2015-09-09 15:20:08 -07001143
1144 return validProgram;
1145}
1146
Jamie Madillef300b12016-10-07 15:12:09 -04001147Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001148{
1149 // See ValidProgram for spec details.
1150
1151 Shader *validShader = context->getShader(id);
1152
1153 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001154 {
Dian Xiang769769a2015-09-09 15:20:08 -07001155 if (context->getProgram(id))
1156 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001157 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001158 }
1159 else
1160 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001161 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001162 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001163 }
Dian Xiang769769a2015-09-09 15:20:08 -07001164
1165 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001166}
1167
Geoff Langb1196682014-07-23 13:47:29 -04001168bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001169{
1170 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1171 {
1172 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1173
Geoff Langaae65a42014-05-26 12:43:44 -04001174 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001175 {
Martin Radevd178aa42017-07-13 14:03:22 +03001176 context->handleError(
1177 InvalidOperation()
1178 << "attachment index cannot be greater or equal to MAX_COLOR_ATTACHMENTS.");
Geoff Langb1196682014-07-23 13:47:29 -04001179 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001180 }
1181 }
1182 else
1183 {
1184 switch (attachment)
1185 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001186 case GL_DEPTH_ATTACHMENT:
1187 case GL_STENCIL_ATTACHMENT:
1188 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001189
He Yunchaoced53ae2016-11-29 15:00:51 +08001190 case GL_DEPTH_STENCIL_ATTACHMENT:
1191 if (!context->getExtensions().webglCompatibility &&
1192 context->getClientMajorVersion() < 3)
1193 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001194 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001195 return false;
1196 }
1197 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001198
He Yunchaoced53ae2016-11-29 15:00:51 +08001199 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001200 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001201 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001202 }
1203 }
1204
1205 return true;
1206}
1207
Jamie Madille8fb6402017-02-14 17:56:40 -05001208bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001209 GLenum target,
1210 GLsizei samples,
1211 GLenum internalformat,
1212 GLsizei width,
1213 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001214{
1215 switch (target)
1216 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001217 case GL_RENDERBUFFER:
1218 break;
1219 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001220 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001221 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001222 }
1223
1224 if (width < 0 || height < 0 || samples < 0)
1225 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001226 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001227 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001228 }
1229
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001230 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1231 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1232
1233 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001234 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001235 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001236 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001237 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001238 }
1239
1240 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1241 // 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 -08001242 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001243 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1244 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001245 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001246 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001247 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001248 }
1249
Geoff Langaae65a42014-05-26 12:43:44 -04001250 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001251 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001252 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001253 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001254 }
1255
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001256 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001257 if (handle == 0)
1258 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001259 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001260 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001261 }
1262
1263 return true;
1264}
1265
He Yunchaoced53ae2016-11-29 15:00:51 +08001266bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1267 GLenum target,
1268 GLenum attachment,
1269 GLenum renderbuffertarget,
1270 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001271{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001272 if (!ValidFramebufferTarget(target))
1273 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001274 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001275 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001276 }
1277
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001278 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001279
Jamie Madill84115c92015-04-23 15:00:07 -04001280 ASSERT(framebuffer);
1281 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001282 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001283 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001284 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001285 }
1286
Jamie Madillb4472272014-07-03 10:38:55 -04001287 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001288 {
Jamie Madillb4472272014-07-03 10:38:55 -04001289 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001290 }
1291
Jamie Madillab9d82c2014-01-21 16:38:14 -05001292 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1293 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1294 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1295 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1296 if (renderbuffer != 0)
1297 {
1298 if (!context->getRenderbuffer(renderbuffer))
1299 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001300 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001301 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001302 }
1303 }
1304
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001305 return true;
1306}
1307
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001308bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001309 GLint srcX0,
1310 GLint srcY0,
1311 GLint srcX1,
1312 GLint srcY1,
1313 GLint dstX0,
1314 GLint dstY0,
1315 GLint dstX1,
1316 GLint dstY1,
1317 GLbitfield mask,
1318 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001319{
1320 switch (filter)
1321 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001322 case GL_NEAREST:
1323 break;
1324 case GL_LINEAR:
1325 break;
1326 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001327 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001328 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001329 }
1330
1331 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1332 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001333 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001334 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001335 }
1336
1337 if (mask == 0)
1338 {
1339 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1340 // buffers are copied.
1341 return false;
1342 }
1343
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001344 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1345 // color buffer, leaving only nearest being unfiltered from above
1346 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1347 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001348 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001349 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001350 }
1351
Jamie Madill51f40ec2016-06-15 14:06:00 -04001352 const auto &glState = context->getGLState();
1353 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1354 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001355
1356 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001357 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001358 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001359 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001360 }
1361
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001362 if (readFramebuffer->id() == drawFramebuffer->id())
1363 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001364 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001365 return false;
1366 }
1367
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001368 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001369 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001370 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001371 return false;
1372 }
1373
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001374 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001375 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001376 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001377 return false;
1378 }
1379
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001380 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001381 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001382 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001383 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001384 }
1385
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001386 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1387
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001388 if (mask & GL_COLOR_BUFFER_BIT)
1389 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001390 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001391 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001392
He Yunchao66a41a22016-12-15 16:45:05 +08001393 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001394 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001395 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001396
Geoff Langa15472a2015-08-11 11:48:03 -04001397 for (size_t drawbufferIdx = 0;
1398 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001399 {
Geoff Langa15472a2015-08-11 11:48:03 -04001400 const FramebufferAttachment *attachment =
1401 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1402 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001403 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001404 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001405
Geoff Langb2f3d052013-08-13 12:49:27 -04001406 // The GL ES 3.0.2 spec (pg 193) states that:
1407 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001408 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1409 // as well
1410 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1411 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001412 // Changes with EXT_color_buffer_float:
1413 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001414 GLenum readComponentType = readFormat.info->componentType;
1415 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001416 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001417 readComponentType == GL_SIGNED_NORMALIZED);
1418 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1419 drawComponentType == GL_SIGNED_NORMALIZED);
1420
1421 if (extensions.colorBufferFloat)
1422 {
1423 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1424 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1425
1426 if (readFixedOrFloat != drawFixedOrFloat)
1427 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001428 context->handleError(InvalidOperation()
1429 << "If the read buffer contains fixed-point or "
1430 "floating-point values, the draw buffer must "
1431 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001432 return false;
1433 }
1434 }
1435 else if (readFixedPoint != drawFixedPoint)
1436 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001437 context->handleError(InvalidOperation()
1438 << "If the read buffer contains fixed-point values, "
1439 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001440 return false;
1441 }
1442
1443 if (readComponentType == GL_UNSIGNED_INT &&
1444 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001445 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001446 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001447 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001448 }
1449
Jamie Madill6163c752015-12-07 16:32:59 -05001450 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001451 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001452 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001453 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001454 }
1455
Jamie Madilla3944d42016-07-22 22:13:26 -04001456 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001457 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001458 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001459 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001460 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001461 }
Geoff Lange4915782017-04-12 15:19:07 -04001462
1463 if (context->getExtensions().webglCompatibility &&
1464 *readColorBuffer == *attachment)
1465 {
1466 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001467 InvalidOperation()
1468 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001469 return false;
1470 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001471 }
1472 }
1473
Jamie Madilla3944d42016-07-22 22:13:26 -04001474 if ((readFormat.info->componentType == GL_INT ||
1475 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1476 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001477 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001478 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001479 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001480 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001481 }
He Yunchao66a41a22016-12-15 16:45:05 +08001482 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1483 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1484 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1485 // situation is an application error that would lead to a crash in ANGLE.
1486 else if (drawFramebuffer->hasEnabledDrawBuffer())
1487 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001488 context->handleError(
1489 InvalidOperation()
1490 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001491 return false;
1492 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001493 }
1494
He Yunchaoced53ae2016-11-29 15:00:51 +08001495 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001496 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1497 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001498 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001499 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001500 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001501 const gl::FramebufferAttachment *readBuffer =
1502 readFramebuffer->getAttachment(attachments[i]);
1503 const gl::FramebufferAttachment *drawBuffer =
1504 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001505
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001506 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001507 {
Kenneth Russell69382852017-07-21 16:38:44 -04001508 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001509 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001510 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001511 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001512 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001513
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001514 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001515 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001516 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001517 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001518 }
Geoff Lange4915782017-04-12 15:19:07 -04001519
1520 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1521 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001522 context->handleError(
1523 InvalidOperation()
1524 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001525 return false;
1526 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001527 }
He Yunchao66a41a22016-12-15 16:45:05 +08001528 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1529 else if (drawBuffer)
1530 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001531 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1532 "depth/stencil attachment of a "
1533 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001534 return false;
1535 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001536 }
1537 }
1538
Martin Radeva3ed4572017-07-27 18:29:37 +03001539 // ANGLE_multiview, Revision 1:
1540 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1541 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1542 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1543 {
1544 context->handleError(InvalidFramebufferOperation()
1545 << "Attempt to read from a multi-view framebuffer.");
1546 return false;
1547 }
1548 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1549 {
1550 context->handleError(InvalidFramebufferOperation()
1551 << "Attempt to write to a multi-view framebuffer.");
1552 return false;
1553 }
1554
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001555 return true;
1556}
1557
Jamie Madill4928b7c2017-06-20 12:57:39 -04001558bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001559 GLint x,
1560 GLint y,
1561 GLsizei width,
1562 GLsizei height,
1563 GLenum format,
1564 GLenum type,
1565 GLsizei bufSize,
1566 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001567 GLsizei *columns,
1568 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001569 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001570{
1571 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001572 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001573 return false;
1574 }
1575
Geoff Lang62fce5b2016-09-30 10:46:35 -04001576 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001577 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001578 {
Geoff Langb1196682014-07-23 13:47:29 -04001579 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001580 }
1581
Geoff Lang62fce5b2016-09-30 10:46:35 -04001582 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001583 {
Geoff Langb1196682014-07-23 13:47:29 -04001584 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001585 }
1586
Jamie Madillc29968b2016-01-20 11:17:23 -05001587 return true;
1588}
1589
1590bool ValidateReadnPixelsEXT(Context *context,
1591 GLint x,
1592 GLint y,
1593 GLsizei width,
1594 GLsizei height,
1595 GLenum format,
1596 GLenum type,
1597 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001598 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001599{
1600 if (bufSize < 0)
1601 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001602 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001603 return false;
1604 }
1605
Geoff Lang62fce5b2016-09-30 10:46:35 -04001606 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001607 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001608}
Jamie Madill26e91952014-03-05 15:01:27 -05001609
Jamie Madill4928b7c2017-06-20 12:57:39 -04001610bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001611 GLint x,
1612 GLint y,
1613 GLsizei width,
1614 GLsizei height,
1615 GLenum format,
1616 GLenum type,
1617 GLsizei bufSize,
1618 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001619 GLsizei *columns,
1620 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001621 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001622{
1623 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001624 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001625 return false;
1626 }
1627
Geoff Lange93daba2017-03-30 13:54:40 -04001628 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1629 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001630 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001631 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001632 }
1633
Geoff Lang62fce5b2016-09-30 10:46:35 -04001634 if (!ValidateRobustBufferSize(context, bufSize, *length))
1635 {
1636 return false;
1637 }
1638
1639 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001640}
1641
Jamie Madillf0e04492017-08-26 15:28:42 -04001642bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001643{
1644 if (!context->getExtensions().occlusionQueryBoolean &&
1645 !context->getExtensions().disjointTimerQuery)
1646 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001647 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001648 return false;
1649 }
1650
Olli Etuaho41997e72016-03-10 13:38:39 +02001651 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001652}
1653
Jamie Madillf0e04492017-08-26 15:28:42 -04001654bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001655{
1656 if (!context->getExtensions().occlusionQueryBoolean &&
1657 !context->getExtensions().disjointTimerQuery)
1658 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001659 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001660 return false;
1661 }
1662
Olli Etuaho41997e72016-03-10 13:38:39 +02001663 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001664}
1665
Jamie Madillf0e04492017-08-26 15:28:42 -04001666bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1667{
1668 if (!context->getExtensions().occlusionQueryBoolean &&
1669 !context->getExtensions().disjointTimerQuery)
1670 {
1671 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1672 return false;
1673 }
1674
1675 return true;
1676}
1677
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001678bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001679{
1680 if (!ValidQueryType(context, target))
1681 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001682 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001683 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001684 }
1685
1686 if (id == 0)
1687 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001688 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001689 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001690 }
1691
1692 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1693 // of zero, if the active query object name for <target> is non-zero (for the
1694 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1695 // the active query for either target is non-zero), if <id> is the name of an
1696 // existing query object whose type does not match <target>, or if <id> is the
1697 // active query object name for any query type, the error INVALID_OPERATION is
1698 // generated.
1699
1700 // Ensure no other queries are active
1701 // NOTE: If other queries than occlusion are supported, we will need to check
1702 // separately that:
1703 // a) The query ID passed is not the current active query for any target/type
1704 // b) There are no active queries for the requested target (and in the case
1705 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1706 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001707
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001708 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001709 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001710 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001711 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001712 }
1713
1714 Query *queryObject = context->getQuery(id, true, target);
1715
1716 // check that name was obtained with glGenQueries
1717 if (!queryObject)
1718 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001719 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001720 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001721 }
1722
1723 // check for type mismatch
1724 if (queryObject->getType() != target)
1725 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001726 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001727 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001728 }
1729
1730 return true;
1731}
1732
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001733bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1734{
1735 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001736 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001737 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001738 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001739 return false;
1740 }
1741
1742 return ValidateBeginQueryBase(context, target, id);
1743}
1744
1745bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001746{
1747 if (!ValidQueryType(context, target))
1748 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001749 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001750 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001751 }
1752
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001753 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001754
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001755 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001756 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001757 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001758 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001759 }
1760
Jamie Madill45c785d2014-05-13 14:09:34 -04001761 return true;
1762}
1763
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001764bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1765{
1766 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001767 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001768 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001769 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001770 return false;
1771 }
1772
1773 return ValidateEndQueryBase(context, target);
1774}
1775
1776bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1777{
1778 if (!context->getExtensions().disjointTimerQuery)
1779 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001780 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001781 return false;
1782 }
1783
1784 if (target != GL_TIMESTAMP_EXT)
1785 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001786 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001787 return false;
1788 }
1789
1790 Query *queryObject = context->getQuery(id, true, target);
1791 if (queryObject == nullptr)
1792 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001793 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001794 return false;
1795 }
1796
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001797 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001798 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001799 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001800 return false;
1801 }
1802
1803 return true;
1804}
1805
Geoff Lang2186c382016-10-14 10:54:54 -04001806bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001807{
Geoff Lang2186c382016-10-14 10:54:54 -04001808 if (numParams)
1809 {
1810 *numParams = 0;
1811 }
1812
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001813 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1814 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001815 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001816 return false;
1817 }
1818
1819 switch (pname)
1820 {
1821 case GL_CURRENT_QUERY_EXT:
1822 if (target == GL_TIMESTAMP_EXT)
1823 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001824 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001825 return false;
1826 }
1827 break;
1828 case GL_QUERY_COUNTER_BITS_EXT:
1829 if (!context->getExtensions().disjointTimerQuery ||
1830 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1831 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001832 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001833 return false;
1834 }
1835 break;
1836 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001837 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001838 return false;
1839 }
1840
Geoff Lang2186c382016-10-14 10:54:54 -04001841 if (numParams)
1842 {
1843 // All queries return only one value
1844 *numParams = 1;
1845 }
1846
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001847 return true;
1848}
1849
1850bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1851{
1852 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001853 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001854 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001855 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001856 return false;
1857 }
1858
Geoff Lang2186c382016-10-14 10:54:54 -04001859 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001860}
1861
Geoff Lang2186c382016-10-14 10:54:54 -04001862bool ValidateGetQueryivRobustANGLE(Context *context,
1863 GLenum target,
1864 GLenum pname,
1865 GLsizei bufSize,
1866 GLsizei *length,
1867 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001868{
Geoff Lang2186c382016-10-14 10:54:54 -04001869 if (!ValidateRobustEntryPoint(context, bufSize))
1870 {
1871 return false;
1872 }
1873
1874 if (!ValidateGetQueryivBase(context, target, pname, length))
1875 {
1876 return false;
1877 }
1878
1879 if (!ValidateRobustBufferSize(context, bufSize, *length))
1880 {
1881 return false;
1882 }
1883
1884 return true;
1885}
1886
1887bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1888{
1889 if (numParams)
1890 {
1891 *numParams = 0;
1892 }
1893
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001894 Query *queryObject = context->getQuery(id, false, GL_NONE);
1895
1896 if (!queryObject)
1897 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001898 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001899 return false;
1900 }
1901
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001902 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001903 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001904 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001905 return false;
1906 }
1907
1908 switch (pname)
1909 {
1910 case GL_QUERY_RESULT_EXT:
1911 case GL_QUERY_RESULT_AVAILABLE_EXT:
1912 break;
1913
1914 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001915 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001916 return false;
1917 }
1918
Geoff Lang2186c382016-10-14 10:54:54 -04001919 if (numParams)
1920 {
1921 *numParams = 1;
1922 }
1923
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001924 return true;
1925}
1926
1927bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1928{
1929 if (!context->getExtensions().disjointTimerQuery)
1930 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001931 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001932 return false;
1933 }
Geoff Lang2186c382016-10-14 10:54:54 -04001934 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1935}
1936
1937bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1938 GLuint id,
1939 GLenum pname,
1940 GLsizei bufSize,
1941 GLsizei *length,
1942 GLint *params)
1943{
1944 if (!context->getExtensions().disjointTimerQuery)
1945 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001946 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001947 return false;
1948 }
1949
1950 if (!ValidateRobustEntryPoint(context, bufSize))
1951 {
1952 return false;
1953 }
1954
1955 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1956 {
1957 return false;
1958 }
1959
1960 if (!ValidateRobustBufferSize(context, bufSize, *length))
1961 {
1962 return false;
1963 }
1964
1965 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001966}
1967
1968bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1969{
1970 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001971 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001972 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001973 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001974 return false;
1975 }
Geoff Lang2186c382016-10-14 10:54:54 -04001976 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1977}
1978
1979bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1980 GLuint id,
1981 GLenum pname,
1982 GLsizei bufSize,
1983 GLsizei *length,
1984 GLuint *params)
1985{
1986 if (!context->getExtensions().disjointTimerQuery &&
1987 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1988 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001989 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001990 return false;
1991 }
1992
1993 if (!ValidateRobustEntryPoint(context, bufSize))
1994 {
1995 return false;
1996 }
1997
1998 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1999 {
2000 return false;
2001 }
2002
2003 if (!ValidateRobustBufferSize(context, bufSize, *length))
2004 {
2005 return false;
2006 }
2007
2008 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002009}
2010
2011bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2012{
2013 if (!context->getExtensions().disjointTimerQuery)
2014 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002015 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002016 return false;
2017 }
Geoff Lang2186c382016-10-14 10:54:54 -04002018 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2019}
2020
2021bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2022 GLuint id,
2023 GLenum pname,
2024 GLsizei bufSize,
2025 GLsizei *length,
2026 GLint64 *params)
2027{
2028 if (!context->getExtensions().disjointTimerQuery)
2029 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002030 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002031 return false;
2032 }
2033
2034 if (!ValidateRobustEntryPoint(context, bufSize))
2035 {
2036 return false;
2037 }
2038
2039 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2040 {
2041 return false;
2042 }
2043
2044 if (!ValidateRobustBufferSize(context, bufSize, *length))
2045 {
2046 return false;
2047 }
2048
2049 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002050}
2051
2052bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2053{
2054 if (!context->getExtensions().disjointTimerQuery)
2055 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002056 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002057 return false;
2058 }
Geoff Lang2186c382016-10-14 10:54:54 -04002059 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2060}
2061
2062bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2063 GLuint id,
2064 GLenum pname,
2065 GLsizei bufSize,
2066 GLsizei *length,
2067 GLuint64 *params)
2068{
2069 if (!context->getExtensions().disjointTimerQuery)
2070 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002071 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002072 return false;
2073 }
2074
2075 if (!ValidateRobustEntryPoint(context, bufSize))
2076 {
2077 return false;
2078 }
2079
2080 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2081 {
2082 return false;
2083 }
2084
2085 if (!ValidateRobustBufferSize(context, bufSize, *length))
2086 {
2087 return false;
2088 }
2089
2090 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002091}
2092
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002093bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002094 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002095 GLuint program,
2096 GLint location,
2097 GLsizei count)
2098{
2099 // Check for ES31 program uniform entry points
2100 if (context->getClientVersion() < Version(3, 1))
2101 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002102 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002103 return false;
2104 }
2105
2106 const LinkedUniform *uniform = nullptr;
2107 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002108 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2109 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002110}
2111
Frank Henigmana98a6472017-02-02 21:38:32 -05002112bool ValidateProgramUniform1iv(gl::Context *context,
2113 GLuint program,
2114 GLint location,
2115 GLsizei count,
2116 const GLint *value)
2117{
2118 // Check for ES31 program uniform entry points
2119 if (context->getClientVersion() < Version(3, 1))
2120 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002121 context->handleError(InvalidOperation());
Frank Henigmana98a6472017-02-02 21:38:32 -05002122 return false;
2123 }
2124
2125 const LinkedUniform *uniform = nullptr;
2126 gl::Program *programObject = GetValidProgram(context, program);
2127 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2128 ValidateUniform1ivValue(context, uniform->type, count, value);
2129}
2130
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002131bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002132 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002133 GLuint program,
2134 GLint location,
2135 GLsizei count,
2136 GLboolean transpose)
2137{
2138 // Check for ES31 program uniform entry points
2139 if (context->getClientVersion() < Version(3, 1))
2140 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002141 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002142 return false;
2143 }
2144
2145 const LinkedUniform *uniform = nullptr;
2146 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002147 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2148 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002149}
2150
Jamie Madillc1d770e2017-04-13 17:31:24 -04002151bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002152{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002153 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002154 gl::Program *programObject = context->getGLState().getProgram();
2155 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2156 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002157}
2158
Jamie Madillbe849e42017-05-02 15:49:00 -04002159bool ValidateUniform1iv(ValidationContext *context,
2160 GLint location,
2161 GLsizei count,
2162 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002163{
2164 const LinkedUniform *uniform = nullptr;
2165 gl::Program *programObject = context->getGLState().getProgram();
2166 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2167 ValidateUniform1ivValue(context, uniform->type, count, value);
2168}
2169
Jamie Madillc1d770e2017-04-13 17:31:24 -04002170bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002171 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002172 GLint location,
2173 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002174 GLboolean transpose)
2175{
Martin Radev1be913c2016-07-11 17:59:16 +03002176 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002177 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002178 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002179 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002180 }
2181
Jamie Madill62d31cb2015-09-11 13:25:51 -04002182 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002183 gl::Program *programObject = context->getGLState().getProgram();
2184 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2185 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002186}
2187
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002188bool ValidateStateQuery(ValidationContext *context,
2189 GLenum pname,
2190 GLenum *nativeType,
2191 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002192{
2193 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2194 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002195 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002196 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002197 }
2198
Jamie Madill0af26e12015-03-05 19:54:33 -05002199 const Caps &caps = context->getCaps();
2200
Jamie Madill893ab082014-05-16 16:56:10 -04002201 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2202 {
2203 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2204
Jamie Madill0af26e12015-03-05 19:54:33 -05002205 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002206 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002207 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002208 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002209 }
2210 }
2211
2212 switch (pname)
2213 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002214 case GL_TEXTURE_BINDING_2D:
2215 case GL_TEXTURE_BINDING_CUBE_MAP:
2216 case GL_TEXTURE_BINDING_3D:
2217 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002218 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002219 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002220 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2221 if (!context->getExtensions().textureRectangle)
2222 {
2223 context->handleError(InvalidEnum()
2224 << "ANGLE_texture_rectangle extension not present");
2225 return false;
2226 }
2227 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002228 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2229 if (!context->getExtensions().eglStreamConsumerExternal &&
2230 !context->getExtensions().eglImageExternal)
2231 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002232 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2233 "nor GL_OES_EGL_image_external "
2234 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002235 return false;
2236 }
2237 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002238
He Yunchaoced53ae2016-11-29 15:00:51 +08002239 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2240 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002241 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002242 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2243 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002244 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002245 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002246 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002247 }
2248
Jamie Madill51f40ec2016-06-15 14:06:00 -04002249 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2250 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002251
2252 if (framebuffer->getReadBufferState() == GL_NONE)
2253 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002254 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002255 return false;
2256 }
2257
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002258 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002259 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002260 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002261 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002262 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002263 }
2264 }
2265 break;
2266
He Yunchaoced53ae2016-11-29 15:00:51 +08002267 default:
2268 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002269 }
2270
2271 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002272 if (*numParams == 0)
2273 {
2274 return false;
2275 }
2276
2277 return true;
2278}
2279
2280bool ValidateRobustStateQuery(ValidationContext *context,
2281 GLenum pname,
2282 GLsizei bufSize,
2283 GLenum *nativeType,
2284 unsigned int *numParams)
2285{
2286 if (!ValidateRobustEntryPoint(context, bufSize))
2287 {
2288 return false;
2289 }
2290
2291 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2292 {
2293 return false;
2294 }
2295
2296 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002297 {
2298 return false;
2299 }
2300
2301 return true;
2302}
2303
Jamie Madillc29968b2016-01-20 11:17:23 -05002304bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2305 GLenum target,
2306 GLint level,
2307 GLenum internalformat,
2308 bool isSubImage,
2309 GLint xoffset,
2310 GLint yoffset,
2311 GLint zoffset,
2312 GLint x,
2313 GLint y,
2314 GLsizei width,
2315 GLsizei height,
2316 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002317 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002318{
Brandon Jones6cad5662017-06-14 13:25:13 -07002319 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002320 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002321 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2322 return false;
2323 }
2324
2325 if (width < 0 || height < 0)
2326 {
2327 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002328 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002329 }
2330
He Yunchaoced53ae2016-11-29 15:00:51 +08002331 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2332 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002333 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002334 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002335 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002336 }
2337
2338 if (border != 0)
2339 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002340 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002341 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002342 }
2343
2344 if (!ValidMipLevel(context, target, level))
2345 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002346 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002347 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002348 }
2349
Jamie Madill51f40ec2016-06-15 14:06:00 -04002350 const auto &state = context->getGLState();
2351 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002352 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002353 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002354 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002355 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002356 }
2357
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002358 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002359 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002360 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002361 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002362 }
2363
Martin Radev138064f2016-07-15 12:03:41 +03002364 if (readFramebuffer->getReadBufferState() == GL_NONE)
2365 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002366 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002367 return false;
2368 }
2369
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002370 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2371 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002372 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002373 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002374 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2375 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002376 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002377 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002378 return false;
2379 }
2380
Martin Radev04e2c3b2017-07-27 16:54:35 +03002381 // ANGLE_multiview spec, Revision 1:
2382 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2383 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2384 // is not NONE.
2385 if (source->getMultiviewLayout() != GL_NONE)
2386 {
2387 context->handleError(InvalidFramebufferOperation()
2388 << "The active read framebuffer object has multiview attachments.");
2389 return false;
2390 }
2391
Geoff Langaae65a42014-05-26 12:43:44 -04002392 const gl::Caps &caps = context->getCaps();
2393
Geoff Langaae65a42014-05-26 12:43:44 -04002394 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002395 switch (target)
2396 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002397 case GL_TEXTURE_2D:
2398 maxDimension = caps.max2DTextureSize;
2399 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002400
He Yunchaoced53ae2016-11-29 15:00:51 +08002401 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2402 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2403 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2404 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2405 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2406 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2407 maxDimension = caps.maxCubeMapTextureSize;
2408 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002409
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002410 case GL_TEXTURE_RECTANGLE_ANGLE:
2411 maxDimension = caps.maxRectangleTextureSize;
2412 break;
2413
He Yunchaoced53ae2016-11-29 15:00:51 +08002414 case GL_TEXTURE_2D_ARRAY:
2415 maxDimension = caps.max2DTextureSize;
2416 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002417
He Yunchaoced53ae2016-11-29 15:00:51 +08002418 case GL_TEXTURE_3D:
2419 maxDimension = caps.max3DTextureSize;
2420 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002421
He Yunchaoced53ae2016-11-29 15:00:51 +08002422 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002423 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002424 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002425 }
2426
Jamie Madillc29968b2016-01-20 11:17:23 -05002427 gl::Texture *texture =
2428 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002429 if (!texture)
2430 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002431 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002432 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002433 }
2434
Geoff Lang69cce582015-09-17 13:20:36 -04002435 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002436 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002437 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002438 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002439 }
2440
Geoff Langca271392017-04-05 12:30:00 -04002441 const gl::InternalFormat &formatInfo =
2442 gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002443
Geoff Lang966c9402017-04-18 12:38:27 -04002444 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002445 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002446 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002447 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002448 }
2449
2450 if (isSubImage)
2451 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002452 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2453 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2454 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002455 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002456 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002457 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002458 }
2459 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002460 else
2461 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002462 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002463 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002464 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002465 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002466 }
2467
Geoff Langeb66a6e2016-10-31 13:06:12 -04002468 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002469 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002470 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002471 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002472 }
2473
2474 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002475 if (static_cast<int>(width) > maxLevelDimension ||
2476 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002477 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002478 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002479 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002480 }
2481 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002482
Jamie Madill0c8abca2016-07-22 20:21:26 -04002483 if (textureFormatOut)
2484 {
2485 *textureFormatOut = texture->getFormat(target, level);
2486 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002487
2488 // Detect texture copying feedback loops for WebGL.
2489 if (context->getExtensions().webglCompatibility)
2490 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002491 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002492 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002493 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002494 return false;
2495 }
2496 }
2497
Jamie Madill560a8d82014-05-21 13:06:20 -04002498 return true;
2499}
2500
Jiajia Qind9671222016-11-29 16:30:31 +08002501bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002502{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002503 switch (mode)
2504 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002505 case GL_POINTS:
2506 case GL_LINES:
2507 case GL_LINE_LOOP:
2508 case GL_LINE_STRIP:
2509 case GL_TRIANGLES:
2510 case GL_TRIANGLE_STRIP:
2511 case GL_TRIANGLE_FAN:
2512 break;
2513 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002514 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002515 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002516 }
2517
Jamie Madill250d33f2014-06-06 17:09:03 -04002518 if (count < 0)
2519 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002520 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002521 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002522 }
2523
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002524 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002525
Jamie Madill250d33f2014-06-06 17:09:03 -04002526 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002527 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002528 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002529 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002530 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002531 }
2532
Jamie Madillcbcde722017-01-06 14:50:00 -05002533 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2534 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002535 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002536 const Extensions &extensions = context->getExtensions();
2537 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002538 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002539 const FramebufferAttachment *dsAttachment =
2540 framebuffer->getStencilOrDepthStencilAttachment();
2541 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002542 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002543 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002544
2545 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2546 bool differentWritemasks =
2547 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2548 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2549 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2550 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2551
2552 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002553 {
Martin Radevffe754b2017-07-31 10:38:07 +03002554 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002555 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002556 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2557 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002558 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002559 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002560 return false;
2561 }
Jamie Madillac528012014-06-20 13:21:23 -04002562 }
2563
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002564 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002565 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002566 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002567 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002568 }
2569
Geoff Lang7dd2e102014-11-10 15:19:26 -05002570 gl::Program *program = state.getProgram();
2571 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002572 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002573 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002574 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002575 }
2576
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002577 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002578 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002579 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002580 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002581 }
2582
Martin Radevffe754b2017-07-31 10:38:07 +03002583 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002584 {
Martin Radevda8e2572017-09-12 17:21:16 +03002585 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002586 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002587 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002588 {
2589 context->handleError(InvalidOperation() << "The number of views in the active program "
2590 "and draw framebuffer does not match.");
2591 return false;
2592 }
Martin Radev7e69f762017-07-27 14:54:13 +03002593
2594 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2595 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2596 framebufferNumViews > 1)
2597 {
2598 context->handleError(InvalidOperation()
2599 << "There is an active transform feedback object "
2600 "when the number of views in the active draw "
2601 "framebuffer is greater than 1.");
2602 return false;
2603 }
Martin Radevffe754b2017-07-31 10:38:07 +03002604
2605 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2606 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2607 {
2608 context->handleError(InvalidOperation() << "There is an active query for target "
2609 "GL_TIME_ELAPSED_EXT when the number of "
2610 "views in the active draw framebuffer is "
2611 "greater than 1.");
2612 return false;
2613 }
Martin Radev7cf61662017-07-26 17:10:53 +03002614 }
2615
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002616 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002617 for (unsigned int uniformBlockIndex = 0;
2618 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002619 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002620 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002621 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002622 const OffsetBindingPointer<Buffer> &uniformBuffer =
2623 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002624
Geoff Lang5d124a62015-09-15 13:03:27 -04002625 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002626 {
2627 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002628 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002629 InvalidOperation()
2630 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002631 return false;
2632 }
2633
Geoff Lang5d124a62015-09-15 13:03:27 -04002634 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002635 if (uniformBufferSize == 0)
2636 {
2637 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002638 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002639 }
2640
Jamie Madill62d31cb2015-09-11 13:25:51 -04002641 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002642 {
2643 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002644 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002645 InvalidOperation()
2646 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002647 return false;
2648 }
2649 }
2650
Geoff Lange0cff192017-05-30 13:04:56 -04002651 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002652 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002653 {
Geoff Lange0cff192017-05-30 13:04:56 -04002654 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002655 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2656 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002657 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002658 return false;
2659 }
Geoff Lange0cff192017-05-30 13:04:56 -04002660
Geoff Lang9ab5b822017-05-30 16:19:23 -04002661 // Detect that the vertex shader input types match the attribute types
2662 if (!ValidateVertexShaderAttributeTypeMatch(context))
2663 {
2664 return false;
2665 }
2666
Geoff Lange0cff192017-05-30 13:04:56 -04002667 // Detect that the color buffer types match the fragment shader output types
2668 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2669 {
2670 return false;
2671 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002672 }
2673
Jamie Madill250d33f2014-06-06 17:09:03 -04002674 // No-op if zero count
2675 return (count > 0);
2676}
2677
Jamie Madillc1d770e2017-04-13 17:31:24 -04002678bool ValidateDrawArraysCommon(ValidationContext *context,
2679 GLenum mode,
2680 GLint first,
2681 GLsizei count,
2682 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002683{
Jamie Madillfd716582014-06-06 17:09:04 -04002684 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002685 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002686 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002687 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002688 }
2689
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002690 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002691 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002692 if (curTransformFeedback && curTransformFeedback->isActive() &&
2693 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002694 {
2695 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002696 // that does not match the current transform feedback object's draw mode (if transform
2697 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002698 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002699 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002700 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002701 }
2702
Jiajia Qind9671222016-11-29 16:30:31 +08002703 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002704 {
2705 return false;
2706 }
2707
Corentin Wallez71168a02016-12-19 15:11:18 -08002708 // Check the computation of maxVertex doesn't overflow.
2709 // - first < 0 or count < 0 have been checked as an error condition
2710 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2711 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2712 ASSERT(count > 0 && first >= 0);
2713 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2714 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002715 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002716 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002717 return false;
2718 }
2719
Corentin Wallez71168a02016-12-19 15:11:18 -08002720 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002721 {
2722 return false;
2723 }
2724
2725 return true;
2726}
2727
He Yunchaoced53ae2016-11-29 15:00:51 +08002728bool ValidateDrawArraysInstancedANGLE(Context *context,
2729 GLenum mode,
2730 GLint first,
2731 GLsizei count,
2732 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002733{
Corentin Wallez170efbf2017-05-02 13:45:01 -04002734 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002735 {
2736 return false;
2737 }
2738
Corentin Wallez0dc97812017-06-22 14:38:44 -04002739 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002740}
2741
Jiajia Qind9671222016-11-29 16:30:31 +08002742bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002743{
Jamie Madill250d33f2014-06-06 17:09:03 -04002744 switch (type)
2745 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002746 case GL_UNSIGNED_BYTE:
2747 case GL_UNSIGNED_SHORT:
2748 break;
2749 case GL_UNSIGNED_INT:
2750 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2751 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002752 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002753 return false;
2754 }
2755 break;
2756 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002757 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002758 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002759 }
2760
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002761 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002762
2763 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002764 if (curTransformFeedback && curTransformFeedback->isActive() &&
2765 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002766 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002767 // It is an invalid operation to call DrawElements, DrawRangeElements or
2768 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002769 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002770 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002771 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002772 }
2773
Jiajia Qind9671222016-11-29 16:30:31 +08002774 return true;
2775}
2776
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002777bool ValidateDrawElementsCommon(ValidationContext *context,
2778 GLenum mode,
2779 GLsizei count,
2780 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002781 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002782 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002783{
2784 if (!ValidateDrawElementsBase(context, type))
2785 return false;
2786
2787 const State &state = context->getGLState();
2788
Corentin Wallez170efbf2017-05-02 13:45:01 -04002789 if (!ValidateDrawBase(context, mode, count))
2790 {
2791 return false;
2792 }
2793
Jamie Madill250d33f2014-06-06 17:09:03 -04002794 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002795 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002796 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002797 context->handleError(InvalidOperation() << "Index buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -04002798 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002799 }
2800
He Yunchaoced53ae2016-11-29 15:00:51 +08002801 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002802 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002803
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002804 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2805
2806 if (context->getExtensions().webglCompatibility)
2807 {
2808 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2809 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2810 {
2811 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2812 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2813 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002814 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002815 return false;
2816 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002817
2818 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2819 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2820 // error is generated.
2821 if (reinterpret_cast<intptr_t>(indices) < 0)
2822 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002823 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002824 return false;
2825 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002826 }
2827
2828 if (context->getExtensions().webglCompatibility ||
2829 !context->getGLState().areClientArraysEnabled())
2830 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002831 if (!elementArrayBuffer && count > 0)
2832 {
2833 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2834 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2835 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002836 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002837 return false;
2838 }
2839 }
2840
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002841 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002842 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002843 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002844 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002845 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2846 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2847 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2848 constexpr uint64_t kMaxTypeSize = 8;
2849 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2850 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2851 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002852
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002853 uint64_t typeSize = typeBytes;
2854 uint64_t elementCount = static_cast<uint64_t>(count);
2855 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2856
2857 // Doing the multiplication here is overflow-safe
2858 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2859
2860 // The offset can be any value, check for overflows
2861 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2862 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002863 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002864 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002865 return false;
2866 }
2867
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002868 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2869 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002870 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002871 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002872 return false;
2873 }
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002874
Corentin Wallez487653b2017-09-01 17:17:55 -04002875 ASSERT(isPow2(typeSize) && typeSize > 0);
2876 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002877 {
2878 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
2879 return false;
2880 }
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002881 }
2882 else if (!indices)
2883 {
2884 // This is an application error that would normally result in a crash,
2885 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002886 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04002887 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002888 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002889 }
2890
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002891 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002892 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002893 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2894 // access is enabled.
2895 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2896 {
2897 return false;
2898 }
2899 }
2900 else
2901 {
2902 // Use the parameter buffer to retrieve and cache the index range.
2903 const auto &params = context->getParams<HasIndexRange>();
2904 const auto &indexRangeOpt = params.getIndexRange();
2905 if (!indexRangeOpt.valid())
2906 {
2907 // Unexpected error.
2908 return false;
2909 }
2910
2911 // If we use an index greater than our maximum supported index range, return an error.
2912 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2913 // return an error if possible here.
2914 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2915 {
2916 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2917 return false;
2918 }
2919
2920 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2921 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2922 {
2923 return false;
2924 }
2925
2926 // No op if there are no real indices in the index data (all are primitive restart).
2927 return (indexRangeOpt.value().vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002928 }
2929
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002930 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002931}
2932
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002933bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2934 GLenum mode,
2935 GLsizei count,
2936 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002937 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002938 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002939{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002940 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002941}
2942
Geoff Lang3edfe032015-09-04 16:38:24 -04002943bool ValidateDrawElementsInstancedANGLE(Context *context,
2944 GLenum mode,
2945 GLsizei count,
2946 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002947 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002948 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002949{
Corentin Wallez170efbf2017-05-02 13:45:01 -04002950 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002951 {
2952 return false;
2953 }
2954
Corentin Wallez0dc97812017-06-22 14:38:44 -04002955 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002956}
2957
He Yunchaoced53ae2016-11-29 15:00:51 +08002958bool ValidateFramebufferTextureBase(Context *context,
2959 GLenum target,
2960 GLenum attachment,
2961 GLuint texture,
2962 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002963{
Jamie Madill55ec3b12014-07-03 10:38:57 -04002964 if (!ValidFramebufferTarget(target))
2965 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002966 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002967 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002968 }
2969
2970 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002971 {
2972 return false;
2973 }
2974
Jamie Madill55ec3b12014-07-03 10:38:57 -04002975 if (texture != 0)
2976 {
2977 gl::Texture *tex = context->getTexture(texture);
2978
Jamie Madillbe849e42017-05-02 15:49:00 -04002979 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002980 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002981 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002982 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002983 }
2984
2985 if (level < 0)
2986 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002987 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002988 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002989 }
2990 }
2991
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002992 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002993 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002994
Jamie Madill84115c92015-04-23 15:00:07 -04002995 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002996 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002997 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002998 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002999 }
3000
3001 return true;
3002}
3003
Geoff Langb1196682014-07-23 13:47:29 -04003004bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003005{
3006 if (program == 0)
3007 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003008 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003009 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003010 }
3011
Dian Xiang769769a2015-09-09 15:20:08 -07003012 gl::Program *programObject = GetValidProgram(context, program);
3013 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003014 {
3015 return false;
3016 }
3017
Jamie Madill0063c512014-08-25 15:47:53 -04003018 if (!programObject || !programObject->isLinked())
3019 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003020 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003021 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003022 }
3023
Geoff Lang7dd2e102014-11-10 15:19:26 -05003024 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003025 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003026 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003027 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003028 }
3029
Jamie Madill0063c512014-08-25 15:47:53 -04003030 return true;
3031}
3032
Geoff Langf41d0ee2016-10-07 13:04:23 -04003033static bool ValidateSizedGetUniform(Context *context,
3034 GLuint program,
3035 GLint location,
3036 GLsizei bufSize,
3037 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003038{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003039 if (length)
3040 {
3041 *length = 0;
3042 }
3043
Jamie Madill78f41802014-08-25 15:47:55 -04003044 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003045 {
Jamie Madill78f41802014-08-25 15:47:55 -04003046 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003047 }
3048
Geoff Langf41d0ee2016-10-07 13:04:23 -04003049 if (bufSize < 0)
3050 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003051 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003052 return false;
3053 }
3054
Jamie Madilla502c742014-08-28 17:19:13 -04003055 gl::Program *programObject = context->getProgram(program);
3056 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003057
Jamie Madill78f41802014-08-25 15:47:55 -04003058 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003059 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003060 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003061 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003062 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003063 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003064 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003065 }
3066
Geoff Langf41d0ee2016-10-07 13:04:23 -04003067 if (length)
3068 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003069 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003070 }
3071
Jamie Madill0063c512014-08-25 15:47:53 -04003072 return true;
3073}
3074
He Yunchaoced53ae2016-11-29 15:00:51 +08003075bool ValidateGetnUniformfvEXT(Context *context,
3076 GLuint program,
3077 GLint location,
3078 GLsizei bufSize,
3079 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003080{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003081 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003082}
3083
He Yunchaoced53ae2016-11-29 15:00:51 +08003084bool ValidateGetnUniformivEXT(Context *context,
3085 GLuint program,
3086 GLint location,
3087 GLsizei bufSize,
3088 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003089{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003090 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3091}
3092
3093bool ValidateGetUniformfvRobustANGLE(Context *context,
3094 GLuint program,
3095 GLint location,
3096 GLsizei bufSize,
3097 GLsizei *length,
3098 GLfloat *params)
3099{
3100 if (!ValidateRobustEntryPoint(context, bufSize))
3101 {
3102 return false;
3103 }
3104
3105 // bufSize is validated in ValidateSizedGetUniform
3106 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3107}
3108
3109bool ValidateGetUniformivRobustANGLE(Context *context,
3110 GLuint program,
3111 GLint location,
3112 GLsizei bufSize,
3113 GLsizei *length,
3114 GLint *params)
3115{
3116 if (!ValidateRobustEntryPoint(context, bufSize))
3117 {
3118 return false;
3119 }
3120
3121 // bufSize is validated in ValidateSizedGetUniform
3122 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3123}
3124
3125bool ValidateGetUniformuivRobustANGLE(Context *context,
3126 GLuint program,
3127 GLint location,
3128 GLsizei bufSize,
3129 GLsizei *length,
3130 GLuint *params)
3131{
3132 if (!ValidateRobustEntryPoint(context, bufSize))
3133 {
3134 return false;
3135 }
3136
3137 if (context->getClientMajorVersion() < 3)
3138 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003139 context->handleError(InvalidOperation() << "Entry point requires at least OpenGL ES 3.0.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003140 return false;
3141 }
3142
3143 // bufSize is validated in ValidateSizedGetUniform
3144 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003145}
3146
He Yunchaoced53ae2016-11-29 15:00:51 +08003147bool ValidateDiscardFramebufferBase(Context *context,
3148 GLenum target,
3149 GLsizei numAttachments,
3150 const GLenum *attachments,
3151 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003152{
3153 if (numAttachments < 0)
3154 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003155 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003156 return false;
3157 }
3158
3159 for (GLsizei i = 0; i < numAttachments; ++i)
3160 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003161 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003162 {
3163 if (defaultFramebuffer)
3164 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003165 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003166 return false;
3167 }
3168
3169 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3170 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003171 context->handleError(InvalidOperation() << "Requested color attachment is "
3172 "greater than the maximum supported "
3173 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003174 return false;
3175 }
3176 }
3177 else
3178 {
3179 switch (attachments[i])
3180 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003181 case GL_DEPTH_ATTACHMENT:
3182 case GL_STENCIL_ATTACHMENT:
3183 case GL_DEPTH_STENCIL_ATTACHMENT:
3184 if (defaultFramebuffer)
3185 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003186 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3187 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003188 return false;
3189 }
3190 break;
3191 case GL_COLOR:
3192 case GL_DEPTH:
3193 case GL_STENCIL:
3194 if (!defaultFramebuffer)
3195 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003196 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3197 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003198 return false;
3199 }
3200 break;
3201 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003202 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003203 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003204 }
3205 }
3206 }
3207
3208 return true;
3209}
3210
Austin Kinross6ee1e782015-05-29 17:05:37 -07003211bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3212{
3213 // Note that debug marker calls must not set error state
3214
3215 if (length < 0)
3216 {
3217 return false;
3218 }
3219
3220 if (marker == nullptr)
3221 {
3222 return false;
3223 }
3224
3225 return true;
3226}
3227
3228bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3229{
3230 // Note that debug marker calls must not set error state
3231
3232 if (length < 0)
3233 {
3234 return false;
3235 }
3236
3237 if (length > 0 && marker == nullptr)
3238 {
3239 return false;
3240 }
3241
3242 return true;
3243}
3244
Geoff Langdcab33b2015-07-21 13:03:16 -04003245bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003246 GLenum target,
3247 egl::Image *image)
3248{
Geoff Langa8406172015-07-21 16:53:39 -04003249 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3250 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003251 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003252 return false;
3253 }
3254
3255 switch (target)
3256 {
3257 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003258 if (!context->getExtensions().eglImage)
3259 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003260 context->handleError(InvalidEnum()
3261 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003262 }
3263 break;
3264
3265 case GL_TEXTURE_EXTERNAL_OES:
3266 if (!context->getExtensions().eglImageExternal)
3267 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003268 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3269 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003270 }
Geoff Langa8406172015-07-21 16:53:39 -04003271 break;
3272
3273 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003274 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003275 return false;
3276 }
3277
Jamie Madill61e16b42017-06-19 11:13:23 -04003278 ASSERT(context->getCurrentDisplay());
3279 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003280 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003281 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003282 return false;
3283 }
3284
3285 if (image->getSamples() > 0)
3286 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003287 context->handleError(InvalidOperation()
3288 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003289 return false;
3290 }
3291
Geoff Langca271392017-04-05 12:30:00 -04003292 const TextureCaps &textureCaps =
3293 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003294 if (!textureCaps.texturable)
3295 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003296 context->handleError(InvalidOperation()
3297 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003298 return false;
3299 }
3300
Geoff Langdcab33b2015-07-21 13:03:16 -04003301 return true;
3302}
3303
3304bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003305 GLenum target,
3306 egl::Image *image)
3307{
Geoff Langa8406172015-07-21 16:53:39 -04003308 if (!context->getExtensions().eglImage)
3309 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003310 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003311 return false;
3312 }
3313
3314 switch (target)
3315 {
3316 case GL_RENDERBUFFER:
3317 break;
3318
3319 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003320 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003321 return false;
3322 }
3323
Jamie Madill61e16b42017-06-19 11:13:23 -04003324 ASSERT(context->getCurrentDisplay());
3325 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003326 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003327 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003328 return false;
3329 }
3330
Geoff Langca271392017-04-05 12:30:00 -04003331 const TextureCaps &textureCaps =
3332 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003333 if (!textureCaps.renderable)
3334 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003335 context->handleError(InvalidOperation()
3336 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003337 return false;
3338 }
3339
Geoff Langdcab33b2015-07-21 13:03:16 -04003340 return true;
3341}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003342
3343bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3344{
Geoff Lang36167ab2015-12-07 10:27:14 -05003345 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003346 {
3347 // The default VAO should always exist
3348 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003349 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003350 return false;
3351 }
3352
3353 return true;
3354}
3355
Geoff Langc5629752015-12-07 16:29:04 -05003356bool ValidateProgramBinaryBase(Context *context,
3357 GLuint program,
3358 GLenum binaryFormat,
3359 const void *binary,
3360 GLint length)
3361{
3362 Program *programObject = GetValidProgram(context, program);
3363 if (programObject == nullptr)
3364 {
3365 return false;
3366 }
3367
3368 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3369 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3370 programBinaryFormats.end())
3371 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003372 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003373 return false;
3374 }
3375
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003376 if (context->hasActiveTransformFeedback(program))
3377 {
3378 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003379 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3380 "is associated with an active transform "
3381 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003382 return false;
3383 }
3384
Geoff Langc5629752015-12-07 16:29:04 -05003385 return true;
3386}
3387
3388bool ValidateGetProgramBinaryBase(Context *context,
3389 GLuint program,
3390 GLsizei bufSize,
3391 GLsizei *length,
3392 GLenum *binaryFormat,
3393 void *binary)
3394{
3395 Program *programObject = GetValidProgram(context, program);
3396 if (programObject == nullptr)
3397 {
3398 return false;
3399 }
3400
3401 if (!programObject->isLinked())
3402 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003403 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003404 return false;
3405 }
3406
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003407 if (context->getCaps().programBinaryFormats.empty())
3408 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003409 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003410 return false;
3411 }
3412
Geoff Langc5629752015-12-07 16:29:04 -05003413 return true;
3414}
Jamie Madillc29968b2016-01-20 11:17:23 -05003415
Jamie Madillc29968b2016-01-20 11:17:23 -05003416bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3417{
3418 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003419 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003420 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003421 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3422 return false;
3423 }
3424 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3425 {
3426 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003427 return false;
3428 }
3429
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003430 ASSERT(context->getGLState().getDrawFramebuffer());
3431 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003432 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3433
3434 // This should come first before the check for the default frame buffer
3435 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3436 // rather than INVALID_OPERATION
3437 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3438 {
3439 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3440
3441 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003442 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3443 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003444 {
3445 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003446 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3447 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3448 // 3.1 is still a bit ambiguous about the error, but future specs are
3449 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003450 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003451 return false;
3452 }
3453 else if (bufs[colorAttachment] >= maxColorAttachment)
3454 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003455 context->handleError(InvalidOperation()
3456 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003457 return false;
3458 }
3459 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3460 frameBufferId != 0)
3461 {
3462 // INVALID_OPERATION-GL is bound to buffer and ith argument
3463 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003464 context->handleError(InvalidOperation()
3465 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003466 return false;
3467 }
3468 }
3469
3470 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3471 // and n is not 1 or bufs is bound to value other than BACK and NONE
3472 if (frameBufferId == 0)
3473 {
3474 if (n != 1)
3475 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003476 context->handleError(InvalidOperation()
3477 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003478 return false;
3479 }
3480
3481 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3482 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003483 context->handleError(
3484 InvalidOperation()
3485 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003486 return false;
3487 }
3488 }
3489
3490 return true;
3491}
3492
Geoff Lang496c02d2016-10-20 11:38:11 -07003493bool ValidateGetBufferPointervBase(Context *context,
3494 GLenum target,
3495 GLenum pname,
3496 GLsizei *length,
3497 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003498{
Geoff Lang496c02d2016-10-20 11:38:11 -07003499 if (length)
3500 {
3501 *length = 0;
3502 }
3503
3504 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3505 {
3506 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003507 InvalidOperation()
3508 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003509 return false;
3510 }
3511
Olli Etuaho4f667482016-03-30 15:56:35 +03003512 if (!ValidBufferTarget(context, target))
3513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003514 context->handleError(InvalidEnum() << "Buffer target not valid: 0x" << std::hex
3515 << std::uppercase << target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003516 return false;
3517 }
3518
Geoff Lang496c02d2016-10-20 11:38:11 -07003519 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003520 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003521 case GL_BUFFER_MAP_POINTER:
3522 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003523
Geoff Lang496c02d2016-10-20 11:38:11 -07003524 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003525 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003526 return false;
3527 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003528
3529 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3530 // target bound to zero generate an INVALID_OPERATION error."
3531 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003532 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003533 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003534 context->handleError(InvalidOperation()
3535 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003536 return false;
3537 }
3538
Geoff Lang496c02d2016-10-20 11:38:11 -07003539 if (length)
3540 {
3541 *length = 1;
3542 }
3543
Olli Etuaho4f667482016-03-30 15:56:35 +03003544 return true;
3545}
3546
3547bool ValidateUnmapBufferBase(Context *context, GLenum target)
3548{
3549 if (!ValidBufferTarget(context, target))
3550 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003551 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003552 return false;
3553 }
3554
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003555 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003556
3557 if (buffer == nullptr || !buffer->isMapped())
3558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003559 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003560 return false;
3561 }
3562
3563 return true;
3564}
3565
3566bool ValidateMapBufferRangeBase(Context *context,
3567 GLenum target,
3568 GLintptr offset,
3569 GLsizeiptr length,
3570 GLbitfield access)
3571{
3572 if (!ValidBufferTarget(context, target))
3573 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003574 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003575 return false;
3576 }
3577
Brandon Jones6cad5662017-06-14 13:25:13 -07003578 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003579 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003580 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3581 return false;
3582 }
3583
3584 if (length < 0)
3585 {
3586 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003587 return false;
3588 }
3589
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003590 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003591
3592 if (!buffer)
3593 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003594 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003595 return false;
3596 }
3597
3598 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003599 CheckedNumeric<size_t> checkedOffset(offset);
3600 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003601
Jamie Madille2e406c2016-06-02 13:04:10 -04003602 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003603 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003604 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003605 return false;
3606 }
3607
3608 // Check for invalid bits in the mask
3609 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3610 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3611 GL_MAP_UNSYNCHRONIZED_BIT;
3612
3613 if (access & ~(allAccessBits))
3614 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003615 context->handleError(InvalidValue()
3616 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003617 return false;
3618 }
3619
3620 if (length == 0)
3621 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003622 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003623 return false;
3624 }
3625
3626 if (buffer->isMapped())
3627 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003628 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003629 return false;
3630 }
3631
3632 // Check for invalid bit combinations
3633 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3634 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003635 context->handleError(InvalidOperation()
3636 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003637 return false;
3638 }
3639
3640 GLbitfield writeOnlyBits =
3641 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3642
3643 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3644 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003645 context->handleError(InvalidOperation()
3646 << "Invalid access bits when mapping buffer for reading: 0x"
3647 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003648 return false;
3649 }
3650
3651 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3652 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003653 context->handleError(
3654 InvalidOperation()
3655 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003656 return false;
3657 }
Geoff Lang79f71042017-08-14 16:43:43 -04003658
3659 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003660}
3661
3662bool ValidateFlushMappedBufferRangeBase(Context *context,
3663 GLenum target,
3664 GLintptr offset,
3665 GLsizeiptr length)
3666{
Brandon Jones6cad5662017-06-14 13:25:13 -07003667 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003668 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003669 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3670 return false;
3671 }
3672
3673 if (length < 0)
3674 {
3675 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003676 return false;
3677 }
3678
3679 if (!ValidBufferTarget(context, target))
3680 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003681 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003682 return false;
3683 }
3684
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003685 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003686
3687 if (buffer == nullptr)
3688 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003689 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003690 return false;
3691 }
3692
3693 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3694 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003695 context->handleError(InvalidOperation()
3696 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003697 return false;
3698 }
3699
3700 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003701 CheckedNumeric<size_t> checkedOffset(offset);
3702 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003703
Jamie Madille2e406c2016-06-02 13:04:10 -04003704 if (!checkedSize.IsValid() ||
3705 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003706 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003707 context->handleError(InvalidValue()
3708 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003709 return false;
3710 }
3711
3712 return true;
3713}
3714
Olli Etuaho41997e72016-03-10 13:38:39 +02003715bool ValidateGenOrDelete(Context *context, GLint n)
3716{
3717 if (n < 0)
3718 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003719 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003720 return false;
3721 }
3722 return true;
3723}
3724
Geoff Langff5b2d52016-09-07 11:32:23 -04003725bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3726{
3727 if (!context->getExtensions().robustClientMemory)
3728 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003729 context->handleError(InvalidOperation()
3730 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003731 return false;
3732 }
3733
3734 if (bufSize < 0)
3735 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003736 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003737 return false;
3738 }
3739
3740 return true;
3741}
3742
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003743bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3744{
3745 if (bufSize < numParams)
3746 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003747 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3748 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003749 return false;
3750 }
3751
3752 return true;
3753}
3754
Jamie Madillbe849e42017-05-02 15:49:00 -04003755bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3756 GLenum target,
3757 GLenum attachment,
3758 GLenum pname,
3759 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003760{
Geoff Langff5b2d52016-09-07 11:32:23 -04003761 if (!ValidFramebufferTarget(target))
3762 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003763 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003764 return false;
3765 }
3766
3767 int clientVersion = context->getClientMajorVersion();
3768
3769 switch (pname)
3770 {
3771 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3772 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3773 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3774 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3775 break;
3776
Martin Radeve5285d22017-07-14 16:23:53 +03003777 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3778 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3779 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3780 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3781 if (clientVersion < 3 || !context->getExtensions().multiview)
3782 {
3783 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3784 return false;
3785 }
3786 break;
3787
Geoff Langff5b2d52016-09-07 11:32:23 -04003788 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3789 if (clientVersion < 3 && !context->getExtensions().sRGB)
3790 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003791 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003792 return false;
3793 }
3794 break;
3795
3796 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3797 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3798 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3799 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3800 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3801 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3802 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3803 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3804 if (clientVersion < 3)
3805 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003806 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003807 return false;
3808 }
3809 break;
3810
3811 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003812 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003813 return false;
3814 }
3815
3816 // Determine if the attachment is a valid enum
3817 switch (attachment)
3818 {
3819 case GL_BACK:
3820 case GL_FRONT:
3821 case GL_DEPTH:
3822 case GL_STENCIL:
3823 case GL_DEPTH_STENCIL_ATTACHMENT:
3824 if (clientVersion < 3)
3825 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003826 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003827 return false;
3828 }
3829 break;
3830
3831 case GL_DEPTH_ATTACHMENT:
3832 case GL_STENCIL_ATTACHMENT:
3833 break;
3834
3835 default:
3836 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
3837 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3838 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003839 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003840 return false;
3841 }
3842 break;
3843 }
3844
3845 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3846 ASSERT(framebuffer);
3847
3848 if (framebuffer->id() == 0)
3849 {
3850 if (clientVersion < 3)
3851 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003852 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003853 return false;
3854 }
3855
3856 switch (attachment)
3857 {
3858 case GL_BACK:
3859 case GL_DEPTH:
3860 case GL_STENCIL:
3861 break;
3862
3863 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003864 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003865 return false;
3866 }
3867 }
3868 else
3869 {
3870 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3871 {
3872 // Valid attachment query
3873 }
3874 else
3875 {
3876 switch (attachment)
3877 {
3878 case GL_DEPTH_ATTACHMENT:
3879 case GL_STENCIL_ATTACHMENT:
3880 break;
3881
3882 case GL_DEPTH_STENCIL_ATTACHMENT:
3883 if (!framebuffer->hasValidDepthStencil())
3884 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003885 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003886 return false;
3887 }
3888 break;
3889
3890 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003891 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003892 return false;
3893 }
3894 }
3895 }
3896
3897 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3898 if (attachmentObject)
3899 {
3900 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3901 attachmentObject->type() == GL_TEXTURE ||
3902 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3903
3904 switch (pname)
3905 {
3906 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3907 if (attachmentObject->type() != GL_RENDERBUFFER &&
3908 attachmentObject->type() != GL_TEXTURE)
3909 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003910 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003911 return false;
3912 }
3913 break;
3914
3915 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3916 if (attachmentObject->type() != GL_TEXTURE)
3917 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003918 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003919 return false;
3920 }
3921 break;
3922
3923 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3924 if (attachmentObject->type() != GL_TEXTURE)
3925 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003926 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003927 return false;
3928 }
3929 break;
3930
3931 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3932 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3933 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003934 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003935 return false;
3936 }
3937 break;
3938
3939 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3940 if (attachmentObject->type() != GL_TEXTURE)
3941 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003942 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003943 return false;
3944 }
3945 break;
3946
3947 default:
3948 break;
3949 }
3950 }
3951 else
3952 {
3953 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3954 // is NONE, then querying any other pname will generate INVALID_ENUM.
3955
3956 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3957 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3958 // INVALID_OPERATION for all other pnames
3959
3960 switch (pname)
3961 {
3962 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3963 break;
3964
3965 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3966 if (clientVersion < 3)
3967 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003968 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07003969 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003970 return false;
3971 }
3972 break;
3973
3974 default:
3975 if (clientVersion < 3)
3976 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003977 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07003978 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003979 return false;
3980 }
3981 else
3982 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003983 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Brandon Jonesafa75152017-07-21 13:11:29 -07003984 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003985 return false;
3986 }
3987 }
3988 }
3989
Martin Radeve5285d22017-07-14 16:23:53 +03003990 if (numParams)
3991 {
3992 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
3993 {
3994 // Only when the viewport offsets are queried we can have a varying number of output
3995 // parameters.
3996 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
3997 *numParams = numViews * 2;
3998 }
3999 else
4000 {
4001 // For all other queries we can have only one output parameter.
4002 *numParams = 1;
4003 }
4004 }
4005
Geoff Langff5b2d52016-09-07 11:32:23 -04004006 return true;
4007}
4008
4009bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4010 GLenum target,
4011 GLenum attachment,
4012 GLenum pname,
4013 GLsizei bufSize,
4014 GLsizei *numParams)
4015{
4016 if (!ValidateRobustEntryPoint(context, bufSize))
4017 {
4018 return false;
4019 }
4020
Jamie Madillbe849e42017-05-02 15:49:00 -04004021 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4022 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004023 {
4024 return false;
4025 }
4026
4027 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4028 {
4029 return false;
4030 }
4031
4032 return true;
4033}
4034
Geoff Langff5b2d52016-09-07 11:32:23 -04004035bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4036 GLenum target,
4037 GLenum pname,
4038 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004039 GLsizei *length,
4040 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004041{
4042 if (!ValidateRobustEntryPoint(context, bufSize))
4043 {
4044 return false;
4045 }
4046
Geoff Langebebe1c2016-10-14 12:01:31 -04004047 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004048 {
4049 return false;
4050 }
4051
Geoff Langebebe1c2016-10-14 12:01:31 -04004052 if (!ValidateRobustBufferSize(context, bufSize, *length))
4053 {
4054 return false;
4055 }
4056
4057 return true;
4058}
4059
Geoff Langebebe1c2016-10-14 12:01:31 -04004060bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4061 GLenum target,
4062 GLenum pname,
4063 GLsizei bufSize,
4064 GLsizei *length,
4065 GLint64 *params)
4066{
4067 if (!ValidateRobustEntryPoint(context, bufSize))
4068 {
4069 return false;
4070 }
4071
4072 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4073 {
4074 return false;
4075 }
4076
4077 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004078 {
4079 return false;
4080 }
4081
4082 return true;
4083}
4084
Jamie Madillbe849e42017-05-02 15:49:00 -04004085bool ValidateGetProgramivBase(ValidationContext *context,
4086 GLuint program,
4087 GLenum pname,
4088 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004089{
4090 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004091 if (numParams)
4092 {
4093 *numParams = 1;
4094 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004095
4096 Program *programObject = GetValidProgram(context, program);
4097 if (!programObject)
4098 {
4099 return false;
4100 }
4101
4102 switch (pname)
4103 {
4104 case GL_DELETE_STATUS:
4105 case GL_LINK_STATUS:
4106 case GL_VALIDATE_STATUS:
4107 case GL_INFO_LOG_LENGTH:
4108 case GL_ATTACHED_SHADERS:
4109 case GL_ACTIVE_ATTRIBUTES:
4110 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4111 case GL_ACTIVE_UNIFORMS:
4112 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4113 break;
4114
4115 case GL_PROGRAM_BINARY_LENGTH:
4116 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4117 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004118 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4119 "requires GL_OES_get_program_binary or "
4120 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004121 return false;
4122 }
4123 break;
4124
4125 case GL_ACTIVE_UNIFORM_BLOCKS:
4126 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4127 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4128 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4129 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4130 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4131 if (context->getClientMajorVersion() < 3)
4132 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004133 context->handleError(InvalidEnum() << "Querying requires at least ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004134 return false;
4135 }
4136 break;
4137
Yunchao He61afff12017-03-14 15:34:03 +08004138 case GL_PROGRAM_SEPARABLE:
4139 if (context->getClientVersion() < Version(3, 1))
4140 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004141 context->handleError(InvalidEnum() << "Querying requires at least ES 3.1.");
Yunchao He61afff12017-03-14 15:34:03 +08004142 return false;
4143 }
4144 break;
4145
Geoff Langff5b2d52016-09-07 11:32:23 -04004146 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004147 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004148 return false;
4149 }
4150
4151 return true;
4152}
4153
4154bool ValidateGetProgramivRobustANGLE(Context *context,
4155 GLuint program,
4156 GLenum pname,
4157 GLsizei bufSize,
4158 GLsizei *numParams)
4159{
4160 if (!ValidateRobustEntryPoint(context, bufSize))
4161 {
4162 return false;
4163 }
4164
Jamie Madillbe849e42017-05-02 15:49:00 -04004165 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004166 {
4167 return false;
4168 }
4169
4170 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4171 {
4172 return false;
4173 }
4174
4175 return true;
4176}
4177
Geoff Lang740d9022016-10-07 11:20:52 -04004178bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4179 GLenum target,
4180 GLenum pname,
4181 GLsizei bufSize,
4182 GLsizei *length,
4183 GLint *params)
4184{
4185 if (!ValidateRobustEntryPoint(context, bufSize))
4186 {
4187 return false;
4188 }
4189
4190 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4191 {
4192 return false;
4193 }
4194
4195 if (!ValidateRobustBufferSize(context, bufSize, *length))
4196 {
4197 return false;
4198 }
4199
4200 return true;
4201}
4202
Geoff Langd7d0ed32016-10-07 11:33:51 -04004203bool ValidateGetShaderivRobustANGLE(Context *context,
4204 GLuint shader,
4205 GLenum pname,
4206 GLsizei bufSize,
4207 GLsizei *length,
4208 GLint *params)
4209{
4210 if (!ValidateRobustEntryPoint(context, bufSize))
4211 {
4212 return false;
4213 }
4214
4215 if (!ValidateGetShaderivBase(context, shader, pname, length))
4216 {
4217 return false;
4218 }
4219
4220 if (!ValidateRobustBufferSize(context, bufSize, *length))
4221 {
4222 return false;
4223 }
4224
4225 return true;
4226}
4227
Geoff Langc1984ed2016-10-07 12:41:00 -04004228bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4229 GLenum target,
4230 GLenum pname,
4231 GLsizei bufSize,
4232 GLsizei *length,
4233 GLfloat *params)
4234{
4235 if (!ValidateRobustEntryPoint(context, bufSize))
4236 {
4237 return false;
4238 }
4239
4240 if (!ValidateGetTexParameterBase(context, target, pname, length))
4241 {
4242 return false;
4243 }
4244
4245 if (!ValidateRobustBufferSize(context, bufSize, *length))
4246 {
4247 return false;
4248 }
4249
4250 return true;
4251}
4252
Geoff Langc1984ed2016-10-07 12:41:00 -04004253bool ValidateGetTexParameterivRobustANGLE(Context *context,
4254 GLenum target,
4255 GLenum pname,
4256 GLsizei bufSize,
4257 GLsizei *length,
4258 GLint *params)
4259{
4260 if (!ValidateRobustEntryPoint(context, bufSize))
4261 {
4262 return false;
4263 }
4264
4265 if (!ValidateGetTexParameterBase(context, target, pname, length))
4266 {
4267 return false;
4268 }
4269
4270 if (!ValidateRobustBufferSize(context, bufSize, *length))
4271 {
4272 return false;
4273 }
4274
4275 return true;
4276}
4277
Geoff Langc1984ed2016-10-07 12:41:00 -04004278bool ValidateTexParameterfvRobustANGLE(Context *context,
4279 GLenum target,
4280 GLenum pname,
4281 GLsizei bufSize,
4282 const GLfloat *params)
4283{
4284 if (!ValidateRobustEntryPoint(context, bufSize))
4285 {
4286 return false;
4287 }
4288
4289 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4290}
4291
Geoff Langc1984ed2016-10-07 12:41:00 -04004292bool ValidateTexParameterivRobustANGLE(Context *context,
4293 GLenum target,
4294 GLenum pname,
4295 GLsizei bufSize,
4296 const GLint *params)
4297{
4298 if (!ValidateRobustEntryPoint(context, bufSize))
4299 {
4300 return false;
4301 }
4302
4303 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4304}
4305
Geoff Langc1984ed2016-10-07 12:41:00 -04004306bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4307 GLuint sampler,
4308 GLenum pname,
4309 GLuint bufSize,
4310 GLsizei *length,
4311 GLfloat *params)
4312{
4313 if (!ValidateRobustEntryPoint(context, bufSize))
4314 {
4315 return false;
4316 }
4317
4318 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4319 {
4320 return false;
4321 }
4322
4323 if (!ValidateRobustBufferSize(context, bufSize, *length))
4324 {
4325 return false;
4326 }
4327
4328 return true;
4329}
4330
Geoff Langc1984ed2016-10-07 12:41:00 -04004331bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4332 GLuint sampler,
4333 GLenum pname,
4334 GLuint bufSize,
4335 GLsizei *length,
4336 GLint *params)
4337{
4338 if (!ValidateRobustEntryPoint(context, bufSize))
4339 {
4340 return false;
4341 }
4342
4343 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4344 {
4345 return false;
4346 }
4347
4348 if (!ValidateRobustBufferSize(context, bufSize, *length))
4349 {
4350 return false;
4351 }
4352
4353 return true;
4354}
4355
Geoff Langc1984ed2016-10-07 12:41:00 -04004356bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4357 GLuint sampler,
4358 GLenum pname,
4359 GLsizei bufSize,
4360 const GLfloat *params)
4361{
4362 if (!ValidateRobustEntryPoint(context, bufSize))
4363 {
4364 return false;
4365 }
4366
4367 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4368}
4369
Geoff Langc1984ed2016-10-07 12:41:00 -04004370bool ValidateSamplerParameterivRobustANGLE(Context *context,
4371 GLuint sampler,
4372 GLenum pname,
4373 GLsizei bufSize,
4374 const GLint *params)
4375{
4376 if (!ValidateRobustEntryPoint(context, bufSize))
4377 {
4378 return false;
4379 }
4380
4381 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4382}
4383
Geoff Lang0b031062016-10-13 14:30:04 -04004384bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4385 GLuint index,
4386 GLenum pname,
4387 GLsizei bufSize,
4388 GLsizei *length,
4389 GLfloat *params)
4390{
4391 if (!ValidateRobustEntryPoint(context, bufSize))
4392 {
4393 return false;
4394 }
4395
4396 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4397 {
4398 return false;
4399 }
4400
4401 if (!ValidateRobustBufferSize(context, bufSize, *length))
4402 {
4403 return false;
4404 }
4405
4406 return true;
4407}
4408
Geoff Lang0b031062016-10-13 14:30:04 -04004409bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4410 GLuint index,
4411 GLenum pname,
4412 GLsizei bufSize,
4413 GLsizei *length,
4414 GLint *params)
4415{
4416 if (!ValidateRobustEntryPoint(context, bufSize))
4417 {
4418 return false;
4419 }
4420
4421 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4422 {
4423 return false;
4424 }
4425
4426 if (!ValidateRobustBufferSize(context, bufSize, *length))
4427 {
4428 return false;
4429 }
4430
4431 return true;
4432}
4433
Geoff Lang0b031062016-10-13 14:30:04 -04004434bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4435 GLuint index,
4436 GLenum pname,
4437 GLsizei bufSize,
4438 GLsizei *length,
4439 void **pointer)
4440{
4441 if (!ValidateRobustEntryPoint(context, bufSize))
4442 {
4443 return false;
4444 }
4445
4446 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4447 {
4448 return false;
4449 }
4450
4451 if (!ValidateRobustBufferSize(context, bufSize, *length))
4452 {
4453 return false;
4454 }
4455
4456 return true;
4457}
4458
Geoff Lang0b031062016-10-13 14:30:04 -04004459bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4460 GLuint index,
4461 GLenum pname,
4462 GLsizei bufSize,
4463 GLsizei *length,
4464 GLint *params)
4465{
4466 if (!ValidateRobustEntryPoint(context, bufSize))
4467 {
4468 return false;
4469 }
4470
4471 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4472 {
4473 return false;
4474 }
4475
4476 if (!ValidateRobustBufferSize(context, bufSize, *length))
4477 {
4478 return false;
4479 }
4480
4481 return true;
4482}
4483
Geoff Lang0b031062016-10-13 14:30:04 -04004484bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4485 GLuint index,
4486 GLenum pname,
4487 GLsizei bufSize,
4488 GLsizei *length,
4489 GLuint *params)
4490{
4491 if (!ValidateRobustEntryPoint(context, bufSize))
4492 {
4493 return false;
4494 }
4495
4496 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4497 {
4498 return false;
4499 }
4500
4501 if (!ValidateRobustBufferSize(context, bufSize, *length))
4502 {
4503 return false;
4504 }
4505
4506 return true;
4507}
4508
Geoff Lang6899b872016-10-14 11:30:13 -04004509bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4510 GLuint program,
4511 GLuint uniformBlockIndex,
4512 GLenum pname,
4513 GLsizei bufSize,
4514 GLsizei *length,
4515 GLint *params)
4516{
4517 if (!ValidateRobustEntryPoint(context, bufSize))
4518 {
4519 return false;
4520 }
4521
4522 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4523 {
4524 return false;
4525 }
4526
4527 if (!ValidateRobustBufferSize(context, bufSize, *length))
4528 {
4529 return false;
4530 }
4531
4532 return true;
4533}
4534
Geoff Lang0a9661f2016-10-20 10:59:20 -07004535bool ValidateGetInternalFormativRobustANGLE(Context *context,
4536 GLenum target,
4537 GLenum internalformat,
4538 GLenum pname,
4539 GLsizei bufSize,
4540 GLsizei *length,
4541 GLint *params)
4542{
4543 if (!ValidateRobustEntryPoint(context, bufSize))
4544 {
4545 return false;
4546 }
4547
4548 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4549 {
4550 return false;
4551 }
4552
4553 if (!ValidateRobustBufferSize(context, bufSize, *length))
4554 {
4555 return false;
4556 }
4557
4558 return true;
4559}
4560
Shao80957d92017-02-20 21:25:59 +08004561bool ValidateVertexFormatBase(ValidationContext *context,
4562 GLuint attribIndex,
4563 GLint size,
4564 GLenum type,
4565 GLboolean pureInteger)
4566{
4567 const Caps &caps = context->getCaps();
4568 if (attribIndex >= caps.maxVertexAttributes)
4569 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004570 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004571 return false;
4572 }
4573
4574 if (size < 1 || size > 4)
4575 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004576 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004577 return false;
Shao80957d92017-02-20 21:25:59 +08004578 }
4579
4580 switch (type)
4581 {
4582 case GL_BYTE:
4583 case GL_UNSIGNED_BYTE:
4584 case GL_SHORT:
4585 case GL_UNSIGNED_SHORT:
4586 break;
4587
4588 case GL_INT:
4589 case GL_UNSIGNED_INT:
4590 if (context->getClientMajorVersion() < 3)
4591 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004592 context->handleError(InvalidEnum()
4593 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004594 return false;
4595 }
4596 break;
4597
4598 case GL_FIXED:
4599 case GL_FLOAT:
4600 if (pureInteger)
4601 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004602 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004603 return false;
4604 }
4605 break;
4606
4607 case GL_HALF_FLOAT:
4608 if (context->getClientMajorVersion() < 3)
4609 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004610 context->handleError(InvalidEnum()
4611 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004612 return false;
4613 }
4614 if (pureInteger)
4615 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004616 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004617 return false;
4618 }
4619 break;
4620
4621 case GL_INT_2_10_10_10_REV:
4622 case GL_UNSIGNED_INT_2_10_10_10_REV:
4623 if (context->getClientMajorVersion() < 3)
4624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004625 context->handleError(InvalidEnum()
4626 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004627 return false;
4628 }
4629 if (pureInteger)
4630 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004631 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004632 return false;
4633 }
4634 if (size != 4)
4635 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004636 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4637 "UNSIGNED_INT_2_10_10_10_REV and "
4638 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004639 return false;
4640 }
4641 break;
4642
4643 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004644 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004645 return false;
4646 }
4647
4648 return true;
4649}
4650
Geoff Lang76e65652017-03-27 14:58:02 -04004651// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4652// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4653// specified clear value and the type of a buffer that is being cleared generates an
4654// INVALID_OPERATION error instead of producing undefined results
4655bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4656 GLint drawbuffer,
4657 const GLenum *validComponentTypes,
4658 size_t validComponentTypeCount)
4659{
4660 const FramebufferAttachment *attachment =
4661 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4662 if (attachment)
4663 {
4664 GLenum componentType = attachment->getFormat().info->componentType;
4665 const GLenum *end = validComponentTypes + validComponentTypeCount;
4666 if (std::find(validComponentTypes, end, componentType) == end)
4667 {
4668 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004669 InvalidOperation()
4670 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004671 return false;
4672 }
4673 }
4674
4675 return true;
4676}
4677
Corentin Wallezb2931602017-04-11 15:58:57 -04004678bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4679 GLsizei imageSize,
4680 GLsizei dataSize)
4681{
4682 if (!ValidateRobustEntryPoint(context, dataSize))
4683 {
4684 return false;
4685 }
4686
4687 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
4688 if (pixelUnpackBuffer == nullptr)
4689 {
4690 if (dataSize < imageSize)
4691 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004692 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004693 }
4694 }
4695 return true;
4696}
4697
Jamie Madillbe849e42017-05-02 15:49:00 -04004698bool ValidateGetBufferParameterBase(ValidationContext *context,
4699 GLenum target,
4700 GLenum pname,
4701 bool pointerVersion,
4702 GLsizei *numParams)
4703{
4704 if (numParams)
4705 {
4706 *numParams = 0;
4707 }
4708
4709 if (!ValidBufferTarget(context, target))
4710 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004711 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004712 return false;
4713 }
4714
4715 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4716 if (!buffer)
4717 {
4718 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004719 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004720 return false;
4721 }
4722
4723 const Extensions &extensions = context->getExtensions();
4724
4725 switch (pname)
4726 {
4727 case GL_BUFFER_USAGE:
4728 case GL_BUFFER_SIZE:
4729 break;
4730
4731 case GL_BUFFER_ACCESS_OES:
4732 if (!extensions.mapBuffer)
4733 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004734 context->handleError(InvalidEnum()
4735 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004736 return false;
4737 }
4738 break;
4739
4740 case GL_BUFFER_MAPPED:
4741 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4742 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4743 !extensions.mapBufferRange)
4744 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004745 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4746 "GL_OES_mapbuffer or "
4747 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004748 return false;
4749 }
4750 break;
4751
4752 case GL_BUFFER_MAP_POINTER:
4753 if (!pointerVersion)
4754 {
4755 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004756 InvalidEnum()
4757 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004758 return false;
4759 }
4760 break;
4761
4762 case GL_BUFFER_ACCESS_FLAGS:
4763 case GL_BUFFER_MAP_OFFSET:
4764 case GL_BUFFER_MAP_LENGTH:
4765 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4766 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004767 context->handleError(InvalidEnum()
4768 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004769 return false;
4770 }
4771 break;
4772
4773 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004774 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004775 return false;
4776 }
4777
4778 // All buffer parameter queries return one value.
4779 if (numParams)
4780 {
4781 *numParams = 1;
4782 }
4783
4784 return true;
4785}
4786
4787bool ValidateGetRenderbufferParameterivBase(Context *context,
4788 GLenum target,
4789 GLenum pname,
4790 GLsizei *length)
4791{
4792 if (length)
4793 {
4794 *length = 0;
4795 }
4796
4797 if (target != GL_RENDERBUFFER)
4798 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004799 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004800 return false;
4801 }
4802
4803 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4804 if (renderbuffer == nullptr)
4805 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004806 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004807 return false;
4808 }
4809
4810 switch (pname)
4811 {
4812 case GL_RENDERBUFFER_WIDTH:
4813 case GL_RENDERBUFFER_HEIGHT:
4814 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4815 case GL_RENDERBUFFER_RED_SIZE:
4816 case GL_RENDERBUFFER_GREEN_SIZE:
4817 case GL_RENDERBUFFER_BLUE_SIZE:
4818 case GL_RENDERBUFFER_ALPHA_SIZE:
4819 case GL_RENDERBUFFER_DEPTH_SIZE:
4820 case GL_RENDERBUFFER_STENCIL_SIZE:
4821 break;
4822
4823 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4824 if (!context->getExtensions().framebufferMultisample)
4825 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004826 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004827 return false;
4828 }
4829 break;
4830
4831 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004832 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004833 return false;
4834 }
4835
4836 if (length)
4837 {
4838 *length = 1;
4839 }
4840 return true;
4841}
4842
4843bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4844{
4845 if (length)
4846 {
4847 *length = 0;
4848 }
4849
4850 if (GetValidShader(context, shader) == nullptr)
4851 {
4852 return false;
4853 }
4854
4855 switch (pname)
4856 {
4857 case GL_SHADER_TYPE:
4858 case GL_DELETE_STATUS:
4859 case GL_COMPILE_STATUS:
4860 case GL_INFO_LOG_LENGTH:
4861 case GL_SHADER_SOURCE_LENGTH:
4862 break;
4863
4864 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4865 if (!context->getExtensions().translatedShaderSource)
4866 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004867 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004868 return false;
4869 }
4870 break;
4871
4872 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004873 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004874 return false;
4875 }
4876
4877 if (length)
4878 {
4879 *length = 1;
4880 }
4881 return true;
4882}
4883
4884bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4885{
4886 if (length)
4887 {
4888 *length = 0;
4889 }
4890
4891 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4892 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004893 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004894 return false;
4895 }
4896
4897 if (context->getTargetTexture(target) == nullptr)
4898 {
4899 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004900 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004901 return false;
4902 }
4903
4904 switch (pname)
4905 {
4906 case GL_TEXTURE_MAG_FILTER:
4907 case GL_TEXTURE_MIN_FILTER:
4908 case GL_TEXTURE_WRAP_S:
4909 case GL_TEXTURE_WRAP_T:
4910 break;
4911
4912 case GL_TEXTURE_USAGE_ANGLE:
4913 if (!context->getExtensions().textureUsage)
4914 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004915 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004916 return false;
4917 }
4918 break;
4919
4920 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4921 if (!context->getExtensions().textureFilterAnisotropic)
4922 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004923 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004924 return false;
4925 }
4926 break;
4927
4928 case GL_TEXTURE_IMMUTABLE_FORMAT:
4929 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4930 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004931 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004932 return false;
4933 }
4934 break;
4935
4936 case GL_TEXTURE_WRAP_R:
4937 case GL_TEXTURE_IMMUTABLE_LEVELS:
4938 case GL_TEXTURE_SWIZZLE_R:
4939 case GL_TEXTURE_SWIZZLE_G:
4940 case GL_TEXTURE_SWIZZLE_B:
4941 case GL_TEXTURE_SWIZZLE_A:
4942 case GL_TEXTURE_BASE_LEVEL:
4943 case GL_TEXTURE_MAX_LEVEL:
4944 case GL_TEXTURE_MIN_LOD:
4945 case GL_TEXTURE_MAX_LOD:
4946 case GL_TEXTURE_COMPARE_MODE:
4947 case GL_TEXTURE_COMPARE_FUNC:
4948 if (context->getClientMajorVersion() < 3)
4949 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004950 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004951 return false;
4952 }
4953 break;
4954
4955 case GL_TEXTURE_SRGB_DECODE_EXT:
4956 if (!context->getExtensions().textureSRGBDecode)
4957 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004958 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004959 return false;
4960 }
4961 break;
4962
4963 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004964 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004965 return false;
4966 }
4967
4968 if (length)
4969 {
4970 *length = 1;
4971 }
4972 return true;
4973}
4974
4975bool ValidateGetVertexAttribBase(Context *context,
4976 GLuint index,
4977 GLenum pname,
4978 GLsizei *length,
4979 bool pointer,
4980 bool pureIntegerEntryPoint)
4981{
4982 if (length)
4983 {
4984 *length = 0;
4985 }
4986
4987 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
4988 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004989 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004990 return false;
4991 }
4992
4993 if (index >= context->getCaps().maxVertexAttributes)
4994 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004995 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04004996 return false;
4997 }
4998
4999 if (pointer)
5000 {
5001 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5002 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005003 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005004 return false;
5005 }
5006 }
5007 else
5008 {
5009 switch (pname)
5010 {
5011 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5012 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5013 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5014 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5015 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5016 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5017 case GL_CURRENT_VERTEX_ATTRIB:
5018 break;
5019
5020 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5021 static_assert(
5022 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5023 "ANGLE extension enums not equal to GL enums.");
5024 if (context->getClientMajorVersion() < 3 &&
5025 !context->getExtensions().instancedArrays)
5026 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005027 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5028 "requires OpenGL ES 3.0 or "
5029 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005030 return false;
5031 }
5032 break;
5033
5034 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5035 if (context->getClientMajorVersion() < 3)
5036 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005037 context->handleError(
5038 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005039 return false;
5040 }
5041 break;
5042
5043 case GL_VERTEX_ATTRIB_BINDING:
5044 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5045 if (context->getClientVersion() < ES_3_1)
5046 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005047 context->handleError(InvalidEnum()
5048 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005049 return false;
5050 }
5051 break;
5052
5053 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005054 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005055 return false;
5056 }
5057 }
5058
5059 if (length)
5060 {
5061 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5062 {
5063 *length = 4;
5064 }
5065 else
5066 {
5067 *length = 1;
5068 }
5069 }
5070
5071 return true;
5072}
5073
Jamie Madill4928b7c2017-06-20 12:57:39 -04005074bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005075 GLint x,
5076 GLint y,
5077 GLsizei width,
5078 GLsizei height,
5079 GLenum format,
5080 GLenum type,
5081 GLsizei bufSize,
5082 GLsizei *length,
5083 GLsizei *columns,
5084 GLsizei *rows,
5085 void *pixels)
5086{
5087 if (length != nullptr)
5088 {
5089 *length = 0;
5090 }
5091 if (rows != nullptr)
5092 {
5093 *rows = 0;
5094 }
5095 if (columns != nullptr)
5096 {
5097 *columns = 0;
5098 }
5099
5100 if (width < 0 || height < 0)
5101 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005102 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005103 return false;
5104 }
5105
5106 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5107
5108 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5109 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005110 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005111 return false;
5112 }
5113
5114 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5115 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005116 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005117 return false;
5118 }
5119
5120 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5121 ASSERT(framebuffer);
5122
5123 if (framebuffer->getReadBufferState() == GL_NONE)
5124 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005125 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005126 return false;
5127 }
5128
5129 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5130 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5131 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5132 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5133 // situation is an application error that would lead to a crash in ANGLE.
5134 if (readBuffer == nullptr)
5135 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005136 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005137 return false;
5138 }
5139
Martin Radev28031682017-07-28 14:47:56 +03005140 // ANGLE_multiview, Revision 1:
5141 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5142 // current read framebuffer is not NONE.
5143 if (readBuffer->getMultiviewLayout() != GL_NONE)
5144 {
5145 context->handleError(InvalidFramebufferOperation()
5146 << "Attempting to read from a multi-view framebuffer.");
5147 return false;
5148 }
5149
Geoff Lang280ba992017-04-18 16:30:58 -04005150 if (context->getExtensions().webglCompatibility)
5151 {
5152 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5153 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5154 // and type before validating the combination of format and type. However, the
5155 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5156 // verifies that GL_INVALID_OPERATION is generated.
5157 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5158 // dEQP/WebGL.
5159 if (!ValidReadPixelsFormatEnum(context, format))
5160 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005161 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005162 return false;
5163 }
5164
5165 if (!ValidReadPixelsTypeEnum(context, type))
5166 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005167 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005168 return false;
5169 }
5170 }
5171
Jamie Madill4928b7c2017-06-20 12:57:39 -04005172 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5173 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005174 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5175
5176 bool validFormatTypeCombination =
5177 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5178
5179 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5180 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005181 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005182 return false;
5183 }
5184
5185 // Check for pixel pack buffer related API errors
5186 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5187 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5188 {
5189 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005190 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005191 return false;
5192 }
5193
5194 // .. the data would be packed to the buffer object such that the memory writes required
5195 // would exceed the data store size.
5196 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5197 const gl::Extents size(width, height, 1);
5198 const auto &pack = context->getGLState().getPackState();
5199
5200 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5201 if (endByteOrErr.isError())
5202 {
5203 context->handleError(endByteOrErr.getError());
5204 return false;
5205 }
5206
5207 size_t endByte = endByteOrErr.getResult();
5208 if (bufSize >= 0)
5209 {
5210 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5211 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005212 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005213 return false;
5214 }
5215 }
5216
5217 if (pixelPackBuffer != nullptr)
5218 {
5219 CheckedNumeric<size_t> checkedEndByte(endByte);
5220 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5221 checkedEndByte += checkedOffset;
5222
5223 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5224 {
5225 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005226 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005227 return false;
5228 }
5229 }
5230
5231 if (pixelPackBuffer == nullptr && length != nullptr)
5232 {
5233 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5234 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005235 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005236 return false;
5237 }
5238
5239 *length = static_cast<GLsizei>(endByte);
5240 }
5241
5242 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5243 angle::CheckedNumeric<int> clippedExtent(length);
5244 if (start < 0)
5245 {
5246 // "subtract" the area that is less than 0
5247 clippedExtent += start;
5248 }
5249
5250 const int readExtent = start + length;
5251 if (readExtent > bufferSize)
5252 {
5253 // Subtract the region to the right of the read buffer
5254 clippedExtent -= (readExtent - bufferSize);
5255 }
5256
5257 if (!clippedExtent.IsValid())
5258 {
5259 return 0;
5260 }
5261
5262 return std::max(clippedExtent.ValueOrDie(), 0);
5263 };
5264
5265 if (columns != nullptr)
5266 {
5267 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5268 }
5269
5270 if (rows != nullptr)
5271 {
5272 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5273 }
5274
5275 return true;
5276}
5277
5278template <typename ParamType>
5279bool ValidateTexParameterBase(Context *context,
5280 GLenum target,
5281 GLenum pname,
5282 GLsizei bufSize,
5283 const ParamType *params)
5284{
5285 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5286 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005287 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005288 return false;
5289 }
5290
5291 if (context->getTargetTexture(target) == nullptr)
5292 {
5293 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005294 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005295 return false;
5296 }
5297
5298 const GLsizei minBufSize = 1;
5299 if (bufSize >= 0 && bufSize < minBufSize)
5300 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005301 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005302 return false;
5303 }
5304
5305 switch (pname)
5306 {
5307 case GL_TEXTURE_WRAP_R:
5308 case GL_TEXTURE_SWIZZLE_R:
5309 case GL_TEXTURE_SWIZZLE_G:
5310 case GL_TEXTURE_SWIZZLE_B:
5311 case GL_TEXTURE_SWIZZLE_A:
5312 case GL_TEXTURE_BASE_LEVEL:
5313 case GL_TEXTURE_MAX_LEVEL:
5314 case GL_TEXTURE_COMPARE_MODE:
5315 case GL_TEXTURE_COMPARE_FUNC:
5316 case GL_TEXTURE_MIN_LOD:
5317 case GL_TEXTURE_MAX_LOD:
5318 if (context->getClientMajorVersion() < 3)
5319 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005320 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005321 return false;
5322 }
5323 if (target == GL_TEXTURE_EXTERNAL_OES &&
5324 !context->getExtensions().eglImageExternalEssl3)
5325 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005326 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5327 "available without "
5328 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005329 return false;
5330 }
5331 break;
5332
5333 default:
5334 break;
5335 }
5336
JiangYizhou4cff8d62017-07-06 14:54:09 +08005337 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5338 {
5339 switch (pname)
5340 {
5341 case GL_TEXTURE_MIN_FILTER:
5342 case GL_TEXTURE_MAG_FILTER:
5343 case GL_TEXTURE_WRAP_S:
5344 case GL_TEXTURE_WRAP_T:
5345 case GL_TEXTURE_WRAP_R:
5346 case GL_TEXTURE_MIN_LOD:
5347 case GL_TEXTURE_MAX_LOD:
5348 case GL_TEXTURE_COMPARE_MODE:
5349 case GL_TEXTURE_COMPARE_FUNC:
5350 context->handleError(InvalidEnum()
5351 << "Invalid parameter for 2D multisampled textures.");
5352 return false;
5353 }
5354 }
5355
Jamie Madillbe849e42017-05-02 15:49:00 -04005356 switch (pname)
5357 {
5358 case GL_TEXTURE_WRAP_S:
5359 case GL_TEXTURE_WRAP_T:
5360 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005361 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005362 bool restrictedWrapModes =
5363 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5364 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5365 {
5366 return false;
5367 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005368 }
5369 break;
5370
5371 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005372 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005373 bool restrictedMinFilter =
5374 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5375 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5376 {
5377 return false;
5378 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005379 }
5380 break;
5381
5382 case GL_TEXTURE_MAG_FILTER:
5383 if (!ValidateTextureMagFilterValue(context, params))
5384 {
5385 return false;
5386 }
5387 break;
5388
5389 case GL_TEXTURE_USAGE_ANGLE:
5390 switch (ConvertToGLenum(params[0]))
5391 {
5392 case GL_NONE:
5393 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5394 break;
5395
5396 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005397 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005398 return false;
5399 }
5400 break;
5401
5402 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5403 if (!context->getExtensions().textureFilterAnisotropic)
5404 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005405 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005406 return false;
5407 }
5408
5409 // we assume the parameter passed to this validation method is truncated, not rounded
5410 if (params[0] < 1)
5411 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005412 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005413 return false;
5414 }
5415 break;
5416
5417 case GL_TEXTURE_MIN_LOD:
5418 case GL_TEXTURE_MAX_LOD:
5419 // any value is permissible
5420 break;
5421
5422 case GL_TEXTURE_COMPARE_MODE:
5423 if (!ValidateTextureCompareModeValue(context, params))
5424 {
5425 return false;
5426 }
5427 break;
5428
5429 case GL_TEXTURE_COMPARE_FUNC:
5430 if (!ValidateTextureCompareFuncValue(context, params))
5431 {
5432 return false;
5433 }
5434 break;
5435
5436 case GL_TEXTURE_SWIZZLE_R:
5437 case GL_TEXTURE_SWIZZLE_G:
5438 case GL_TEXTURE_SWIZZLE_B:
5439 case GL_TEXTURE_SWIZZLE_A:
5440 switch (ConvertToGLenum(params[0]))
5441 {
5442 case GL_RED:
5443 case GL_GREEN:
5444 case GL_BLUE:
5445 case GL_ALPHA:
5446 case GL_ZERO:
5447 case GL_ONE:
5448 break;
5449
5450 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005451 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005452 return false;
5453 }
5454 break;
5455
5456 case GL_TEXTURE_BASE_LEVEL:
5457 if (params[0] < 0)
5458 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005459 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005460 return false;
5461 }
5462 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5463 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005464 context->handleError(InvalidOperation()
5465 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005466 return false;
5467 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005468 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5469 {
5470 context->handleError(InvalidOperation()
5471 << "Base level must be 0 for multisampled textures.");
5472 return false;
5473 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005474 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5475 {
5476 context->handleError(InvalidOperation()
5477 << "Base level must be 0 for rectangle textures.");
5478 return false;
5479 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005480 break;
5481
5482 case GL_TEXTURE_MAX_LEVEL:
5483 if (params[0] < 0)
5484 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005485 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005486 return false;
5487 }
5488 break;
5489
5490 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5491 if (context->getClientVersion() < Version(3, 1))
5492 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005493 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005494 return false;
5495 }
5496 switch (ConvertToGLenum(params[0]))
5497 {
5498 case GL_DEPTH_COMPONENT:
5499 case GL_STENCIL_INDEX:
5500 break;
5501
5502 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005503 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005504 return false;
5505 }
5506 break;
5507
5508 case GL_TEXTURE_SRGB_DECODE_EXT:
5509 if (!ValidateTextureSRGBDecodeValue(context, params))
5510 {
5511 return false;
5512 }
5513 break;
5514
5515 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005516 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005517 return false;
5518 }
5519
5520 return true;
5521}
5522
5523template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5524template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5525
Jamie Madill12e957f2017-08-26 21:42:26 -04005526bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5527{
5528 if (index >= MAX_VERTEX_ATTRIBS)
5529 {
5530 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5531 return false;
5532 }
5533
5534 return true;
5535}
5536
5537bool ValidateGetActiveUniformBlockivBase(Context *context,
5538 GLuint program,
5539 GLuint uniformBlockIndex,
5540 GLenum pname,
5541 GLsizei *length)
5542{
5543 if (length)
5544 {
5545 *length = 0;
5546 }
5547
5548 if (context->getClientMajorVersion() < 3)
5549 {
5550 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5551 return false;
5552 }
5553
5554 Program *programObject = GetValidProgram(context, program);
5555 if (!programObject)
5556 {
5557 return false;
5558 }
5559
5560 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5561 {
5562 context->handleError(InvalidValue()
5563 << "uniformBlockIndex exceeds active uniform block count.");
5564 return false;
5565 }
5566
5567 switch (pname)
5568 {
5569 case GL_UNIFORM_BLOCK_BINDING:
5570 case GL_UNIFORM_BLOCK_DATA_SIZE:
5571 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5572 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5573 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5574 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5575 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5576 break;
5577
5578 default:
5579 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5580 return false;
5581 }
5582
5583 if (length)
5584 {
5585 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5586 {
5587 const UniformBlock &uniformBlock =
5588 programObject->getUniformBlockByIndex(uniformBlockIndex);
5589 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5590 }
5591 else
5592 {
5593 *length = 1;
5594 }
5595 }
5596
5597 return true;
5598}
5599
Jamie Madill9696d072017-08-26 23:19:57 -04005600template <typename ParamType>
5601bool ValidateSamplerParameterBase(Context *context,
5602 GLuint sampler,
5603 GLenum pname,
5604 GLsizei bufSize,
5605 ParamType *params)
5606{
5607 if (context->getClientMajorVersion() < 3)
5608 {
5609 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5610 return false;
5611 }
5612
5613 if (!context->isSampler(sampler))
5614 {
5615 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5616 return false;
5617 }
5618
5619 const GLsizei minBufSize = 1;
5620 if (bufSize >= 0 && bufSize < minBufSize)
5621 {
5622 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5623 return false;
5624 }
5625
5626 switch (pname)
5627 {
5628 case GL_TEXTURE_WRAP_S:
5629 case GL_TEXTURE_WRAP_T:
5630 case GL_TEXTURE_WRAP_R:
5631 if (!ValidateTextureWrapModeValue(context, params, false))
5632 {
5633 return false;
5634 }
5635 break;
5636
5637 case GL_TEXTURE_MIN_FILTER:
5638 if (!ValidateTextureMinFilterValue(context, params, false))
5639 {
5640 return false;
5641 }
5642 break;
5643
5644 case GL_TEXTURE_MAG_FILTER:
5645 if (!ValidateTextureMagFilterValue(context, params))
5646 {
5647 return false;
5648 }
5649 break;
5650
5651 case GL_TEXTURE_MIN_LOD:
5652 case GL_TEXTURE_MAX_LOD:
5653 // any value is permissible
5654 break;
5655
5656 case GL_TEXTURE_COMPARE_MODE:
5657 if (!ValidateTextureCompareModeValue(context, params))
5658 {
5659 return false;
5660 }
5661 break;
5662
5663 case GL_TEXTURE_COMPARE_FUNC:
5664 if (!ValidateTextureCompareFuncValue(context, params))
5665 {
5666 return false;
5667 }
5668 break;
5669
5670 case GL_TEXTURE_SRGB_DECODE_EXT:
5671 if (!ValidateTextureSRGBDecodeValue(context, params))
5672 {
5673 return false;
5674 }
5675 break;
5676
5677 default:
5678 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5679 return false;
5680 }
5681
5682 return true;
5683}
5684
5685template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5686template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5687
5688bool ValidateGetSamplerParameterBase(Context *context,
5689 GLuint sampler,
5690 GLenum pname,
5691 GLsizei *length)
5692{
5693 if (length)
5694 {
5695 *length = 0;
5696 }
5697
5698 if (context->getClientMajorVersion() < 3)
5699 {
5700 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5701 return false;
5702 }
5703
5704 if (!context->isSampler(sampler))
5705 {
5706 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5707 return false;
5708 }
5709
5710 switch (pname)
5711 {
5712 case GL_TEXTURE_WRAP_S:
5713 case GL_TEXTURE_WRAP_T:
5714 case GL_TEXTURE_WRAP_R:
5715 case GL_TEXTURE_MIN_FILTER:
5716 case GL_TEXTURE_MAG_FILTER:
5717 case GL_TEXTURE_MIN_LOD:
5718 case GL_TEXTURE_MAX_LOD:
5719 case GL_TEXTURE_COMPARE_MODE:
5720 case GL_TEXTURE_COMPARE_FUNC:
5721 break;
5722
5723 case GL_TEXTURE_SRGB_DECODE_EXT:
5724 if (!context->getExtensions().textureSRGBDecode)
5725 {
5726 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5727 return false;
5728 }
5729 break;
5730
5731 default:
5732 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5733 return false;
5734 }
5735
5736 if (length)
5737 {
5738 *length = 1;
5739 }
5740 return true;
5741}
5742
5743bool ValidateGetInternalFormativBase(Context *context,
5744 GLenum target,
5745 GLenum internalformat,
5746 GLenum pname,
5747 GLsizei bufSize,
5748 GLsizei *numParams)
5749{
5750 if (numParams)
5751 {
5752 *numParams = 0;
5753 }
5754
5755 if (context->getClientMajorVersion() < 3)
5756 {
5757 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
5758 return false;
5759 }
5760
5761 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5762 if (!formatCaps.renderable)
5763 {
5764 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5765 return false;
5766 }
5767
5768 switch (target)
5769 {
5770 case GL_RENDERBUFFER:
5771 break;
5772
5773 case GL_TEXTURE_2D_MULTISAMPLE:
5774 if (context->getClientVersion() < ES_3_1)
5775 {
5776 context->handleError(InvalidOperation()
5777 << "Texture target requires at least OpenGL ES 3.1.");
5778 return false;
5779 }
5780 break;
5781
5782 default:
5783 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5784 return false;
5785 }
5786
5787 if (bufSize < 0)
5788 {
5789 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5790 return false;
5791 }
5792
5793 GLsizei maxWriteParams = 0;
5794 switch (pname)
5795 {
5796 case GL_NUM_SAMPLE_COUNTS:
5797 maxWriteParams = 1;
5798 break;
5799
5800 case GL_SAMPLES:
5801 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5802 break;
5803
5804 default:
5805 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5806 return false;
5807 }
5808
5809 if (numParams)
5810 {
5811 // glGetInternalFormativ will not overflow bufSize
5812 *numParams = std::min(bufSize, maxWriteParams);
5813 }
5814
5815 return true;
5816}
5817
Jamie Madillc29968b2016-01-20 11:17:23 -05005818} // namespace gl