blob: 7d19f7239790b799be8ba7d17a2d000a28d1e166 [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:
179 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat;
180
181 case GL_HALF_FLOAT:
182 return context->getClientVersion() >= ES_3_0 ||
183 context->getExtensions().textureHalfFloat;
184
185 case GL_HALF_FLOAT_OES:
186 return context->getExtensions().colorBufferHalfFloat;
187
188 default:
189 return false;
190 }
191}
192
193bool ValidReadPixelsFormatEnum(ValidationContext *context, GLenum format)
194{
195 switch (format)
196 {
197 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
198 case GL_RGBA:
199 case GL_RGB:
200 case GL_ALPHA:
201 return context->getClientVersion() >= ES_2_0;
202
203 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
204 case GL_RG:
205 case GL_RED:
206 case GL_RGBA_INTEGER:
207 case GL_RGB_INTEGER:
208 case GL_RG_INTEGER:
209 case GL_RED_INTEGER:
210 return context->getClientVersion() >= ES_3_0;
211
212 case GL_SRGB_ALPHA_EXT:
213 case GL_SRGB_EXT:
214 return context->getExtensions().sRGB;
215
216 case GL_BGRA_EXT:
217 return context->getExtensions().readFormatBGRA;
218
219 default:
220 return false;
221 }
222}
223
Geoff Langf607c602016-09-21 11:46:48 -0400224bool ValidReadPixelsFormatType(ValidationContext *context,
225 GLenum framebufferComponentType,
226 GLenum format,
227 GLenum type)
228{
229 switch (framebufferComponentType)
230 {
231 case GL_UNSIGNED_NORMALIZED:
232 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
233 // ReadPixels with BGRA even if the extension is not present
234 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
235 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
236 type == GL_UNSIGNED_BYTE);
237
238 case GL_SIGNED_NORMALIZED:
239 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
240
241 case GL_INT:
242 return (format == GL_RGBA_INTEGER && type == GL_INT);
243
244 case GL_UNSIGNED_INT:
245 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
246
247 case GL_FLOAT:
248 return (format == GL_RGBA && type == GL_FLOAT);
249
250 default:
251 UNREACHABLE();
252 return false;
253 }
254}
255
Geoff Langc1984ed2016-10-07 12:41:00 -0400256template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400257bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400258{
259 switch (ConvertToGLenum(params[0]))
260 {
261 case GL_CLAMP_TO_EDGE:
262 break;
263
264 case GL_REPEAT:
265 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400266 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400267 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400268 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700269 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400270 return false;
271 }
272 break;
273
274 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700275 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400276 return false;
277 }
278
279 return true;
280}
281
282template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400283bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400284{
285 switch (ConvertToGLenum(params[0]))
286 {
287 case GL_NEAREST:
288 case GL_LINEAR:
289 break;
290
291 case GL_NEAREST_MIPMAP_NEAREST:
292 case GL_LINEAR_MIPMAP_NEAREST:
293 case GL_NEAREST_MIPMAP_LINEAR:
294 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400295 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400296 {
297 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700298 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400299 return false;
300 }
301 break;
302
303 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700304 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400305 return false;
306 }
307
308 return true;
309}
310
311template <typename ParamType>
312bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
313{
314 switch (ConvertToGLenum(params[0]))
315 {
316 case GL_NEAREST:
317 case GL_LINEAR:
318 break;
319
320 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700321 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400322 return false;
323 }
324
325 return true;
326}
327
328template <typename ParamType>
329bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
330{
331 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
332 switch (ConvertToGLenum(params[0]))
333 {
334 case GL_NONE:
335 case GL_COMPARE_REF_TO_TEXTURE:
336 break;
337
338 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700339 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400340 return false;
341 }
342
343 return true;
344}
345
346template <typename ParamType>
347bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
348{
349 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
350 switch (ConvertToGLenum(params[0]))
351 {
352 case GL_LEQUAL:
353 case GL_GEQUAL:
354 case GL_LESS:
355 case GL_GREATER:
356 case GL_EQUAL:
357 case GL_NOTEQUAL:
358 case GL_ALWAYS:
359 case GL_NEVER:
360 break;
361
362 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700363 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400364 return false;
365 }
366
367 return true;
368}
369
370template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700371bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
372{
373 if (!context->getExtensions().textureSRGBDecode)
374 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700375 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700376 return false;
377 }
378
379 switch (ConvertToGLenum(params[0]))
380 {
381 case GL_DECODE_EXT:
382 case GL_SKIP_DECODE_EXT:
383 break;
384
385 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700386 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700387 return false;
388 }
389
390 return true;
391}
392
Jamie Madillc1d770e2017-04-13 17:31:24 -0400393bool ValidateUniformCommonBase(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500394 gl::Program *program,
395 GLint location,
396 GLsizei count,
397 const LinkedUniform **uniformOut)
398{
399 // TODO(Jiajia): Add image uniform check in future.
400 if (count < 0)
401 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700402 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500403 return false;
404 }
405
Brandon Jones6cad5662017-06-14 13:25:13 -0700406 if (!program)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500407 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700408 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
409 return false;
410 }
411
412 if (!program->isLinked())
413 {
414 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500415 return false;
416 }
417
418 if (location == -1)
419 {
420 // Silently ignore the uniform command
421 return false;
422 }
423
424 const auto &uniformLocations = program->getUniformLocations();
Jamie Madillbe849e42017-05-02 15:49:00 -0400425 size_t castedLocation = static_cast<size_t>(location);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500426 if (castedLocation >= uniformLocations.size())
427 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500428 context->handleError(InvalidOperation() << "Invalid uniform location");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500429 return false;
430 }
431
432 const auto &uniformLocation = uniformLocations[castedLocation];
433 if (uniformLocation.ignored)
434 {
435 // Silently ignore the uniform command
436 return false;
437 }
438
439 if (!uniformLocation.used)
440 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500441 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500442 return false;
443 }
444
445 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
446
447 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
448 if (!uniform.isArray() && count > 1)
449 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500450 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500451 return false;
452 }
453
454 *uniformOut = &uniform;
455 return true;
456}
457
Frank Henigman999b0fd2017-02-02 21:45:55 -0500458bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -0500459 GLenum uniformType,
460 GLsizei count,
461 const GLint *value)
462{
463 // Value type is GL_INT, because we only get here from glUniform1i{v}.
464 // It is compatible with INT or BOOL.
465 // Do these cheap tests first, for a little extra speed.
466 if (GL_INT == uniformType || GL_BOOL == uniformType)
467 {
468 return true;
469 }
470
471 if (IsSamplerType(uniformType))
472 {
Frank Henigman999b0fd2017-02-02 21:45:55 -0500473 // Check that the values are in range.
474 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
475 for (GLsizei i = 0; i < count; ++i)
476 {
477 if (value[i] < 0 || value[i] >= max)
478 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500479 context->handleError(InvalidValue() << "sampler uniform value out of range");
Frank Henigman999b0fd2017-02-02 21:45:55 -0500480 return false;
481 }
482 }
Frank Henigmana98a6472017-02-02 21:38:32 -0500483 return true;
484 }
485
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500486 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmana98a6472017-02-02 21:38:32 -0500487 return false;
488}
489
Jamie Madillc1d770e2017-04-13 17:31:24 -0400490bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500491{
492 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -0500493 // Do the cheaper test first, for a little extra speed.
494 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500495 {
496 return true;
497 }
498
Brandon Jonesafa75152017-07-21 13:11:29 -0700499 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500500 return false;
501}
502
Jamie Madillc1d770e2017-04-13 17:31:24 -0400503bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500504{
505 // Check that the value type is compatible with uniform type.
506 if (valueType == uniformType)
507 {
508 return true;
509 }
510
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500511 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500512 return false;
513}
514
Geoff Lange0cff192017-05-30 13:04:56 -0400515bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
516{
517 const Program *program = context->getGLState().getProgram();
518 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
519
520 const auto &programOutputTypes = program->getOutputVariableTypes();
521 for (size_t drawBufferIdx = 0; drawBufferIdx < programOutputTypes.size(); drawBufferIdx++)
522 {
523 GLenum outputType = programOutputTypes[drawBufferIdx];
524 GLenum inputType = framebuffer->getDrawbufferWriteType(drawBufferIdx);
525 if (outputType != GL_NONE && inputType != GL_NONE && inputType != outputType)
526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500527 context->handleError(InvalidOperation() << "Fragment shader output type does not "
528 "match the bound framebuffer attachment "
529 "type.");
Geoff Lange0cff192017-05-30 13:04:56 -0400530 return false;
531 }
532 }
533
534 return true;
535}
536
Geoff Lang9ab5b822017-05-30 16:19:23 -0400537bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
538{
539 const Program *program = context->getGLState().getProgram();
540 const VertexArray *vao = context->getGLState().getVertexArray();
541
542 for (const auto &shaderAttribute : program->getAttributes())
543 {
Geoff Lang69df2422017-07-05 12:42:31 -0400544 // gl_VertexID and gl_InstanceID are active attributes but don't have a bound attribute.
545 if (shaderAttribute.isBuiltIn())
546 {
547 continue;
548 }
549
Geoff Lang9ab5b822017-05-30 16:19:23 -0400550 GLenum shaderInputType = VariableComponentType(shaderAttribute.type);
551
552 const auto &attrib = vao->getVertexAttribute(shaderAttribute.location);
553 const auto &currentValue =
554 context->getGLState().getVertexAttribCurrentValue(shaderAttribute.location);
555 GLenum vertexType = attrib.enabled ? GetVertexAttributeBaseType(attrib) : currentValue.Type;
556
557 if (shaderInputType != GL_NONE && vertexType != GL_NONE && shaderInputType != vertexType)
558 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500559 context->handleError(InvalidOperation() << "Vertex shader input type does not "
560 "match the type of the bound vertex "
561 "attribute.");
Geoff Lang9ab5b822017-05-30 16:19:23 -0400562 return false;
563 }
564 }
565
566 return true;
567}
568
Geoff Langf41a7152016-09-19 15:11:17 -0400569} // anonymous namespace
570
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500571bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400572{
Jamie Madilld7460c72014-01-21 16:38:14 -0500573 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400574 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800575 case GL_TEXTURE_2D:
576 case GL_TEXTURE_CUBE_MAP:
577 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400578
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400579 case GL_TEXTURE_RECTANGLE_ANGLE:
580 return context->getExtensions().textureRectangle;
581
He Yunchaoced53ae2016-11-29 15:00:51 +0800582 case GL_TEXTURE_3D:
583 case GL_TEXTURE_2D_ARRAY:
584 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500585
He Yunchaoced53ae2016-11-29 15:00:51 +0800586 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800587 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400588
He Yunchaoced53ae2016-11-29 15:00:51 +0800589 default:
590 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500591 }
Jamie Madill35d15012013-10-07 10:46:37 -0400592}
593
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500594bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
595{
596 switch (target)
597 {
598 case GL_TEXTURE_2D:
599 case GL_TEXTURE_CUBE_MAP:
600 return true;
601
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400602 case GL_TEXTURE_RECTANGLE_ANGLE:
603 return context->getExtensions().textureRectangle;
604
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500605 default:
606 return false;
607 }
608}
609
610bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
611{
612 switch (target)
613 {
614 case GL_TEXTURE_3D:
615 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300616 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500617
618 default:
619 return false;
620 }
621}
622
Ian Ewellbda75592016-04-18 17:25:54 -0400623// Most texture GL calls are not compatible with external textures, so we have a separate validation
624// function for use in the GL calls that do
625bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
626{
627 return (target == GL_TEXTURE_EXTERNAL_OES) &&
628 (context->getExtensions().eglImageExternal ||
629 context->getExtensions().eglStreamConsumerExternal);
630}
631
Shannon Woods4dfed832014-03-17 20:03:39 -0400632// This function differs from ValidTextureTarget in that the target must be
633// usable as the destination of a 2D operation-- so a cube face is valid, but
634// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400635// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500636bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400637{
638 switch (target)
639 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800640 case GL_TEXTURE_2D:
641 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
642 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
643 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
644 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
645 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
646 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
647 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400648 case GL_TEXTURE_RECTANGLE_ANGLE:
649 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800650 default:
651 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500652 }
653}
654
Jamie Madillbe849e42017-05-02 15:49:00 -0400655bool ValidateDrawElementsInstancedBase(ValidationContext *context,
656 GLenum mode,
657 GLsizei count,
658 GLenum type,
659 const GLvoid *indices,
660 GLsizei primcount)
661{
662 if (primcount < 0)
663 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700664 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400665 return false;
666 }
667
668 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
669 {
670 return false;
671 }
672
673 // No-op zero primitive count
674 return (primcount > 0);
675}
676
677bool ValidateDrawArraysInstancedBase(Context *context,
678 GLenum mode,
679 GLint first,
680 GLsizei count,
681 GLsizei primcount)
682{
683 if (primcount < 0)
684 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700685 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400686 return false;
687 }
688
689 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
690 {
691 return false;
692 }
693
694 // No-op if zero primitive count
695 return (primcount > 0);
696}
697
Corentin Wallez0dc97812017-06-22 14:38:44 -0400698bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400699{
700 // Verify there is at least one active attribute with a divisor of zero
701 const State &state = context->getGLState();
702
703 Program *program = state.getProgram();
704
705 const auto &attribs = state.getVertexArray()->getVertexAttributes();
706 const auto &bindings = state.getVertexArray()->getVertexBindings();
707 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
708 {
709 const VertexAttribute &attrib = attribs[attributeIndex];
710 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300711 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400712 {
713 return true;
714 }
715 }
716
Brandon Jonesafa75152017-07-21 13:11:29 -0700717 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400718 return false;
719}
720
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500721bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
722{
723 switch (target)
724 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800725 case GL_TEXTURE_3D:
726 case GL_TEXTURE_2D_ARRAY:
727 return true;
728 default:
729 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400730 }
731}
732
He Yunchao11b038b2016-11-22 21:24:04 +0800733bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
734{
735 switch (target)
736 {
737 case GL_TEXTURE_2D:
738 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
739 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
740 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
741 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
742 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
743 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
744 case GL_TEXTURE_3D:
745 case GL_TEXTURE_2D_ARRAY:
746 case GL_TEXTURE_2D_MULTISAMPLE:
747 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400748 case GL_TEXTURE_RECTANGLE_ANGLE:
749 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800750 default:
751 return false;
752 }
753}
754
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500755bool ValidFramebufferTarget(GLenum target)
756{
He Yunchaoced53ae2016-11-29 15:00:51 +0800757 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
758 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400759 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500760
761 switch (target)
762 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800763 case GL_FRAMEBUFFER:
764 return true;
765 case GL_READ_FRAMEBUFFER:
766 return true;
767 case GL_DRAW_FRAMEBUFFER:
768 return true;
769 default:
770 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500771 }
772}
773
Jamie Madill29639852016-09-02 15:00:09 -0400774bool ValidBufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill8c96d582014-03-05 15:01:23 -0500775{
776 switch (target)
777 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800778 case GL_ARRAY_BUFFER:
779 case GL_ELEMENT_ARRAY_BUFFER:
780 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -0500781
He Yunchaoced53ae2016-11-29 15:00:51 +0800782 case GL_PIXEL_PACK_BUFFER:
783 case GL_PIXEL_UNPACK_BUFFER:
784 return (context->getExtensions().pixelBufferObject ||
785 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -0400786
He Yunchaoced53ae2016-11-29 15:00:51 +0800787 case GL_COPY_READ_BUFFER:
788 case GL_COPY_WRITE_BUFFER:
789 case GL_TRANSFORM_FEEDBACK_BUFFER:
790 case GL_UNIFORM_BUFFER:
791 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -0500792
He Yunchaoced53ae2016-11-29 15:00:51 +0800793 case GL_ATOMIC_COUNTER_BUFFER:
794 case GL_SHADER_STORAGE_BUFFER:
795 case GL_DRAW_INDIRECT_BUFFER:
796 case GL_DISPATCH_INDIRECT_BUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800797 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -0400798
He Yunchaoced53ae2016-11-29 15:00:51 +0800799 default:
800 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -0500801 }
802}
803
Jamie Madillc29968b2016-01-20 11:17:23 -0500804bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400805{
Jamie Madillc29968b2016-01-20 11:17:23 -0500806 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400807 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -0400808 switch (target)
809 {
Jamie Madillc29968b2016-01-20 11:17:23 -0500810 case GL_TEXTURE_2D:
811 maxDimension = caps.max2DTextureSize;
812 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800813 case GL_TEXTURE_CUBE_MAP:
814 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
815 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
816 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
817 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
818 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
819 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
820 maxDimension = caps.maxCubeMapTextureSize;
821 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400822 case GL_TEXTURE_RECTANGLE_ANGLE:
823 return level == 0;
He Yunchaoced53ae2016-11-29 15:00:51 +0800824 case GL_TEXTURE_3D:
825 maxDimension = caps.max3DTextureSize;
826 break;
827 case GL_TEXTURE_2D_ARRAY:
828 maxDimension = caps.max2DTextureSize;
829 break;
He Yunchao11b038b2016-11-22 21:24:04 +0800830 case GL_TEXTURE_2D_MULTISAMPLE:
831 maxDimension = caps.max2DTextureSize;
832 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800833 default:
834 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400835 }
836
Brandon Jones6cad5662017-06-14 13:25:13 -0700837 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400838}
839
Brandon Jones6cad5662017-06-14 13:25:13 -0700840bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -0700841 GLenum target,
842 GLint level,
843 GLsizei width,
844 GLsizei height,
845 GLsizei depth,
846 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400847{
Brandon Jones6cad5662017-06-14 13:25:13 -0700848 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400849 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700850 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400851 return false;
852 }
Austin Kinross08528e12015-10-07 16:24:40 -0700853 // TexSubImage parameters can be NPOT without textureNPOT extension,
854 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500855 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500856 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500857 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400858 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400859 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700860 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400861 return false;
862 }
863
864 if (!ValidMipLevel(context, target, level))
865 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700866 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400867 return false;
868 }
869
870 return true;
871}
872
Geoff Lang0d8b7242015-09-09 14:56:53 -0400873bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
874{
875 // List of compressed format that require that the texture size is smaller than or a multiple of
876 // the compressed block size.
877 switch (internalFormat)
878 {
879 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
880 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
881 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
882 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langfff7a7d2017-06-02 10:39:17 -0400883 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
884 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
885 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
886 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
Minmin Gonge3939b92015-12-01 15:36:51 -0800887 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800888 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
889 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
890 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
891 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
892 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
893 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -0400894 return true;
895
896 default:
897 return false;
898 }
899}
900
Geoff Lang966c9402017-04-18 12:38:27 -0400901bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
902{
903 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
904 (size % blockSize == 0);
905}
906
Jamie Madillc29968b2016-01-20 11:17:23 -0500907bool ValidCompressedImageSize(const ValidationContext *context,
908 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400909 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500910 GLsizei width,
911 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400912{
Geoff Langca271392017-04-05 12:30:00 -0400913 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400914 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400915 {
916 return false;
917 }
918
Geoff Lang966c9402017-04-18 12:38:27 -0400919 if (width < 0 || height < 0)
920 {
921 return false;
922 }
923
924 if (CompressedTextureFormatRequiresExactSize(internalFormat))
925 {
926 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
927 // block size for level 0 but WebGL disallows this.
928 bool smallerThanBlockSizeAllowed =
929 level > 0 || !context->getExtensions().webglCompatibility;
930
931 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
932 smallerThanBlockSizeAllowed) ||
933 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
934 smallerThanBlockSizeAllowed))
935 {
936 return false;
937 }
938 }
939
940 return true;
941}
942
943bool ValidCompressedSubImageSize(const ValidationContext *context,
944 GLenum internalFormat,
945 GLint xoffset,
946 GLint yoffset,
947 GLsizei width,
948 GLsizei height,
949 size_t textureWidth,
950 size_t textureHeight)
951{
952 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
953 if (!formatInfo.compressed)
954 {
955 return false;
956 }
957
Geoff Lang44ff5a72017-02-03 15:15:43 -0500958 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400959 {
960 return false;
961 }
962
Geoff Lang0d8b7242015-09-09 14:56:53 -0400963 if (CompressedTextureFormatRequiresExactSize(internalFormat))
964 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500965 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400966 yoffset % formatInfo.compressedBlockHeight != 0)
967 {
968 return false;
969 }
970
971 // Allowed to either have data that is a multiple of block size or is smaller than the block
972 // size but fills the entire mip
973 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
974 static_cast<size_t>(width) == textureWidth &&
975 static_cast<size_t>(height) == textureHeight;
976 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
977 (height % formatInfo.compressedBlockHeight) == 0;
978 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400979 {
980 return false;
981 }
982 }
983
Geoff Langd4f180b2013-09-24 13:57:44 -0400984 return true;
985}
986
Geoff Langff5b2d52016-09-07 11:32:23 -0400987bool ValidImageDataSize(ValidationContext *context,
988 GLenum textureTarget,
989 GLsizei width,
990 GLsizei height,
991 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400992 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400993 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400994 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400995 GLsizei imageSize)
996{
997 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
998 if (pixelUnpackBuffer == nullptr && imageSize < 0)
999 {
1000 // Checks are not required
1001 return true;
1002 }
1003
1004 // ...the data would be unpacked from the buffer object such that the memory reads required
1005 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -04001006 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
1007 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -04001008 const gl::Extents size(width, height, depth);
1009 const auto &unpack = context->getGLState().getUnpackState();
1010
1011 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1012 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1013 if (endByteOrErr.isError())
1014 {
1015 context->handleError(endByteOrErr.getError());
1016 return false;
1017 }
1018
1019 GLuint endByte = endByteOrErr.getResult();
1020
1021 if (pixelUnpackBuffer)
1022 {
1023 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1024 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1025 checkedEndByte += checkedOffset;
1026
1027 if (!checkedEndByte.IsValid() ||
1028 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1029 {
1030 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001031 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04001032 return false;
1033 }
1034 }
1035 else
1036 {
1037 ASSERT(imageSize >= 0);
1038 if (pixels == nullptr && imageSize != 0)
1039 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001040 context->handleError(InvalidOperation()
1041 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001042 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001043 }
1044
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001045 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001046 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001047 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001048 return false;
1049 }
1050 }
1051
1052 return true;
1053}
1054
Geoff Lang37dde692014-01-31 16:34:54 -05001055bool ValidQueryType(const Context *context, GLenum queryType)
1056{
He Yunchaoced53ae2016-11-29 15:00:51 +08001057 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1058 "GL extension enums not equal.");
1059 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1060 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001061
1062 switch (queryType)
1063 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001064 case GL_ANY_SAMPLES_PASSED:
1065 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
1066 return true;
1067 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1068 return (context->getClientMajorVersion() >= 3);
1069 case GL_TIME_ELAPSED_EXT:
1070 return context->getExtensions().disjointTimerQuery;
1071 case GL_COMMANDS_COMPLETED_CHROMIUM:
1072 return context->getExtensions().syncQuery;
1073 default:
1074 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001075 }
1076}
1077
Geoff Lang2d62ab72017-03-23 16:54:40 -04001078bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
1079 GLenum type,
1080 GLboolean normalized,
1081 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001082 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001083 bool pureInteger)
1084{
1085 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001086 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1087 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1088 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1089 // parameter exceeds 255.
1090 constexpr GLsizei kMaxWebGLStride = 255;
1091 if (stride > kMaxWebGLStride)
1092 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001093 context->handleError(InvalidValue()
1094 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001095 return false;
1096 }
1097
1098 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1099 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1100 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1101 // or an INVALID_OPERATION error is generated.
1102 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1103 size_t typeSize = GetVertexFormatTypeSize(internalType);
1104
1105 ASSERT(isPow2(typeSize) && typeSize > 0);
1106 size_t sizeMask = (typeSize - 1);
1107 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1108 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001109 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001110 return false;
1111 }
1112
1113 if ((stride & sizeMask) != 0)
1114 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001115 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001116 return false;
1117 }
1118
1119 return true;
1120}
1121
Jamie Madillef300b12016-10-07 15:12:09 -04001122Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001123{
He Yunchaoced53ae2016-11-29 15:00:51 +08001124 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1125 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1126 // or program object and INVALID_OPERATION if the provided name identifies an object
1127 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001128
Dian Xiang769769a2015-09-09 15:20:08 -07001129 Program *validProgram = context->getProgram(id);
1130
1131 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001132 {
Dian Xiang769769a2015-09-09 15:20:08 -07001133 if (context->getShader(id))
1134 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001135 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001136 }
1137 else
1138 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001139 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001140 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001141 }
Dian Xiang769769a2015-09-09 15:20:08 -07001142
1143 return validProgram;
1144}
1145
Jamie Madillef300b12016-10-07 15:12:09 -04001146Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001147{
1148 // See ValidProgram for spec details.
1149
1150 Shader *validShader = context->getShader(id);
1151
1152 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001153 {
Dian Xiang769769a2015-09-09 15:20:08 -07001154 if (context->getProgram(id))
1155 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001156 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001157 }
1158 else
1159 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001160 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001161 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001162 }
Dian Xiang769769a2015-09-09 15:20:08 -07001163
1164 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001165}
1166
Geoff Langb1196682014-07-23 13:47:29 -04001167bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001168{
1169 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
1170 {
1171 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
1172
Geoff Langaae65a42014-05-26 12:43:44 -04001173 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001174 {
Martin Radevd178aa42017-07-13 14:03:22 +03001175 context->handleError(
1176 InvalidOperation()
1177 << "attachment index cannot be greater or equal to MAX_COLOR_ATTACHMENTS.");
Geoff Langb1196682014-07-23 13:47:29 -04001178 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001179 }
1180 }
1181 else
1182 {
1183 switch (attachment)
1184 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001185 case GL_DEPTH_ATTACHMENT:
1186 case GL_STENCIL_ATTACHMENT:
1187 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001188
He Yunchaoced53ae2016-11-29 15:00:51 +08001189 case GL_DEPTH_STENCIL_ATTACHMENT:
1190 if (!context->getExtensions().webglCompatibility &&
1191 context->getClientMajorVersion() < 3)
1192 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001193 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001194 return false;
1195 }
1196 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001197
He Yunchaoced53ae2016-11-29 15:00:51 +08001198 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001199 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
He Yunchaoced53ae2016-11-29 15:00:51 +08001200 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001201 }
1202 }
1203
1204 return true;
1205}
1206
Jamie Madille8fb6402017-02-14 17:56:40 -05001207bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001208 GLenum target,
1209 GLsizei samples,
1210 GLenum internalformat,
1211 GLsizei width,
1212 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001213{
1214 switch (target)
1215 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001216 case GL_RENDERBUFFER:
1217 break;
1218 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001219 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001220 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001221 }
1222
1223 if (width < 0 || height < 0 || samples < 0)
1224 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001225 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001226 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001227 }
1228
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001229 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1230 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1231
1232 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001233 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001234 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001235 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001236 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001237 }
1238
1239 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1240 // 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 -08001241 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001242 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1243 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001244 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001245 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001246 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001247 }
1248
Geoff Langaae65a42014-05-26 12:43:44 -04001249 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001250 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001251 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001252 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001253 }
1254
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001255 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001256 if (handle == 0)
1257 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001258 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001259 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001260 }
1261
1262 return true;
1263}
1264
He Yunchaoced53ae2016-11-29 15:00:51 +08001265bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1266 GLenum target,
1267 GLenum attachment,
1268 GLenum renderbuffertarget,
1269 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001270{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001271 if (!ValidFramebufferTarget(target))
1272 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001273 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001274 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001275 }
1276
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001277 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001278
Jamie Madill84115c92015-04-23 15:00:07 -04001279 ASSERT(framebuffer);
1280 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001281 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001282 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001283 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001284 }
1285
Jamie Madillb4472272014-07-03 10:38:55 -04001286 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001287 {
Jamie Madillb4472272014-07-03 10:38:55 -04001288 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001289 }
1290
Jamie Madillab9d82c2014-01-21 16:38:14 -05001291 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1292 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1293 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1294 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1295 if (renderbuffer != 0)
1296 {
1297 if (!context->getRenderbuffer(renderbuffer))
1298 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001299 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001300 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001301 }
1302 }
1303
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001304 return true;
1305}
1306
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001307bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001308 GLint srcX0,
1309 GLint srcY0,
1310 GLint srcX1,
1311 GLint srcY1,
1312 GLint dstX0,
1313 GLint dstY0,
1314 GLint dstX1,
1315 GLint dstY1,
1316 GLbitfield mask,
1317 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001318{
1319 switch (filter)
1320 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001321 case GL_NEAREST:
1322 break;
1323 case GL_LINEAR:
1324 break;
1325 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001326 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001327 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001328 }
1329
1330 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1331 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001332 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001333 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001334 }
1335
1336 if (mask == 0)
1337 {
1338 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1339 // buffers are copied.
1340 return false;
1341 }
1342
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001343 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1344 // color buffer, leaving only nearest being unfiltered from above
1345 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1346 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001347 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001348 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001349 }
1350
Jamie Madill51f40ec2016-06-15 14:06:00 -04001351 const auto &glState = context->getGLState();
1352 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1353 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001354
1355 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001356 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001357 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001358 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001359 }
1360
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001361 if (readFramebuffer->id() == drawFramebuffer->id())
1362 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001363 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001364 return false;
1365 }
1366
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001367 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001368 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001369 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001370 return false;
1371 }
1372
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001373 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001374 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001375 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001376 return false;
1377 }
1378
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001379 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001380 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001381 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001382 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001383 }
1384
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001385 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1386
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001387 if (mask & GL_COLOR_BUFFER_BIT)
1388 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001389 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001390 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001391
He Yunchao66a41a22016-12-15 16:45:05 +08001392 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001393 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001394 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001395
Geoff Langa15472a2015-08-11 11:48:03 -04001396 for (size_t drawbufferIdx = 0;
1397 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001398 {
Geoff Langa15472a2015-08-11 11:48:03 -04001399 const FramebufferAttachment *attachment =
1400 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1401 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001402 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001403 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001404
Geoff Langb2f3d052013-08-13 12:49:27 -04001405 // The GL ES 3.0.2 spec (pg 193) states that:
1406 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001407 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1408 // as well
1409 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1410 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001411 // Changes with EXT_color_buffer_float:
1412 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001413 GLenum readComponentType = readFormat.info->componentType;
1414 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001415 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001416 readComponentType == GL_SIGNED_NORMALIZED);
1417 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1418 drawComponentType == GL_SIGNED_NORMALIZED);
1419
1420 if (extensions.colorBufferFloat)
1421 {
1422 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1423 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1424
1425 if (readFixedOrFloat != drawFixedOrFloat)
1426 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001427 context->handleError(InvalidOperation()
1428 << "If the read buffer contains fixed-point or "
1429 "floating-point values, the draw buffer must "
1430 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001431 return false;
1432 }
1433 }
1434 else if (readFixedPoint != drawFixedPoint)
1435 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001436 context->handleError(InvalidOperation()
1437 << "If the read buffer contains fixed-point values, "
1438 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001439 return false;
1440 }
1441
1442 if (readComponentType == GL_UNSIGNED_INT &&
1443 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001444 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001445 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001446 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001447 }
1448
Jamie Madill6163c752015-12-07 16:32:59 -05001449 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001450 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001451 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001452 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001453 }
1454
Jamie Madilla3944d42016-07-22 22:13:26 -04001455 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001456 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001457 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001458 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001459 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001460 }
Geoff Lange4915782017-04-12 15:19:07 -04001461
1462 if (context->getExtensions().webglCompatibility &&
1463 *readColorBuffer == *attachment)
1464 {
1465 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001466 InvalidOperation()
1467 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001468 return false;
1469 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001470 }
1471 }
1472
Jamie Madilla3944d42016-07-22 22:13:26 -04001473 if ((readFormat.info->componentType == GL_INT ||
1474 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1475 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001476 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001477 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001478 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001479 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001480 }
He Yunchao66a41a22016-12-15 16:45:05 +08001481 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1482 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1483 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1484 // situation is an application error that would lead to a crash in ANGLE.
1485 else if (drawFramebuffer->hasEnabledDrawBuffer())
1486 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001487 context->handleError(
1488 InvalidOperation()
1489 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001490 return false;
1491 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001492 }
1493
He Yunchaoced53ae2016-11-29 15:00:51 +08001494 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001495 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1496 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001497 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001498 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001499 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001500 const gl::FramebufferAttachment *readBuffer =
1501 readFramebuffer->getAttachment(attachments[i]);
1502 const gl::FramebufferAttachment *drawBuffer =
1503 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001504
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001505 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001506 {
Kenneth Russell69382852017-07-21 16:38:44 -04001507 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001508 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001509 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001510 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001511 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001512
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001513 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001514 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001515 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001516 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001517 }
Geoff Lange4915782017-04-12 15:19:07 -04001518
1519 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001521 context->handleError(
1522 InvalidOperation()
1523 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001524 return false;
1525 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001526 }
He Yunchao66a41a22016-12-15 16:45:05 +08001527 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1528 else if (drawBuffer)
1529 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001530 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1531 "depth/stencil attachment of a "
1532 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001533 return false;
1534 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001535 }
1536 }
1537
Martin Radeva3ed4572017-07-27 18:29:37 +03001538 // ANGLE_multiview, Revision 1:
1539 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1540 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1541 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1542 {
1543 context->handleError(InvalidFramebufferOperation()
1544 << "Attempt to read from a multi-view framebuffer.");
1545 return false;
1546 }
1547 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1548 {
1549 context->handleError(InvalidFramebufferOperation()
1550 << "Attempt to write to a multi-view framebuffer.");
1551 return false;
1552 }
1553
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001554 return true;
1555}
1556
Jamie Madill4928b7c2017-06-20 12:57:39 -04001557bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001558 GLint x,
1559 GLint y,
1560 GLsizei width,
1561 GLsizei height,
1562 GLenum format,
1563 GLenum type,
1564 GLsizei bufSize,
1565 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001566 GLsizei *columns,
1567 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001568 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001569{
1570 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001571 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001572 return false;
1573 }
1574
Geoff Lang62fce5b2016-09-30 10:46:35 -04001575 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001576 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001577 {
Geoff Langb1196682014-07-23 13:47:29 -04001578 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001579 }
1580
Geoff Lang62fce5b2016-09-30 10:46:35 -04001581 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001582 {
Geoff Langb1196682014-07-23 13:47:29 -04001583 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001584 }
1585
Jamie Madillc29968b2016-01-20 11:17:23 -05001586 return true;
1587}
1588
1589bool ValidateReadnPixelsEXT(Context *context,
1590 GLint x,
1591 GLint y,
1592 GLsizei width,
1593 GLsizei height,
1594 GLenum format,
1595 GLenum type,
1596 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001597 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001598{
1599 if (bufSize < 0)
1600 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001601 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001602 return false;
1603 }
1604
Geoff Lang62fce5b2016-09-30 10:46:35 -04001605 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001606 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001607}
Jamie Madill26e91952014-03-05 15:01:27 -05001608
Jamie Madill4928b7c2017-06-20 12:57:39 -04001609bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001610 GLint x,
1611 GLint y,
1612 GLsizei width,
1613 GLsizei height,
1614 GLenum format,
1615 GLenum type,
1616 GLsizei bufSize,
1617 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001618 GLsizei *columns,
1619 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001620 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001621{
1622 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001623 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001624 return false;
1625 }
1626
Geoff Lange93daba2017-03-30 13:54:40 -04001627 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1628 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001629 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001630 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001631 }
1632
Geoff Lang62fce5b2016-09-30 10:46:35 -04001633 if (!ValidateRobustBufferSize(context, bufSize, *length))
1634 {
1635 return false;
1636 }
1637
1638 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001639}
1640
Jamie Madillf0e04492017-08-26 15:28:42 -04001641bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001642{
1643 if (!context->getExtensions().occlusionQueryBoolean &&
1644 !context->getExtensions().disjointTimerQuery)
1645 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001646 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001647 return false;
1648 }
1649
Olli Etuaho41997e72016-03-10 13:38:39 +02001650 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001651}
1652
Jamie Madillf0e04492017-08-26 15:28:42 -04001653bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001654{
1655 if (!context->getExtensions().occlusionQueryBoolean &&
1656 !context->getExtensions().disjointTimerQuery)
1657 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001658 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001659 return false;
1660 }
1661
Olli Etuaho41997e72016-03-10 13:38:39 +02001662 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001663}
1664
Jamie Madillf0e04492017-08-26 15:28:42 -04001665bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1666{
1667 if (!context->getExtensions().occlusionQueryBoolean &&
1668 !context->getExtensions().disjointTimerQuery)
1669 {
1670 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1671 return false;
1672 }
1673
1674 return true;
1675}
1676
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001677bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001678{
1679 if (!ValidQueryType(context, target))
1680 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001681 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001682 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001683 }
1684
1685 if (id == 0)
1686 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001687 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001688 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001689 }
1690
1691 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1692 // of zero, if the active query object name for <target> is non-zero (for the
1693 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1694 // the active query for either target is non-zero), if <id> is the name of an
1695 // existing query object whose type does not match <target>, or if <id> is the
1696 // active query object name for any query type, the error INVALID_OPERATION is
1697 // generated.
1698
1699 // Ensure no other queries are active
1700 // NOTE: If other queries than occlusion are supported, we will need to check
1701 // separately that:
1702 // a) The query ID passed is not the current active query for any target/type
1703 // b) There are no active queries for the requested target (and in the case
1704 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1705 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001706
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001707 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001708 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001709 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001710 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001711 }
1712
1713 Query *queryObject = context->getQuery(id, true, target);
1714
1715 // check that name was obtained with glGenQueries
1716 if (!queryObject)
1717 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001718 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001719 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001720 }
1721
1722 // check for type mismatch
1723 if (queryObject->getType() != target)
1724 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001725 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001726 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001727 }
1728
1729 return true;
1730}
1731
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001732bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1733{
1734 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001735 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001736 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001737 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001738 return false;
1739 }
1740
1741 return ValidateBeginQueryBase(context, target, id);
1742}
1743
1744bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001745{
1746 if (!ValidQueryType(context, target))
1747 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001748 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001749 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001750 }
1751
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001752 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001753
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001754 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001755 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001756 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001757 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001758 }
1759
Jamie Madill45c785d2014-05-13 14:09:34 -04001760 return true;
1761}
1762
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001763bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1764{
1765 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001766 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001767 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001768 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001769 return false;
1770 }
1771
1772 return ValidateEndQueryBase(context, target);
1773}
1774
1775bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1776{
1777 if (!context->getExtensions().disjointTimerQuery)
1778 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001779 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001780 return false;
1781 }
1782
1783 if (target != GL_TIMESTAMP_EXT)
1784 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001785 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001786 return false;
1787 }
1788
1789 Query *queryObject = context->getQuery(id, true, target);
1790 if (queryObject == nullptr)
1791 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001792 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001793 return false;
1794 }
1795
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001796 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001797 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001798 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001799 return false;
1800 }
1801
1802 return true;
1803}
1804
Geoff Lang2186c382016-10-14 10:54:54 -04001805bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001806{
Geoff Lang2186c382016-10-14 10:54:54 -04001807 if (numParams)
1808 {
1809 *numParams = 0;
1810 }
1811
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001812 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1813 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001814 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001815 return false;
1816 }
1817
1818 switch (pname)
1819 {
1820 case GL_CURRENT_QUERY_EXT:
1821 if (target == GL_TIMESTAMP_EXT)
1822 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001823 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001824 return false;
1825 }
1826 break;
1827 case GL_QUERY_COUNTER_BITS_EXT:
1828 if (!context->getExtensions().disjointTimerQuery ||
1829 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1830 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001831 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001832 return false;
1833 }
1834 break;
1835 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001836 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001837 return false;
1838 }
1839
Geoff Lang2186c382016-10-14 10:54:54 -04001840 if (numParams)
1841 {
1842 // All queries return only one value
1843 *numParams = 1;
1844 }
1845
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001846 return true;
1847}
1848
1849bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1850{
1851 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001852 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001853 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001854 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001855 return false;
1856 }
1857
Geoff Lang2186c382016-10-14 10:54:54 -04001858 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001859}
1860
Geoff Lang2186c382016-10-14 10:54:54 -04001861bool ValidateGetQueryivRobustANGLE(Context *context,
1862 GLenum target,
1863 GLenum pname,
1864 GLsizei bufSize,
1865 GLsizei *length,
1866 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001867{
Geoff Lang2186c382016-10-14 10:54:54 -04001868 if (!ValidateRobustEntryPoint(context, bufSize))
1869 {
1870 return false;
1871 }
1872
1873 if (!ValidateGetQueryivBase(context, target, pname, length))
1874 {
1875 return false;
1876 }
1877
1878 if (!ValidateRobustBufferSize(context, bufSize, *length))
1879 {
1880 return false;
1881 }
1882
1883 return true;
1884}
1885
1886bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1887{
1888 if (numParams)
1889 {
1890 *numParams = 0;
1891 }
1892
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001893 Query *queryObject = context->getQuery(id, false, GL_NONE);
1894
1895 if (!queryObject)
1896 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001897 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001898 return false;
1899 }
1900
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001901 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001902 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001903 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001904 return false;
1905 }
1906
1907 switch (pname)
1908 {
1909 case GL_QUERY_RESULT_EXT:
1910 case GL_QUERY_RESULT_AVAILABLE_EXT:
1911 break;
1912
1913 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001914 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001915 return false;
1916 }
1917
Geoff Lang2186c382016-10-14 10:54:54 -04001918 if (numParams)
1919 {
1920 *numParams = 1;
1921 }
1922
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001923 return true;
1924}
1925
1926bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1927{
1928 if (!context->getExtensions().disjointTimerQuery)
1929 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001930 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001931 return false;
1932 }
Geoff Lang2186c382016-10-14 10:54:54 -04001933 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1934}
1935
1936bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1937 GLuint id,
1938 GLenum pname,
1939 GLsizei bufSize,
1940 GLsizei *length,
1941 GLint *params)
1942{
1943 if (!context->getExtensions().disjointTimerQuery)
1944 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001945 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001946 return false;
1947 }
1948
1949 if (!ValidateRobustEntryPoint(context, bufSize))
1950 {
1951 return false;
1952 }
1953
1954 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1955 {
1956 return false;
1957 }
1958
1959 if (!ValidateRobustBufferSize(context, bufSize, *length))
1960 {
1961 return false;
1962 }
1963
1964 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001965}
1966
1967bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1968{
1969 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001970 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001971 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001972 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001973 return false;
1974 }
Geoff Lang2186c382016-10-14 10:54:54 -04001975 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1976}
1977
1978bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1979 GLuint id,
1980 GLenum pname,
1981 GLsizei bufSize,
1982 GLsizei *length,
1983 GLuint *params)
1984{
1985 if (!context->getExtensions().disjointTimerQuery &&
1986 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1987 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001988 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001989 return false;
1990 }
1991
1992 if (!ValidateRobustEntryPoint(context, bufSize))
1993 {
1994 return false;
1995 }
1996
1997 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1998 {
1999 return false;
2000 }
2001
2002 if (!ValidateRobustBufferSize(context, bufSize, *length))
2003 {
2004 return false;
2005 }
2006
2007 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002008}
2009
2010bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2011{
2012 if (!context->getExtensions().disjointTimerQuery)
2013 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002014 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002015 return false;
2016 }
Geoff Lang2186c382016-10-14 10:54:54 -04002017 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2018}
2019
2020bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2021 GLuint id,
2022 GLenum pname,
2023 GLsizei bufSize,
2024 GLsizei *length,
2025 GLint64 *params)
2026{
2027 if (!context->getExtensions().disjointTimerQuery)
2028 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002029 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002030 return false;
2031 }
2032
2033 if (!ValidateRobustEntryPoint(context, bufSize))
2034 {
2035 return false;
2036 }
2037
2038 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2039 {
2040 return false;
2041 }
2042
2043 if (!ValidateRobustBufferSize(context, bufSize, *length))
2044 {
2045 return false;
2046 }
2047
2048 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002049}
2050
2051bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2052{
2053 if (!context->getExtensions().disjointTimerQuery)
2054 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002055 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002056 return false;
2057 }
Geoff Lang2186c382016-10-14 10:54:54 -04002058 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2059}
2060
2061bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2062 GLuint id,
2063 GLenum pname,
2064 GLsizei bufSize,
2065 GLsizei *length,
2066 GLuint64 *params)
2067{
2068 if (!context->getExtensions().disjointTimerQuery)
2069 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002070 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002071 return false;
2072 }
2073
2074 if (!ValidateRobustEntryPoint(context, bufSize))
2075 {
2076 return false;
2077 }
2078
2079 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2080 {
2081 return false;
2082 }
2083
2084 if (!ValidateRobustBufferSize(context, bufSize, *length))
2085 {
2086 return false;
2087 }
2088
2089 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002090}
2091
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002092bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002093 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002094 GLuint program,
2095 GLint location,
2096 GLsizei count)
2097{
2098 // Check for ES31 program uniform entry points
2099 if (context->getClientVersion() < Version(3, 1))
2100 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002101 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002102 return false;
2103 }
2104
2105 const LinkedUniform *uniform = nullptr;
2106 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002107 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2108 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002109}
2110
Frank Henigmana98a6472017-02-02 21:38:32 -05002111bool ValidateProgramUniform1iv(gl::Context *context,
2112 GLuint program,
2113 GLint location,
2114 GLsizei count,
2115 const GLint *value)
2116{
2117 // Check for ES31 program uniform entry points
2118 if (context->getClientVersion() < Version(3, 1))
2119 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002120 context->handleError(InvalidOperation());
Frank Henigmana98a6472017-02-02 21:38:32 -05002121 return false;
2122 }
2123
2124 const LinkedUniform *uniform = nullptr;
2125 gl::Program *programObject = GetValidProgram(context, program);
2126 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2127 ValidateUniform1ivValue(context, uniform->type, count, value);
2128}
2129
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002130bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002131 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002132 GLuint program,
2133 GLint location,
2134 GLsizei count,
2135 GLboolean transpose)
2136{
2137 // Check for ES31 program uniform entry points
2138 if (context->getClientVersion() < Version(3, 1))
2139 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002140 context->handleError(InvalidOperation());
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002141 return false;
2142 }
2143
2144 const LinkedUniform *uniform = nullptr;
2145 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002146 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2147 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002148}
2149
Jamie Madillc1d770e2017-04-13 17:31:24 -04002150bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002151{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002152 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002153 gl::Program *programObject = context->getGLState().getProgram();
2154 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2155 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002156}
2157
Jamie Madillbe849e42017-05-02 15:49:00 -04002158bool ValidateUniform1iv(ValidationContext *context,
2159 GLint location,
2160 GLsizei count,
2161 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002162{
2163 const LinkedUniform *uniform = nullptr;
2164 gl::Program *programObject = context->getGLState().getProgram();
2165 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2166 ValidateUniform1ivValue(context, uniform->type, count, value);
2167}
2168
Jamie Madillc1d770e2017-04-13 17:31:24 -04002169bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002170 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002171 GLint location,
2172 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002173 GLboolean transpose)
2174{
Martin Radev1be913c2016-07-11 17:59:16 +03002175 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002176 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002177 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002178 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002179 }
2180
Jamie Madill62d31cb2015-09-11 13:25:51 -04002181 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002182 gl::Program *programObject = context->getGLState().getProgram();
2183 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2184 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002185}
2186
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002187bool ValidateStateQuery(ValidationContext *context,
2188 GLenum pname,
2189 GLenum *nativeType,
2190 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002191{
2192 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2193 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002194 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002195 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002196 }
2197
Jamie Madill0af26e12015-03-05 19:54:33 -05002198 const Caps &caps = context->getCaps();
2199
Jamie Madill893ab082014-05-16 16:56:10 -04002200 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2201 {
2202 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2203
Jamie Madill0af26e12015-03-05 19:54:33 -05002204 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002205 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002206 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002207 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002208 }
2209 }
2210
2211 switch (pname)
2212 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002213 case GL_TEXTURE_BINDING_2D:
2214 case GL_TEXTURE_BINDING_CUBE_MAP:
2215 case GL_TEXTURE_BINDING_3D:
2216 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002217 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002218 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002219 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2220 if (!context->getExtensions().textureRectangle)
2221 {
2222 context->handleError(InvalidEnum()
2223 << "ANGLE_texture_rectangle extension not present");
2224 return false;
2225 }
2226 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002227 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2228 if (!context->getExtensions().eglStreamConsumerExternal &&
2229 !context->getExtensions().eglImageExternal)
2230 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002231 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2232 "nor GL_OES_EGL_image_external "
2233 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002234 return false;
2235 }
2236 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002237
He Yunchaoced53ae2016-11-29 15:00:51 +08002238 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2239 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002240 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002241 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2242 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002243 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002244 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002245 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002246 }
2247
Jamie Madill51f40ec2016-06-15 14:06:00 -04002248 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2249 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002250
2251 if (framebuffer->getReadBufferState() == GL_NONE)
2252 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002253 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002254 return false;
2255 }
2256
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002257 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002258 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002259 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002260 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002261 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002262 }
2263 }
2264 break;
2265
He Yunchaoced53ae2016-11-29 15:00:51 +08002266 default:
2267 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002268 }
2269
2270 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002271 if (*numParams == 0)
2272 {
2273 return false;
2274 }
2275
2276 return true;
2277}
2278
2279bool ValidateRobustStateQuery(ValidationContext *context,
2280 GLenum pname,
2281 GLsizei bufSize,
2282 GLenum *nativeType,
2283 unsigned int *numParams)
2284{
2285 if (!ValidateRobustEntryPoint(context, bufSize))
2286 {
2287 return false;
2288 }
2289
2290 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2291 {
2292 return false;
2293 }
2294
2295 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002296 {
2297 return false;
2298 }
2299
2300 return true;
2301}
2302
Jamie Madillc29968b2016-01-20 11:17:23 -05002303bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2304 GLenum target,
2305 GLint level,
2306 GLenum internalformat,
2307 bool isSubImage,
2308 GLint xoffset,
2309 GLint yoffset,
2310 GLint zoffset,
2311 GLint x,
2312 GLint y,
2313 GLsizei width,
2314 GLsizei height,
2315 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002316 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002317{
Brandon Jones6cad5662017-06-14 13:25:13 -07002318 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002319 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002320 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2321 return false;
2322 }
2323
2324 if (width < 0 || height < 0)
2325 {
2326 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002327 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002328 }
2329
He Yunchaoced53ae2016-11-29 15:00:51 +08002330 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2331 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002332 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002333 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002334 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002335 }
2336
2337 if (border != 0)
2338 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002339 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002340 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002341 }
2342
2343 if (!ValidMipLevel(context, target, level))
2344 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002345 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002346 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002347 }
2348
Jamie Madill51f40ec2016-06-15 14:06:00 -04002349 const auto &state = context->getGLState();
2350 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002351 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002352 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002353 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002354 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002355 }
2356
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002357 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002358 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002359 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002360 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002361 }
2362
Martin Radev138064f2016-07-15 12:03:41 +03002363 if (readFramebuffer->getReadBufferState() == GL_NONE)
2364 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002365 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002366 return false;
2367 }
2368
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002369 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2370 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002371 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002372 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002373 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2374 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002375 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002376 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002377 return false;
2378 }
2379
Martin Radev04e2c3b2017-07-27 16:54:35 +03002380 // ANGLE_multiview spec, Revision 1:
2381 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2382 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2383 // is not NONE.
2384 if (source->getMultiviewLayout() != GL_NONE)
2385 {
2386 context->handleError(InvalidFramebufferOperation()
2387 << "The active read framebuffer object has multiview attachments.");
2388 return false;
2389 }
2390
Geoff Langaae65a42014-05-26 12:43:44 -04002391 const gl::Caps &caps = context->getCaps();
2392
Geoff Langaae65a42014-05-26 12:43:44 -04002393 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002394 switch (target)
2395 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002396 case GL_TEXTURE_2D:
2397 maxDimension = caps.max2DTextureSize;
2398 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002399
He Yunchaoced53ae2016-11-29 15:00:51 +08002400 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2401 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2402 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2403 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2404 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2405 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2406 maxDimension = caps.maxCubeMapTextureSize;
2407 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002408
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002409 case GL_TEXTURE_RECTANGLE_ANGLE:
2410 maxDimension = caps.maxRectangleTextureSize;
2411 break;
2412
He Yunchaoced53ae2016-11-29 15:00:51 +08002413 case GL_TEXTURE_2D_ARRAY:
2414 maxDimension = caps.max2DTextureSize;
2415 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002416
He Yunchaoced53ae2016-11-29 15:00:51 +08002417 case GL_TEXTURE_3D:
2418 maxDimension = caps.max3DTextureSize;
2419 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002420
He Yunchaoced53ae2016-11-29 15:00:51 +08002421 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002422 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002423 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002424 }
2425
Jamie Madillc29968b2016-01-20 11:17:23 -05002426 gl::Texture *texture =
2427 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002428 if (!texture)
2429 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002430 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002431 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002432 }
2433
Geoff Lang69cce582015-09-17 13:20:36 -04002434 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002435 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002436 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002437 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002438 }
2439
Geoff Langca271392017-04-05 12:30:00 -04002440 const gl::InternalFormat &formatInfo =
2441 gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002442
Geoff Lang966c9402017-04-18 12:38:27 -04002443 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002444 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002445 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002446 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002447 }
2448
2449 if (isSubImage)
2450 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002451 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2452 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2453 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002454 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002455 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002456 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002457 }
2458 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002459 else
2460 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002461 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002462 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002463 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002464 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002465 }
2466
Geoff Langeb66a6e2016-10-31 13:06:12 -04002467 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002468 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002469 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002470 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002471 }
2472
2473 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002474 if (static_cast<int>(width) > maxLevelDimension ||
2475 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002476 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002477 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002478 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002479 }
2480 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002481
Jamie Madill0c8abca2016-07-22 20:21:26 -04002482 if (textureFormatOut)
2483 {
2484 *textureFormatOut = texture->getFormat(target, level);
2485 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002486
2487 // Detect texture copying feedback loops for WebGL.
2488 if (context->getExtensions().webglCompatibility)
2489 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002490 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002491 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002492 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002493 return false;
2494 }
2495 }
2496
Jamie Madill560a8d82014-05-21 13:06:20 -04002497 return true;
2498}
2499
Jiajia Qind9671222016-11-29 16:30:31 +08002500bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002501{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002502 switch (mode)
2503 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002504 case GL_POINTS:
2505 case GL_LINES:
2506 case GL_LINE_LOOP:
2507 case GL_LINE_STRIP:
2508 case GL_TRIANGLES:
2509 case GL_TRIANGLE_STRIP:
2510 case GL_TRIANGLE_FAN:
2511 break;
2512 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002513 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002514 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002515 }
2516
Jamie Madill250d33f2014-06-06 17:09:03 -04002517 if (count < 0)
2518 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002519 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002520 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002521 }
2522
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002523 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002524
Jamie Madill250d33f2014-06-06 17:09:03 -04002525 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002526 if (state.hasMappedBuffer(GL_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002527 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002528 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002529 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002530 }
2531
Jamie Madillcbcde722017-01-06 14:50:00 -05002532 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2533 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002534 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002535 const Extensions &extensions = context->getExtensions();
2536 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002537 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002538 const FramebufferAttachment *dsAttachment =
2539 framebuffer->getStencilOrDepthStencilAttachment();
2540 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002541 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002542 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002543
2544 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2545 bool differentWritemasks =
2546 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2547 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2548 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2549 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2550
2551 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002552 {
Martin Radevffe754b2017-07-31 10:38:07 +03002553 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002554 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002555 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2556 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002557 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002558 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002559 return false;
2560 }
Jamie Madillac528012014-06-20 13:21:23 -04002561 }
2562
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002563 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002564 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002565 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002566 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002567 }
2568
Geoff Lang7dd2e102014-11-10 15:19:26 -05002569 gl::Program *program = state.getProgram();
2570 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002571 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002572 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002573 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002574 }
2575
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002576 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002577 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002578 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002579 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002580 }
2581
Martin Radevffe754b2017-07-31 10:38:07 +03002582 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002583 {
Martin Radev7e69f762017-07-27 14:54:13 +03002584 const int programNumViews = program->getNumViews();
2585 const int framebufferNumViews = framebuffer->getNumViews();
2586 if (programNumViews != -1 && framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002587 {
2588 context->handleError(InvalidOperation() << "The number of views in the active program "
2589 "and draw framebuffer does not match.");
2590 return false;
2591 }
Martin Radev7e69f762017-07-27 14:54:13 +03002592
2593 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2594 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2595 framebufferNumViews > 1)
2596 {
2597 context->handleError(InvalidOperation()
2598 << "There is an active transform feedback object "
2599 "when the number of views in the active draw "
2600 "framebuffer is greater than 1.");
2601 return false;
2602 }
Martin Radevffe754b2017-07-31 10:38:07 +03002603
2604 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2605 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2606 {
2607 context->handleError(InvalidOperation() << "There is an active query for target "
2608 "GL_TIME_ELAPSED_EXT when the number of "
2609 "views in the active draw framebuffer is "
2610 "greater than 1.");
2611 return false;
2612 }
Martin Radev7cf61662017-07-26 17:10:53 +03002613 }
2614
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002615 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002616 for (unsigned int uniformBlockIndex = 0;
2617 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002618 {
Jamie Madill62d31cb2015-09-11 13:25:51 -04002619 const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002620 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002621 const OffsetBindingPointer<Buffer> &uniformBuffer =
2622 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002623
Geoff Lang5d124a62015-09-15 13:03:27 -04002624 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002625 {
2626 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002627 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002628 InvalidOperation()
2629 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002630 return false;
2631 }
2632
Geoff Lang5d124a62015-09-15 13:03:27 -04002633 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002634 if (uniformBufferSize == 0)
2635 {
2636 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002637 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002638 }
2639
Jamie Madill62d31cb2015-09-11 13:25:51 -04002640 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002641 {
2642 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002643 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002644 InvalidOperation()
2645 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002646 return false;
2647 }
2648 }
2649
Geoff Lange0cff192017-05-30 13:04:56 -04002650 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002651 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002652 {
Geoff Lange0cff192017-05-30 13:04:56 -04002653 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002654 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2655 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002656 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002657 return false;
2658 }
Geoff Lange0cff192017-05-30 13:04:56 -04002659
Geoff Lang9ab5b822017-05-30 16:19:23 -04002660 // Detect that the vertex shader input types match the attribute types
2661 if (!ValidateVertexShaderAttributeTypeMatch(context))
2662 {
2663 return false;
2664 }
2665
Geoff Lange0cff192017-05-30 13:04:56 -04002666 // Detect that the color buffer types match the fragment shader output types
2667 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2668 {
2669 return false;
2670 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002671 }
2672
Jamie Madill250d33f2014-06-06 17:09:03 -04002673 // No-op if zero count
2674 return (count > 0);
2675}
2676
Jamie Madillc1d770e2017-04-13 17:31:24 -04002677bool ValidateDrawArraysCommon(ValidationContext *context,
2678 GLenum mode,
2679 GLint first,
2680 GLsizei count,
2681 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002682{
Jamie Madillfd716582014-06-06 17:09:04 -04002683 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002684 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002685 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002686 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002687 }
2688
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002689 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002690 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002691 if (curTransformFeedback && curTransformFeedback->isActive() &&
2692 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002693 {
2694 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002695 // that does not match the current transform feedback object's draw mode (if transform
2696 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002697 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002698 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002699 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002700 }
2701
Jiajia Qind9671222016-11-29 16:30:31 +08002702 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002703 {
2704 return false;
2705 }
2706
Corentin Wallez71168a02016-12-19 15:11:18 -08002707 // Check the computation of maxVertex doesn't overflow.
2708 // - first < 0 or count < 0 have been checked as an error condition
2709 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2710 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2711 ASSERT(count > 0 && first >= 0);
2712 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2713 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002714 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002715 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002716 return false;
2717 }
2718
Corentin Wallez71168a02016-12-19 15:11:18 -08002719 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002720 {
2721 return false;
2722 }
2723
2724 return true;
2725}
2726
He Yunchaoced53ae2016-11-29 15:00:51 +08002727bool ValidateDrawArraysInstancedANGLE(Context *context,
2728 GLenum mode,
2729 GLint first,
2730 GLsizei count,
2731 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002732{
Corentin Wallez170efbf2017-05-02 13:45:01 -04002733 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002734 {
2735 return false;
2736 }
2737
Corentin Wallez0dc97812017-06-22 14:38:44 -04002738 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002739}
2740
Jiajia Qind9671222016-11-29 16:30:31 +08002741bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002742{
Jamie Madill250d33f2014-06-06 17:09:03 -04002743 switch (type)
2744 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002745 case GL_UNSIGNED_BYTE:
2746 case GL_UNSIGNED_SHORT:
2747 break;
2748 case GL_UNSIGNED_INT:
2749 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2750 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002751 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002752 return false;
2753 }
2754 break;
2755 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002756 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002757 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002758 }
2759
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002760 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002761
2762 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002763 if (curTransformFeedback && curTransformFeedback->isActive() &&
2764 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002765 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002766 // It is an invalid operation to call DrawElements, DrawRangeElements or
2767 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002768 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002769 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002770 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002771 }
2772
Jiajia Qind9671222016-11-29 16:30:31 +08002773 return true;
2774}
2775
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002776bool ValidateDrawElementsCommon(ValidationContext *context,
2777 GLenum mode,
2778 GLsizei count,
2779 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002780 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002781 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002782{
2783 if (!ValidateDrawElementsBase(context, type))
2784 return false;
2785
2786 const State &state = context->getGLState();
2787
Corentin Wallez170efbf2017-05-02 13:45:01 -04002788 if (!ValidateDrawBase(context, mode, count))
2789 {
2790 return false;
2791 }
2792
Jamie Madill250d33f2014-06-06 17:09:03 -04002793 // Check for mapped buffers
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002794 if (state.hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER))
Jamie Madill250d33f2014-06-06 17:09:03 -04002795 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002796 context->handleError(InvalidOperation() << "Index buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -04002797 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002798 }
2799
He Yunchaoced53ae2016-11-29 15:00:51 +08002800 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002801 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002802
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002803 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2804
2805 if (context->getExtensions().webglCompatibility)
2806 {
2807 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2808 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2809 {
2810 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2811 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2812 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002813 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002814 return false;
2815 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002816
2817 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2818 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2819 // error is generated.
2820 if (reinterpret_cast<intptr_t>(indices) < 0)
2821 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002822 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002823 return false;
2824 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002825 }
2826
2827 if (context->getExtensions().webglCompatibility ||
2828 !context->getGLState().areClientArraysEnabled())
2829 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002830 if (!elementArrayBuffer && count > 0)
2831 {
2832 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2833 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2834 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002835 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002836 return false;
2837 }
2838 }
2839
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002840 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002841 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002842 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002843 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002844 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2845 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2846 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2847 constexpr uint64_t kMaxTypeSize = 8;
2848 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2849 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2850 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002851
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002852 uint64_t typeSize = typeBytes;
2853 uint64_t elementCount = static_cast<uint64_t>(count);
2854 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2855
2856 // Doing the multiplication here is overflow-safe
2857 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2858
2859 // The offset can be any value, check for overflows
2860 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2861 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002862 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002863 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002864 return false;
2865 }
2866
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002867 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2868 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002869 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002870 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002871 return false;
2872 }
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002873
Corentin Wallez487653b2017-09-01 17:17:55 -04002874 ASSERT(isPow2(typeSize) && typeSize > 0);
2875 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002876 {
2877 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
2878 return false;
2879 }
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002880 }
2881 else if (!indices)
2882 {
2883 // This is an application error that would normally result in a crash,
2884 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002885 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04002886 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002887 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002888 }
2889
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002890 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002891 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002892 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2893 // access is enabled.
2894 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2895 {
2896 return false;
2897 }
2898 }
2899 else
2900 {
2901 // Use the parameter buffer to retrieve and cache the index range.
2902 const auto &params = context->getParams<HasIndexRange>();
2903 const auto &indexRangeOpt = params.getIndexRange();
2904 if (!indexRangeOpt.valid())
2905 {
2906 // Unexpected error.
2907 return false;
2908 }
2909
2910 // If we use an index greater than our maximum supported index range, return an error.
2911 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2912 // return an error if possible here.
2913 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2914 {
2915 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2916 return false;
2917 }
2918
2919 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2920 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2921 {
2922 return false;
2923 }
2924
2925 // No op if there are no real indices in the index data (all are primitive restart).
2926 return (indexRangeOpt.value().vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002927 }
2928
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002929 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002930}
2931
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002932bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2933 GLenum mode,
2934 GLsizei count,
2935 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002936 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002937 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002938{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002939 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002940}
2941
Geoff Lang3edfe032015-09-04 16:38:24 -04002942bool ValidateDrawElementsInstancedANGLE(Context *context,
2943 GLenum mode,
2944 GLsizei count,
2945 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002946 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002947 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002948{
Corentin Wallez170efbf2017-05-02 13:45:01 -04002949 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002950 {
2951 return false;
2952 }
2953
Corentin Wallez0dc97812017-06-22 14:38:44 -04002954 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002955}
2956
He Yunchaoced53ae2016-11-29 15:00:51 +08002957bool ValidateFramebufferTextureBase(Context *context,
2958 GLenum target,
2959 GLenum attachment,
2960 GLuint texture,
2961 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002962{
Jamie Madill55ec3b12014-07-03 10:38:57 -04002963 if (!ValidFramebufferTarget(target))
2964 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002965 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002966 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002967 }
2968
2969 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002970 {
2971 return false;
2972 }
2973
Jamie Madill55ec3b12014-07-03 10:38:57 -04002974 if (texture != 0)
2975 {
2976 gl::Texture *tex = context->getTexture(texture);
2977
Jamie Madillbe849e42017-05-02 15:49:00 -04002978 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002979 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002980 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002981 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002982 }
2983
2984 if (level < 0)
2985 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002986 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002987 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002988 }
2989 }
2990
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002991 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002992 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002993
Jamie Madill84115c92015-04-23 15:00:07 -04002994 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002995 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002996 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002997 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002998 }
2999
3000 return true;
3001}
3002
Geoff Langb1196682014-07-23 13:47:29 -04003003bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003004{
3005 if (program == 0)
3006 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003007 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003008 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003009 }
3010
Dian Xiang769769a2015-09-09 15:20:08 -07003011 gl::Program *programObject = GetValidProgram(context, program);
3012 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003013 {
3014 return false;
3015 }
3016
Jamie Madill0063c512014-08-25 15:47:53 -04003017 if (!programObject || !programObject->isLinked())
3018 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003019 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003020 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003021 }
3022
Geoff Lang7dd2e102014-11-10 15:19:26 -05003023 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003024 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003025 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003026 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003027 }
3028
Jamie Madill0063c512014-08-25 15:47:53 -04003029 return true;
3030}
3031
Geoff Langf41d0ee2016-10-07 13:04:23 -04003032static bool ValidateSizedGetUniform(Context *context,
3033 GLuint program,
3034 GLint location,
3035 GLsizei bufSize,
3036 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003037{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003038 if (length)
3039 {
3040 *length = 0;
3041 }
3042
Jamie Madill78f41802014-08-25 15:47:55 -04003043 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003044 {
Jamie Madill78f41802014-08-25 15:47:55 -04003045 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003046 }
3047
Geoff Langf41d0ee2016-10-07 13:04:23 -04003048 if (bufSize < 0)
3049 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003050 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003051 return false;
3052 }
3053
Jamie Madilla502c742014-08-28 17:19:13 -04003054 gl::Program *programObject = context->getProgram(program);
3055 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003056
Jamie Madill78f41802014-08-25 15:47:55 -04003057 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003058 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003059 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003060 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003061 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003062 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003063 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003064 }
3065
Geoff Langf41d0ee2016-10-07 13:04:23 -04003066 if (length)
3067 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003068 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003069 }
3070
Jamie Madill0063c512014-08-25 15:47:53 -04003071 return true;
3072}
3073
He Yunchaoced53ae2016-11-29 15:00:51 +08003074bool ValidateGetnUniformfvEXT(Context *context,
3075 GLuint program,
3076 GLint location,
3077 GLsizei bufSize,
3078 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003079{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003080 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003081}
3082
He Yunchaoced53ae2016-11-29 15:00:51 +08003083bool ValidateGetnUniformivEXT(Context *context,
3084 GLuint program,
3085 GLint location,
3086 GLsizei bufSize,
3087 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003088{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003089 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3090}
3091
3092bool ValidateGetUniformfvRobustANGLE(Context *context,
3093 GLuint program,
3094 GLint location,
3095 GLsizei bufSize,
3096 GLsizei *length,
3097 GLfloat *params)
3098{
3099 if (!ValidateRobustEntryPoint(context, bufSize))
3100 {
3101 return false;
3102 }
3103
3104 // bufSize is validated in ValidateSizedGetUniform
3105 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3106}
3107
3108bool ValidateGetUniformivRobustANGLE(Context *context,
3109 GLuint program,
3110 GLint location,
3111 GLsizei bufSize,
3112 GLsizei *length,
3113 GLint *params)
3114{
3115 if (!ValidateRobustEntryPoint(context, bufSize))
3116 {
3117 return false;
3118 }
3119
3120 // bufSize is validated in ValidateSizedGetUniform
3121 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3122}
3123
3124bool ValidateGetUniformuivRobustANGLE(Context *context,
3125 GLuint program,
3126 GLint location,
3127 GLsizei bufSize,
3128 GLsizei *length,
3129 GLuint *params)
3130{
3131 if (!ValidateRobustEntryPoint(context, bufSize))
3132 {
3133 return false;
3134 }
3135
3136 if (context->getClientMajorVersion() < 3)
3137 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003138 context->handleError(InvalidOperation() << "Entry point requires at least OpenGL ES 3.0.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003139 return false;
3140 }
3141
3142 // bufSize is validated in ValidateSizedGetUniform
3143 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003144}
3145
He Yunchaoced53ae2016-11-29 15:00:51 +08003146bool ValidateDiscardFramebufferBase(Context *context,
3147 GLenum target,
3148 GLsizei numAttachments,
3149 const GLenum *attachments,
3150 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003151{
3152 if (numAttachments < 0)
3153 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003154 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003155 return false;
3156 }
3157
3158 for (GLsizei i = 0; i < numAttachments; ++i)
3159 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003160 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003161 {
3162 if (defaultFramebuffer)
3163 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003164 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003165 return false;
3166 }
3167
3168 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3169 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003170 context->handleError(InvalidOperation() << "Requested color attachment is "
3171 "greater than the maximum supported "
3172 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003173 return false;
3174 }
3175 }
3176 else
3177 {
3178 switch (attachments[i])
3179 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003180 case GL_DEPTH_ATTACHMENT:
3181 case GL_STENCIL_ATTACHMENT:
3182 case GL_DEPTH_STENCIL_ATTACHMENT:
3183 if (defaultFramebuffer)
3184 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003185 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3186 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003187 return false;
3188 }
3189 break;
3190 case GL_COLOR:
3191 case GL_DEPTH:
3192 case GL_STENCIL:
3193 if (!defaultFramebuffer)
3194 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003195 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3196 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003197 return false;
3198 }
3199 break;
3200 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003201 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003202 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003203 }
3204 }
3205 }
3206
3207 return true;
3208}
3209
Austin Kinross6ee1e782015-05-29 17:05:37 -07003210bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3211{
3212 // Note that debug marker calls must not set error state
3213
3214 if (length < 0)
3215 {
3216 return false;
3217 }
3218
3219 if (marker == nullptr)
3220 {
3221 return false;
3222 }
3223
3224 return true;
3225}
3226
3227bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3228{
3229 // Note that debug marker calls must not set error state
3230
3231 if (length < 0)
3232 {
3233 return false;
3234 }
3235
3236 if (length > 0 && marker == nullptr)
3237 {
3238 return false;
3239 }
3240
3241 return true;
3242}
3243
Geoff Langdcab33b2015-07-21 13:03:16 -04003244bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003245 GLenum target,
3246 egl::Image *image)
3247{
Geoff Langa8406172015-07-21 16:53:39 -04003248 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3249 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003250 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003251 return false;
3252 }
3253
3254 switch (target)
3255 {
3256 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003257 if (!context->getExtensions().eglImage)
3258 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003259 context->handleError(InvalidEnum()
3260 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003261 }
3262 break;
3263
3264 case GL_TEXTURE_EXTERNAL_OES:
3265 if (!context->getExtensions().eglImageExternal)
3266 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003267 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3268 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003269 }
Geoff Langa8406172015-07-21 16:53:39 -04003270 break;
3271
3272 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003273 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003274 return false;
3275 }
3276
Jamie Madill61e16b42017-06-19 11:13:23 -04003277 ASSERT(context->getCurrentDisplay());
3278 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003279 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003280 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003281 return false;
3282 }
3283
3284 if (image->getSamples() > 0)
3285 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003286 context->handleError(InvalidOperation()
3287 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003288 return false;
3289 }
3290
Geoff Langca271392017-04-05 12:30:00 -04003291 const TextureCaps &textureCaps =
3292 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003293 if (!textureCaps.texturable)
3294 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003295 context->handleError(InvalidOperation()
3296 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003297 return false;
3298 }
3299
Geoff Langdcab33b2015-07-21 13:03:16 -04003300 return true;
3301}
3302
3303bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003304 GLenum target,
3305 egl::Image *image)
3306{
Geoff Langa8406172015-07-21 16:53:39 -04003307 if (!context->getExtensions().eglImage)
3308 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003309 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003310 return false;
3311 }
3312
3313 switch (target)
3314 {
3315 case GL_RENDERBUFFER:
3316 break;
3317
3318 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003319 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003320 return false;
3321 }
3322
Jamie Madill61e16b42017-06-19 11:13:23 -04003323 ASSERT(context->getCurrentDisplay());
3324 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003325 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003326 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003327 return false;
3328 }
3329
Geoff Langca271392017-04-05 12:30:00 -04003330 const TextureCaps &textureCaps =
3331 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003332 if (!textureCaps.renderable)
3333 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003334 context->handleError(InvalidOperation()
3335 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003336 return false;
3337 }
3338
Geoff Langdcab33b2015-07-21 13:03:16 -04003339 return true;
3340}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003341
3342bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3343{
Geoff Lang36167ab2015-12-07 10:27:14 -05003344 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003345 {
3346 // The default VAO should always exist
3347 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003348 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003349 return false;
3350 }
3351
3352 return true;
3353}
3354
Geoff Langc5629752015-12-07 16:29:04 -05003355bool ValidateProgramBinaryBase(Context *context,
3356 GLuint program,
3357 GLenum binaryFormat,
3358 const void *binary,
3359 GLint length)
3360{
3361 Program *programObject = GetValidProgram(context, program);
3362 if (programObject == nullptr)
3363 {
3364 return false;
3365 }
3366
3367 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3368 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3369 programBinaryFormats.end())
3370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003371 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003372 return false;
3373 }
3374
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003375 if (context->hasActiveTransformFeedback(program))
3376 {
3377 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003378 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3379 "is associated with an active transform "
3380 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003381 return false;
3382 }
3383
Geoff Langc5629752015-12-07 16:29:04 -05003384 return true;
3385}
3386
3387bool ValidateGetProgramBinaryBase(Context *context,
3388 GLuint program,
3389 GLsizei bufSize,
3390 GLsizei *length,
3391 GLenum *binaryFormat,
3392 void *binary)
3393{
3394 Program *programObject = GetValidProgram(context, program);
3395 if (programObject == nullptr)
3396 {
3397 return false;
3398 }
3399
3400 if (!programObject->isLinked())
3401 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003402 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003403 return false;
3404 }
3405
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003406 if (context->getCaps().programBinaryFormats.empty())
3407 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003408 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003409 return false;
3410 }
3411
Geoff Langc5629752015-12-07 16:29:04 -05003412 return true;
3413}
Jamie Madillc29968b2016-01-20 11:17:23 -05003414
Jamie Madillc29968b2016-01-20 11:17:23 -05003415bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3416{
3417 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003418 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003419 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003420 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3421 return false;
3422 }
3423 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3424 {
3425 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003426 return false;
3427 }
3428
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003429 ASSERT(context->getGLState().getDrawFramebuffer());
3430 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003431 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3432
3433 // This should come first before the check for the default frame buffer
3434 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3435 // rather than INVALID_OPERATION
3436 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3437 {
3438 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3439
3440 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003441 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3442 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003443 {
3444 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003445 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3446 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3447 // 3.1 is still a bit ambiguous about the error, but future specs are
3448 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003449 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003450 return false;
3451 }
3452 else if (bufs[colorAttachment] >= maxColorAttachment)
3453 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003454 context->handleError(InvalidOperation()
3455 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003456 return false;
3457 }
3458 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3459 frameBufferId != 0)
3460 {
3461 // INVALID_OPERATION-GL is bound to buffer and ith argument
3462 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003463 context->handleError(InvalidOperation()
3464 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003465 return false;
3466 }
3467 }
3468
3469 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3470 // and n is not 1 or bufs is bound to value other than BACK and NONE
3471 if (frameBufferId == 0)
3472 {
3473 if (n != 1)
3474 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003475 context->handleError(InvalidOperation()
3476 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003477 return false;
3478 }
3479
3480 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3481 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003482 context->handleError(
3483 InvalidOperation()
3484 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003485 return false;
3486 }
3487 }
3488
3489 return true;
3490}
3491
Geoff Lang496c02d2016-10-20 11:38:11 -07003492bool ValidateGetBufferPointervBase(Context *context,
3493 GLenum target,
3494 GLenum pname,
3495 GLsizei *length,
3496 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003497{
Geoff Lang496c02d2016-10-20 11:38:11 -07003498 if (length)
3499 {
3500 *length = 0;
3501 }
3502
3503 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3504 {
3505 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003506 InvalidOperation()
3507 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003508 return false;
3509 }
3510
Olli Etuaho4f667482016-03-30 15:56:35 +03003511 if (!ValidBufferTarget(context, target))
3512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003513 context->handleError(InvalidEnum() << "Buffer target not valid: 0x" << std::hex
3514 << std::uppercase << target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003515 return false;
3516 }
3517
Geoff Lang496c02d2016-10-20 11:38:11 -07003518 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003519 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003520 case GL_BUFFER_MAP_POINTER:
3521 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003522
Geoff Lang496c02d2016-10-20 11:38:11 -07003523 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003524 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003525 return false;
3526 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003527
3528 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3529 // target bound to zero generate an INVALID_OPERATION error."
3530 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003531 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003532 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003533 context->handleError(InvalidOperation()
3534 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003535 return false;
3536 }
3537
Geoff Lang496c02d2016-10-20 11:38:11 -07003538 if (length)
3539 {
3540 *length = 1;
3541 }
3542
Olli Etuaho4f667482016-03-30 15:56:35 +03003543 return true;
3544}
3545
3546bool ValidateUnmapBufferBase(Context *context, GLenum target)
3547{
3548 if (!ValidBufferTarget(context, target))
3549 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003550 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003551 return false;
3552 }
3553
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003554 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003555
3556 if (buffer == nullptr || !buffer->isMapped())
3557 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003558 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003559 return false;
3560 }
3561
3562 return true;
3563}
3564
3565bool ValidateMapBufferRangeBase(Context *context,
3566 GLenum target,
3567 GLintptr offset,
3568 GLsizeiptr length,
3569 GLbitfield access)
3570{
3571 if (!ValidBufferTarget(context, target))
3572 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003573 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003574 return false;
3575 }
3576
Brandon Jones6cad5662017-06-14 13:25:13 -07003577 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003578 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003579 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3580 return false;
3581 }
3582
3583 if (length < 0)
3584 {
3585 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003586 return false;
3587 }
3588
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003589 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003590
3591 if (!buffer)
3592 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003593 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003594 return false;
3595 }
3596
3597 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003598 CheckedNumeric<size_t> checkedOffset(offset);
3599 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003600
Jamie Madille2e406c2016-06-02 13:04:10 -04003601 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003602 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003603 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003604 return false;
3605 }
3606
3607 // Check for invalid bits in the mask
3608 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3609 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3610 GL_MAP_UNSYNCHRONIZED_BIT;
3611
3612 if (access & ~(allAccessBits))
3613 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003614 context->handleError(InvalidValue()
3615 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003616 return false;
3617 }
3618
3619 if (length == 0)
3620 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003621 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003622 return false;
3623 }
3624
3625 if (buffer->isMapped())
3626 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003627 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003628 return false;
3629 }
3630
3631 // Check for invalid bit combinations
3632 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3633 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003634 context->handleError(InvalidOperation()
3635 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003636 return false;
3637 }
3638
3639 GLbitfield writeOnlyBits =
3640 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3641
3642 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3643 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003644 context->handleError(InvalidOperation()
3645 << "Invalid access bits when mapping buffer for reading: 0x"
3646 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003647 return false;
3648 }
3649
3650 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3651 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003652 context->handleError(
3653 InvalidOperation()
3654 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003655 return false;
3656 }
Geoff Lang79f71042017-08-14 16:43:43 -04003657
3658 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003659}
3660
3661bool ValidateFlushMappedBufferRangeBase(Context *context,
3662 GLenum target,
3663 GLintptr offset,
3664 GLsizeiptr length)
3665{
Brandon Jones6cad5662017-06-14 13:25:13 -07003666 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003667 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003668 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3669 return false;
3670 }
3671
3672 if (length < 0)
3673 {
3674 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003675 return false;
3676 }
3677
3678 if (!ValidBufferTarget(context, target))
3679 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003680 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003681 return false;
3682 }
3683
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003684 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003685
3686 if (buffer == nullptr)
3687 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003688 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003689 return false;
3690 }
3691
3692 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3693 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003694 context->handleError(InvalidOperation()
3695 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003696 return false;
3697 }
3698
3699 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003700 CheckedNumeric<size_t> checkedOffset(offset);
3701 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003702
Jamie Madille2e406c2016-06-02 13:04:10 -04003703 if (!checkedSize.IsValid() ||
3704 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003705 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003706 context->handleError(InvalidValue()
3707 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003708 return false;
3709 }
3710
3711 return true;
3712}
3713
Olli Etuaho41997e72016-03-10 13:38:39 +02003714bool ValidateGenOrDelete(Context *context, GLint n)
3715{
3716 if (n < 0)
3717 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003718 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003719 return false;
3720 }
3721 return true;
3722}
3723
Geoff Langff5b2d52016-09-07 11:32:23 -04003724bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3725{
3726 if (!context->getExtensions().robustClientMemory)
3727 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003728 context->handleError(InvalidOperation()
3729 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003730 return false;
3731 }
3732
3733 if (bufSize < 0)
3734 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003735 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003736 return false;
3737 }
3738
3739 return true;
3740}
3741
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003742bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3743{
3744 if (bufSize < numParams)
3745 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003746 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3747 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003748 return false;
3749 }
3750
3751 return true;
3752}
3753
Jamie Madillbe849e42017-05-02 15:49:00 -04003754bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3755 GLenum target,
3756 GLenum attachment,
3757 GLenum pname,
3758 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003759{
Geoff Langff5b2d52016-09-07 11:32:23 -04003760 if (!ValidFramebufferTarget(target))
3761 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003762 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003763 return false;
3764 }
3765
3766 int clientVersion = context->getClientMajorVersion();
3767
3768 switch (pname)
3769 {
3770 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3771 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3772 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3773 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3774 break;
3775
Martin Radeve5285d22017-07-14 16:23:53 +03003776 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3777 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3778 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3779 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3780 if (clientVersion < 3 || !context->getExtensions().multiview)
3781 {
3782 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3783 return false;
3784 }
3785 break;
3786
Geoff Langff5b2d52016-09-07 11:32:23 -04003787 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3788 if (clientVersion < 3 && !context->getExtensions().sRGB)
3789 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003790 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003791 return false;
3792 }
3793 break;
3794
3795 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3796 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3797 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3798 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3799 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3800 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3801 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3802 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3803 if (clientVersion < 3)
3804 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003805 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003806 return false;
3807 }
3808 break;
3809
3810 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003811 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003812 return false;
3813 }
3814
3815 // Determine if the attachment is a valid enum
3816 switch (attachment)
3817 {
3818 case GL_BACK:
3819 case GL_FRONT:
3820 case GL_DEPTH:
3821 case GL_STENCIL:
3822 case GL_DEPTH_STENCIL_ATTACHMENT:
3823 if (clientVersion < 3)
3824 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003825 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003826 return false;
3827 }
3828 break;
3829
3830 case GL_DEPTH_ATTACHMENT:
3831 case GL_STENCIL_ATTACHMENT:
3832 break;
3833
3834 default:
3835 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
3836 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3837 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003838 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003839 return false;
3840 }
3841 break;
3842 }
3843
3844 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3845 ASSERT(framebuffer);
3846
3847 if (framebuffer->id() == 0)
3848 {
3849 if (clientVersion < 3)
3850 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003851 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003852 return false;
3853 }
3854
3855 switch (attachment)
3856 {
3857 case GL_BACK:
3858 case GL_DEPTH:
3859 case GL_STENCIL:
3860 break;
3861
3862 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003863 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003864 return false;
3865 }
3866 }
3867 else
3868 {
3869 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3870 {
3871 // Valid attachment query
3872 }
3873 else
3874 {
3875 switch (attachment)
3876 {
3877 case GL_DEPTH_ATTACHMENT:
3878 case GL_STENCIL_ATTACHMENT:
3879 break;
3880
3881 case GL_DEPTH_STENCIL_ATTACHMENT:
3882 if (!framebuffer->hasValidDepthStencil())
3883 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003884 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003885 return false;
3886 }
3887 break;
3888
3889 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003890 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003891 return false;
3892 }
3893 }
3894 }
3895
3896 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3897 if (attachmentObject)
3898 {
3899 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3900 attachmentObject->type() == GL_TEXTURE ||
3901 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3902
3903 switch (pname)
3904 {
3905 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3906 if (attachmentObject->type() != GL_RENDERBUFFER &&
3907 attachmentObject->type() != GL_TEXTURE)
3908 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003909 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003910 return false;
3911 }
3912 break;
3913
3914 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3915 if (attachmentObject->type() != GL_TEXTURE)
3916 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003917 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003918 return false;
3919 }
3920 break;
3921
3922 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3923 if (attachmentObject->type() != GL_TEXTURE)
3924 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003925 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003926 return false;
3927 }
3928 break;
3929
3930 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3931 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3932 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003933 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003934 return false;
3935 }
3936 break;
3937
3938 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3939 if (attachmentObject->type() != GL_TEXTURE)
3940 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003941 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003942 return false;
3943 }
3944 break;
3945
3946 default:
3947 break;
3948 }
3949 }
3950 else
3951 {
3952 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3953 // is NONE, then querying any other pname will generate INVALID_ENUM.
3954
3955 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3956 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3957 // INVALID_OPERATION for all other pnames
3958
3959 switch (pname)
3960 {
3961 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3962 break;
3963
3964 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3965 if (clientVersion < 3)
3966 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003967 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07003968 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003969 return false;
3970 }
3971 break;
3972
3973 default:
3974 if (clientVersion < 3)
3975 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003976 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07003977 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003978 return false;
3979 }
3980 else
3981 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003982 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Brandon Jonesafa75152017-07-21 13:11:29 -07003983 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003984 return false;
3985 }
3986 }
3987 }
3988
Martin Radeve5285d22017-07-14 16:23:53 +03003989 if (numParams)
3990 {
3991 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
3992 {
3993 // Only when the viewport offsets are queried we can have a varying number of output
3994 // parameters.
3995 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
3996 *numParams = numViews * 2;
3997 }
3998 else
3999 {
4000 // For all other queries we can have only one output parameter.
4001 *numParams = 1;
4002 }
4003 }
4004
Geoff Langff5b2d52016-09-07 11:32:23 -04004005 return true;
4006}
4007
4008bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4009 GLenum target,
4010 GLenum attachment,
4011 GLenum pname,
4012 GLsizei bufSize,
4013 GLsizei *numParams)
4014{
4015 if (!ValidateRobustEntryPoint(context, bufSize))
4016 {
4017 return false;
4018 }
4019
Jamie Madillbe849e42017-05-02 15:49:00 -04004020 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4021 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004022 {
4023 return false;
4024 }
4025
4026 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4027 {
4028 return false;
4029 }
4030
4031 return true;
4032}
4033
Geoff Langff5b2d52016-09-07 11:32:23 -04004034bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4035 GLenum target,
4036 GLenum pname,
4037 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004038 GLsizei *length,
4039 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004040{
4041 if (!ValidateRobustEntryPoint(context, bufSize))
4042 {
4043 return false;
4044 }
4045
Geoff Langebebe1c2016-10-14 12:01:31 -04004046 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004047 {
4048 return false;
4049 }
4050
Geoff Langebebe1c2016-10-14 12:01:31 -04004051 if (!ValidateRobustBufferSize(context, bufSize, *length))
4052 {
4053 return false;
4054 }
4055
4056 return true;
4057}
4058
Geoff Langebebe1c2016-10-14 12:01:31 -04004059bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4060 GLenum target,
4061 GLenum pname,
4062 GLsizei bufSize,
4063 GLsizei *length,
4064 GLint64 *params)
4065{
4066 if (!ValidateRobustEntryPoint(context, bufSize))
4067 {
4068 return false;
4069 }
4070
4071 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4072 {
4073 return false;
4074 }
4075
4076 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004077 {
4078 return false;
4079 }
4080
4081 return true;
4082}
4083
Jamie Madillbe849e42017-05-02 15:49:00 -04004084bool ValidateGetProgramivBase(ValidationContext *context,
4085 GLuint program,
4086 GLenum pname,
4087 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004088{
4089 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004090 if (numParams)
4091 {
4092 *numParams = 1;
4093 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004094
4095 Program *programObject = GetValidProgram(context, program);
4096 if (!programObject)
4097 {
4098 return false;
4099 }
4100
4101 switch (pname)
4102 {
4103 case GL_DELETE_STATUS:
4104 case GL_LINK_STATUS:
4105 case GL_VALIDATE_STATUS:
4106 case GL_INFO_LOG_LENGTH:
4107 case GL_ATTACHED_SHADERS:
4108 case GL_ACTIVE_ATTRIBUTES:
4109 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4110 case GL_ACTIVE_UNIFORMS:
4111 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4112 break;
4113
4114 case GL_PROGRAM_BINARY_LENGTH:
4115 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4116 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004117 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4118 "requires GL_OES_get_program_binary or "
4119 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004120 return false;
4121 }
4122 break;
4123
4124 case GL_ACTIVE_UNIFORM_BLOCKS:
4125 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4126 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4127 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4128 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4129 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4130 if (context->getClientMajorVersion() < 3)
4131 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004132 context->handleError(InvalidEnum() << "Querying requires at least ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004133 return false;
4134 }
4135 break;
4136
Yunchao He61afff12017-03-14 15:34:03 +08004137 case GL_PROGRAM_SEPARABLE:
4138 if (context->getClientVersion() < Version(3, 1))
4139 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004140 context->handleError(InvalidEnum() << "Querying requires at least ES 3.1.");
Yunchao He61afff12017-03-14 15:34:03 +08004141 return false;
4142 }
4143 break;
4144
Geoff Langff5b2d52016-09-07 11:32:23 -04004145 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004146 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004147 return false;
4148 }
4149
4150 return true;
4151}
4152
4153bool ValidateGetProgramivRobustANGLE(Context *context,
4154 GLuint program,
4155 GLenum pname,
4156 GLsizei bufSize,
4157 GLsizei *numParams)
4158{
4159 if (!ValidateRobustEntryPoint(context, bufSize))
4160 {
4161 return false;
4162 }
4163
Jamie Madillbe849e42017-05-02 15:49:00 -04004164 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004165 {
4166 return false;
4167 }
4168
4169 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4170 {
4171 return false;
4172 }
4173
4174 return true;
4175}
4176
Geoff Lang740d9022016-10-07 11:20:52 -04004177bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4178 GLenum target,
4179 GLenum pname,
4180 GLsizei bufSize,
4181 GLsizei *length,
4182 GLint *params)
4183{
4184 if (!ValidateRobustEntryPoint(context, bufSize))
4185 {
4186 return false;
4187 }
4188
4189 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4190 {
4191 return false;
4192 }
4193
4194 if (!ValidateRobustBufferSize(context, bufSize, *length))
4195 {
4196 return false;
4197 }
4198
4199 return true;
4200}
4201
Geoff Langd7d0ed32016-10-07 11:33:51 -04004202bool ValidateGetShaderivRobustANGLE(Context *context,
4203 GLuint shader,
4204 GLenum pname,
4205 GLsizei bufSize,
4206 GLsizei *length,
4207 GLint *params)
4208{
4209 if (!ValidateRobustEntryPoint(context, bufSize))
4210 {
4211 return false;
4212 }
4213
4214 if (!ValidateGetShaderivBase(context, shader, pname, length))
4215 {
4216 return false;
4217 }
4218
4219 if (!ValidateRobustBufferSize(context, bufSize, *length))
4220 {
4221 return false;
4222 }
4223
4224 return true;
4225}
4226
Geoff Langc1984ed2016-10-07 12:41:00 -04004227bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4228 GLenum target,
4229 GLenum pname,
4230 GLsizei bufSize,
4231 GLsizei *length,
4232 GLfloat *params)
4233{
4234 if (!ValidateRobustEntryPoint(context, bufSize))
4235 {
4236 return false;
4237 }
4238
4239 if (!ValidateGetTexParameterBase(context, target, pname, length))
4240 {
4241 return false;
4242 }
4243
4244 if (!ValidateRobustBufferSize(context, bufSize, *length))
4245 {
4246 return false;
4247 }
4248
4249 return true;
4250}
4251
Geoff Langc1984ed2016-10-07 12:41:00 -04004252bool ValidateGetTexParameterivRobustANGLE(Context *context,
4253 GLenum target,
4254 GLenum pname,
4255 GLsizei bufSize,
4256 GLsizei *length,
4257 GLint *params)
4258{
4259 if (!ValidateRobustEntryPoint(context, bufSize))
4260 {
4261 return false;
4262 }
4263
4264 if (!ValidateGetTexParameterBase(context, target, pname, length))
4265 {
4266 return false;
4267 }
4268
4269 if (!ValidateRobustBufferSize(context, bufSize, *length))
4270 {
4271 return false;
4272 }
4273
4274 return true;
4275}
4276
Geoff Langc1984ed2016-10-07 12:41:00 -04004277bool ValidateTexParameterfvRobustANGLE(Context *context,
4278 GLenum target,
4279 GLenum pname,
4280 GLsizei bufSize,
4281 const GLfloat *params)
4282{
4283 if (!ValidateRobustEntryPoint(context, bufSize))
4284 {
4285 return false;
4286 }
4287
4288 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4289}
4290
Geoff Langc1984ed2016-10-07 12:41:00 -04004291bool ValidateTexParameterivRobustANGLE(Context *context,
4292 GLenum target,
4293 GLenum pname,
4294 GLsizei bufSize,
4295 const GLint *params)
4296{
4297 if (!ValidateRobustEntryPoint(context, bufSize))
4298 {
4299 return false;
4300 }
4301
4302 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4303}
4304
Geoff Langc1984ed2016-10-07 12:41:00 -04004305bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4306 GLuint sampler,
4307 GLenum pname,
4308 GLuint bufSize,
4309 GLsizei *length,
4310 GLfloat *params)
4311{
4312 if (!ValidateRobustEntryPoint(context, bufSize))
4313 {
4314 return false;
4315 }
4316
4317 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4318 {
4319 return false;
4320 }
4321
4322 if (!ValidateRobustBufferSize(context, bufSize, *length))
4323 {
4324 return false;
4325 }
4326
4327 return true;
4328}
4329
Geoff Langc1984ed2016-10-07 12:41:00 -04004330bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4331 GLuint sampler,
4332 GLenum pname,
4333 GLuint bufSize,
4334 GLsizei *length,
4335 GLint *params)
4336{
4337 if (!ValidateRobustEntryPoint(context, bufSize))
4338 {
4339 return false;
4340 }
4341
4342 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4343 {
4344 return false;
4345 }
4346
4347 if (!ValidateRobustBufferSize(context, bufSize, *length))
4348 {
4349 return false;
4350 }
4351
4352 return true;
4353}
4354
Geoff Langc1984ed2016-10-07 12:41:00 -04004355bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4356 GLuint sampler,
4357 GLenum pname,
4358 GLsizei bufSize,
4359 const GLfloat *params)
4360{
4361 if (!ValidateRobustEntryPoint(context, bufSize))
4362 {
4363 return false;
4364 }
4365
4366 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4367}
4368
Geoff Langc1984ed2016-10-07 12:41:00 -04004369bool ValidateSamplerParameterivRobustANGLE(Context *context,
4370 GLuint sampler,
4371 GLenum pname,
4372 GLsizei bufSize,
4373 const GLint *params)
4374{
4375 if (!ValidateRobustEntryPoint(context, bufSize))
4376 {
4377 return false;
4378 }
4379
4380 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4381}
4382
Geoff Lang0b031062016-10-13 14:30:04 -04004383bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4384 GLuint index,
4385 GLenum pname,
4386 GLsizei bufSize,
4387 GLsizei *length,
4388 GLfloat *params)
4389{
4390 if (!ValidateRobustEntryPoint(context, bufSize))
4391 {
4392 return false;
4393 }
4394
4395 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4396 {
4397 return false;
4398 }
4399
4400 if (!ValidateRobustBufferSize(context, bufSize, *length))
4401 {
4402 return false;
4403 }
4404
4405 return true;
4406}
4407
Geoff Lang0b031062016-10-13 14:30:04 -04004408bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4409 GLuint index,
4410 GLenum pname,
4411 GLsizei bufSize,
4412 GLsizei *length,
4413 GLint *params)
4414{
4415 if (!ValidateRobustEntryPoint(context, bufSize))
4416 {
4417 return false;
4418 }
4419
4420 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4421 {
4422 return false;
4423 }
4424
4425 if (!ValidateRobustBufferSize(context, bufSize, *length))
4426 {
4427 return false;
4428 }
4429
4430 return true;
4431}
4432
Geoff Lang0b031062016-10-13 14:30:04 -04004433bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4434 GLuint index,
4435 GLenum pname,
4436 GLsizei bufSize,
4437 GLsizei *length,
4438 void **pointer)
4439{
4440 if (!ValidateRobustEntryPoint(context, bufSize))
4441 {
4442 return false;
4443 }
4444
4445 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4446 {
4447 return false;
4448 }
4449
4450 if (!ValidateRobustBufferSize(context, bufSize, *length))
4451 {
4452 return false;
4453 }
4454
4455 return true;
4456}
4457
Geoff Lang0b031062016-10-13 14:30:04 -04004458bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4459 GLuint index,
4460 GLenum pname,
4461 GLsizei bufSize,
4462 GLsizei *length,
4463 GLint *params)
4464{
4465 if (!ValidateRobustEntryPoint(context, bufSize))
4466 {
4467 return false;
4468 }
4469
4470 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4471 {
4472 return false;
4473 }
4474
4475 if (!ValidateRobustBufferSize(context, bufSize, *length))
4476 {
4477 return false;
4478 }
4479
4480 return true;
4481}
4482
Geoff Lang0b031062016-10-13 14:30:04 -04004483bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4484 GLuint index,
4485 GLenum pname,
4486 GLsizei bufSize,
4487 GLsizei *length,
4488 GLuint *params)
4489{
4490 if (!ValidateRobustEntryPoint(context, bufSize))
4491 {
4492 return false;
4493 }
4494
4495 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4496 {
4497 return false;
4498 }
4499
4500 if (!ValidateRobustBufferSize(context, bufSize, *length))
4501 {
4502 return false;
4503 }
4504
4505 return true;
4506}
4507
Geoff Lang6899b872016-10-14 11:30:13 -04004508bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4509 GLuint program,
4510 GLuint uniformBlockIndex,
4511 GLenum pname,
4512 GLsizei bufSize,
4513 GLsizei *length,
4514 GLint *params)
4515{
4516 if (!ValidateRobustEntryPoint(context, bufSize))
4517 {
4518 return false;
4519 }
4520
4521 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4522 {
4523 return false;
4524 }
4525
4526 if (!ValidateRobustBufferSize(context, bufSize, *length))
4527 {
4528 return false;
4529 }
4530
4531 return true;
4532}
4533
Geoff Lang0a9661f2016-10-20 10:59:20 -07004534bool ValidateGetInternalFormativRobustANGLE(Context *context,
4535 GLenum target,
4536 GLenum internalformat,
4537 GLenum pname,
4538 GLsizei bufSize,
4539 GLsizei *length,
4540 GLint *params)
4541{
4542 if (!ValidateRobustEntryPoint(context, bufSize))
4543 {
4544 return false;
4545 }
4546
4547 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4548 {
4549 return false;
4550 }
4551
4552 if (!ValidateRobustBufferSize(context, bufSize, *length))
4553 {
4554 return false;
4555 }
4556
4557 return true;
4558}
4559
Shao80957d92017-02-20 21:25:59 +08004560bool ValidateVertexFormatBase(ValidationContext *context,
4561 GLuint attribIndex,
4562 GLint size,
4563 GLenum type,
4564 GLboolean pureInteger)
4565{
4566 const Caps &caps = context->getCaps();
4567 if (attribIndex >= caps.maxVertexAttributes)
4568 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004569 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004570 return false;
4571 }
4572
4573 if (size < 1 || size > 4)
4574 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004575 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004576 return false;
Shao80957d92017-02-20 21:25:59 +08004577 }
4578
4579 switch (type)
4580 {
4581 case GL_BYTE:
4582 case GL_UNSIGNED_BYTE:
4583 case GL_SHORT:
4584 case GL_UNSIGNED_SHORT:
4585 break;
4586
4587 case GL_INT:
4588 case GL_UNSIGNED_INT:
4589 if (context->getClientMajorVersion() < 3)
4590 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004591 context->handleError(InvalidEnum()
4592 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004593 return false;
4594 }
4595 break;
4596
4597 case GL_FIXED:
4598 case GL_FLOAT:
4599 if (pureInteger)
4600 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004601 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004602 return false;
4603 }
4604 break;
4605
4606 case GL_HALF_FLOAT:
4607 if (context->getClientMajorVersion() < 3)
4608 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004609 context->handleError(InvalidEnum()
4610 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004611 return false;
4612 }
4613 if (pureInteger)
4614 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004615 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004616 return false;
4617 }
4618 break;
4619
4620 case GL_INT_2_10_10_10_REV:
4621 case GL_UNSIGNED_INT_2_10_10_10_REV:
4622 if (context->getClientMajorVersion() < 3)
4623 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004624 context->handleError(InvalidEnum()
4625 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004626 return false;
4627 }
4628 if (pureInteger)
4629 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004630 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004631 return false;
4632 }
4633 if (size != 4)
4634 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004635 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4636 "UNSIGNED_INT_2_10_10_10_REV and "
4637 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004638 return false;
4639 }
4640 break;
4641
4642 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004643 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004644 return false;
4645 }
4646
4647 return true;
4648}
4649
Geoff Lang76e65652017-03-27 14:58:02 -04004650// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4651// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4652// specified clear value and the type of a buffer that is being cleared generates an
4653// INVALID_OPERATION error instead of producing undefined results
4654bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4655 GLint drawbuffer,
4656 const GLenum *validComponentTypes,
4657 size_t validComponentTypeCount)
4658{
4659 const FramebufferAttachment *attachment =
4660 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4661 if (attachment)
4662 {
4663 GLenum componentType = attachment->getFormat().info->componentType;
4664 const GLenum *end = validComponentTypes + validComponentTypeCount;
4665 if (std::find(validComponentTypes, end, componentType) == end)
4666 {
4667 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004668 InvalidOperation()
4669 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004670 return false;
4671 }
4672 }
4673
4674 return true;
4675}
4676
Corentin Wallezb2931602017-04-11 15:58:57 -04004677bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4678 GLsizei imageSize,
4679 GLsizei dataSize)
4680{
4681 if (!ValidateRobustEntryPoint(context, dataSize))
4682 {
4683 return false;
4684 }
4685
4686 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
4687 if (pixelUnpackBuffer == nullptr)
4688 {
4689 if (dataSize < imageSize)
4690 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004691 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004692 }
4693 }
4694 return true;
4695}
4696
Jamie Madillbe849e42017-05-02 15:49:00 -04004697bool ValidateGetBufferParameterBase(ValidationContext *context,
4698 GLenum target,
4699 GLenum pname,
4700 bool pointerVersion,
4701 GLsizei *numParams)
4702{
4703 if (numParams)
4704 {
4705 *numParams = 0;
4706 }
4707
4708 if (!ValidBufferTarget(context, target))
4709 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004710 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004711 return false;
4712 }
4713
4714 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4715 if (!buffer)
4716 {
4717 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004718 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004719 return false;
4720 }
4721
4722 const Extensions &extensions = context->getExtensions();
4723
4724 switch (pname)
4725 {
4726 case GL_BUFFER_USAGE:
4727 case GL_BUFFER_SIZE:
4728 break;
4729
4730 case GL_BUFFER_ACCESS_OES:
4731 if (!extensions.mapBuffer)
4732 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004733 context->handleError(InvalidEnum()
4734 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004735 return false;
4736 }
4737 break;
4738
4739 case GL_BUFFER_MAPPED:
4740 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4741 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4742 !extensions.mapBufferRange)
4743 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004744 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4745 "GL_OES_mapbuffer or "
4746 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004747 return false;
4748 }
4749 break;
4750
4751 case GL_BUFFER_MAP_POINTER:
4752 if (!pointerVersion)
4753 {
4754 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004755 InvalidEnum()
4756 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004757 return false;
4758 }
4759 break;
4760
4761 case GL_BUFFER_ACCESS_FLAGS:
4762 case GL_BUFFER_MAP_OFFSET:
4763 case GL_BUFFER_MAP_LENGTH:
4764 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4765 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004766 context->handleError(InvalidEnum()
4767 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004768 return false;
4769 }
4770 break;
4771
4772 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004773 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004774 return false;
4775 }
4776
4777 // All buffer parameter queries return one value.
4778 if (numParams)
4779 {
4780 *numParams = 1;
4781 }
4782
4783 return true;
4784}
4785
4786bool ValidateGetRenderbufferParameterivBase(Context *context,
4787 GLenum target,
4788 GLenum pname,
4789 GLsizei *length)
4790{
4791 if (length)
4792 {
4793 *length = 0;
4794 }
4795
4796 if (target != GL_RENDERBUFFER)
4797 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004798 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004799 return false;
4800 }
4801
4802 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4803 if (renderbuffer == nullptr)
4804 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004805 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004806 return false;
4807 }
4808
4809 switch (pname)
4810 {
4811 case GL_RENDERBUFFER_WIDTH:
4812 case GL_RENDERBUFFER_HEIGHT:
4813 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4814 case GL_RENDERBUFFER_RED_SIZE:
4815 case GL_RENDERBUFFER_GREEN_SIZE:
4816 case GL_RENDERBUFFER_BLUE_SIZE:
4817 case GL_RENDERBUFFER_ALPHA_SIZE:
4818 case GL_RENDERBUFFER_DEPTH_SIZE:
4819 case GL_RENDERBUFFER_STENCIL_SIZE:
4820 break;
4821
4822 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4823 if (!context->getExtensions().framebufferMultisample)
4824 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004825 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004826 return false;
4827 }
4828 break;
4829
4830 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004831 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004832 return false;
4833 }
4834
4835 if (length)
4836 {
4837 *length = 1;
4838 }
4839 return true;
4840}
4841
4842bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4843{
4844 if (length)
4845 {
4846 *length = 0;
4847 }
4848
4849 if (GetValidShader(context, shader) == nullptr)
4850 {
4851 return false;
4852 }
4853
4854 switch (pname)
4855 {
4856 case GL_SHADER_TYPE:
4857 case GL_DELETE_STATUS:
4858 case GL_COMPILE_STATUS:
4859 case GL_INFO_LOG_LENGTH:
4860 case GL_SHADER_SOURCE_LENGTH:
4861 break;
4862
4863 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4864 if (!context->getExtensions().translatedShaderSource)
4865 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004866 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004867 return false;
4868 }
4869 break;
4870
4871 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004872 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004873 return false;
4874 }
4875
4876 if (length)
4877 {
4878 *length = 1;
4879 }
4880 return true;
4881}
4882
4883bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4884{
4885 if (length)
4886 {
4887 *length = 0;
4888 }
4889
4890 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4891 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004892 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004893 return false;
4894 }
4895
4896 if (context->getTargetTexture(target) == nullptr)
4897 {
4898 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004899 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004900 return false;
4901 }
4902
4903 switch (pname)
4904 {
4905 case GL_TEXTURE_MAG_FILTER:
4906 case GL_TEXTURE_MIN_FILTER:
4907 case GL_TEXTURE_WRAP_S:
4908 case GL_TEXTURE_WRAP_T:
4909 break;
4910
4911 case GL_TEXTURE_USAGE_ANGLE:
4912 if (!context->getExtensions().textureUsage)
4913 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004914 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004915 return false;
4916 }
4917 break;
4918
4919 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4920 if (!context->getExtensions().textureFilterAnisotropic)
4921 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004922 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004923 return false;
4924 }
4925 break;
4926
4927 case GL_TEXTURE_IMMUTABLE_FORMAT:
4928 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4929 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004930 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004931 return false;
4932 }
4933 break;
4934
4935 case GL_TEXTURE_WRAP_R:
4936 case GL_TEXTURE_IMMUTABLE_LEVELS:
4937 case GL_TEXTURE_SWIZZLE_R:
4938 case GL_TEXTURE_SWIZZLE_G:
4939 case GL_TEXTURE_SWIZZLE_B:
4940 case GL_TEXTURE_SWIZZLE_A:
4941 case GL_TEXTURE_BASE_LEVEL:
4942 case GL_TEXTURE_MAX_LEVEL:
4943 case GL_TEXTURE_MIN_LOD:
4944 case GL_TEXTURE_MAX_LOD:
4945 case GL_TEXTURE_COMPARE_MODE:
4946 case GL_TEXTURE_COMPARE_FUNC:
4947 if (context->getClientMajorVersion() < 3)
4948 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004949 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004950 return false;
4951 }
4952 break;
4953
4954 case GL_TEXTURE_SRGB_DECODE_EXT:
4955 if (!context->getExtensions().textureSRGBDecode)
4956 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004957 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004958 return false;
4959 }
4960 break;
4961
4962 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004963 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004964 return false;
4965 }
4966
4967 if (length)
4968 {
4969 *length = 1;
4970 }
4971 return true;
4972}
4973
4974bool ValidateGetVertexAttribBase(Context *context,
4975 GLuint index,
4976 GLenum pname,
4977 GLsizei *length,
4978 bool pointer,
4979 bool pureIntegerEntryPoint)
4980{
4981 if (length)
4982 {
4983 *length = 0;
4984 }
4985
4986 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
4987 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004988 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004989 return false;
4990 }
4991
4992 if (index >= context->getCaps().maxVertexAttributes)
4993 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004994 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04004995 return false;
4996 }
4997
4998 if (pointer)
4999 {
5000 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5001 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005002 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005003 return false;
5004 }
5005 }
5006 else
5007 {
5008 switch (pname)
5009 {
5010 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5011 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5012 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5013 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5014 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5015 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5016 case GL_CURRENT_VERTEX_ATTRIB:
5017 break;
5018
5019 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5020 static_assert(
5021 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5022 "ANGLE extension enums not equal to GL enums.");
5023 if (context->getClientMajorVersion() < 3 &&
5024 !context->getExtensions().instancedArrays)
5025 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005026 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5027 "requires OpenGL ES 3.0 or "
5028 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005029 return false;
5030 }
5031 break;
5032
5033 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5034 if (context->getClientMajorVersion() < 3)
5035 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005036 context->handleError(
5037 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005038 return false;
5039 }
5040 break;
5041
5042 case GL_VERTEX_ATTRIB_BINDING:
5043 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5044 if (context->getClientVersion() < ES_3_1)
5045 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005046 context->handleError(InvalidEnum()
5047 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005048 return false;
5049 }
5050 break;
5051
5052 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005053 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005054 return false;
5055 }
5056 }
5057
5058 if (length)
5059 {
5060 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5061 {
5062 *length = 4;
5063 }
5064 else
5065 {
5066 *length = 1;
5067 }
5068 }
5069
5070 return true;
5071}
5072
Jamie Madill4928b7c2017-06-20 12:57:39 -04005073bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005074 GLint x,
5075 GLint y,
5076 GLsizei width,
5077 GLsizei height,
5078 GLenum format,
5079 GLenum type,
5080 GLsizei bufSize,
5081 GLsizei *length,
5082 GLsizei *columns,
5083 GLsizei *rows,
5084 void *pixels)
5085{
5086 if (length != nullptr)
5087 {
5088 *length = 0;
5089 }
5090 if (rows != nullptr)
5091 {
5092 *rows = 0;
5093 }
5094 if (columns != nullptr)
5095 {
5096 *columns = 0;
5097 }
5098
5099 if (width < 0 || height < 0)
5100 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005101 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005102 return false;
5103 }
5104
5105 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5106
5107 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5108 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005109 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005110 return false;
5111 }
5112
5113 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5114 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005115 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005116 return false;
5117 }
5118
5119 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5120 ASSERT(framebuffer);
5121
5122 if (framebuffer->getReadBufferState() == GL_NONE)
5123 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005124 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005125 return false;
5126 }
5127
5128 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5129 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5130 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5131 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5132 // situation is an application error that would lead to a crash in ANGLE.
5133 if (readBuffer == nullptr)
5134 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005135 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005136 return false;
5137 }
5138
Martin Radev28031682017-07-28 14:47:56 +03005139 // ANGLE_multiview, Revision 1:
5140 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5141 // current read framebuffer is not NONE.
5142 if (readBuffer->getMultiviewLayout() != GL_NONE)
5143 {
5144 context->handleError(InvalidFramebufferOperation()
5145 << "Attempting to read from a multi-view framebuffer.");
5146 return false;
5147 }
5148
Geoff Lang280ba992017-04-18 16:30:58 -04005149 if (context->getExtensions().webglCompatibility)
5150 {
5151 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5152 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5153 // and type before validating the combination of format and type. However, the
5154 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5155 // verifies that GL_INVALID_OPERATION is generated.
5156 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5157 // dEQP/WebGL.
5158 if (!ValidReadPixelsFormatEnum(context, format))
5159 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005160 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005161 return false;
5162 }
5163
5164 if (!ValidReadPixelsTypeEnum(context, type))
5165 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005166 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005167 return false;
5168 }
5169 }
5170
Jamie Madill4928b7c2017-06-20 12:57:39 -04005171 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5172 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005173 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5174
5175 bool validFormatTypeCombination =
5176 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5177
5178 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5179 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005180 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005181 return false;
5182 }
5183
5184 // Check for pixel pack buffer related API errors
5185 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5186 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5187 {
5188 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005189 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005190 return false;
5191 }
5192
5193 // .. the data would be packed to the buffer object such that the memory writes required
5194 // would exceed the data store size.
5195 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5196 const gl::Extents size(width, height, 1);
5197 const auto &pack = context->getGLState().getPackState();
5198
5199 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5200 if (endByteOrErr.isError())
5201 {
5202 context->handleError(endByteOrErr.getError());
5203 return false;
5204 }
5205
5206 size_t endByte = endByteOrErr.getResult();
5207 if (bufSize >= 0)
5208 {
5209 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5210 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005211 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005212 return false;
5213 }
5214 }
5215
5216 if (pixelPackBuffer != nullptr)
5217 {
5218 CheckedNumeric<size_t> checkedEndByte(endByte);
5219 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5220 checkedEndByte += checkedOffset;
5221
5222 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5223 {
5224 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005225 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005226 return false;
5227 }
5228 }
5229
5230 if (pixelPackBuffer == nullptr && length != nullptr)
5231 {
5232 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5233 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005234 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005235 return false;
5236 }
5237
5238 *length = static_cast<GLsizei>(endByte);
5239 }
5240
5241 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5242 angle::CheckedNumeric<int> clippedExtent(length);
5243 if (start < 0)
5244 {
5245 // "subtract" the area that is less than 0
5246 clippedExtent += start;
5247 }
5248
5249 const int readExtent = start + length;
5250 if (readExtent > bufferSize)
5251 {
5252 // Subtract the region to the right of the read buffer
5253 clippedExtent -= (readExtent - bufferSize);
5254 }
5255
5256 if (!clippedExtent.IsValid())
5257 {
5258 return 0;
5259 }
5260
5261 return std::max(clippedExtent.ValueOrDie(), 0);
5262 };
5263
5264 if (columns != nullptr)
5265 {
5266 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5267 }
5268
5269 if (rows != nullptr)
5270 {
5271 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5272 }
5273
5274 return true;
5275}
5276
5277template <typename ParamType>
5278bool ValidateTexParameterBase(Context *context,
5279 GLenum target,
5280 GLenum pname,
5281 GLsizei bufSize,
5282 const ParamType *params)
5283{
5284 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5285 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005286 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005287 return false;
5288 }
5289
5290 if (context->getTargetTexture(target) == nullptr)
5291 {
5292 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005293 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005294 return false;
5295 }
5296
5297 const GLsizei minBufSize = 1;
5298 if (bufSize >= 0 && bufSize < minBufSize)
5299 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005300 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005301 return false;
5302 }
5303
5304 switch (pname)
5305 {
5306 case GL_TEXTURE_WRAP_R:
5307 case GL_TEXTURE_SWIZZLE_R:
5308 case GL_TEXTURE_SWIZZLE_G:
5309 case GL_TEXTURE_SWIZZLE_B:
5310 case GL_TEXTURE_SWIZZLE_A:
5311 case GL_TEXTURE_BASE_LEVEL:
5312 case GL_TEXTURE_MAX_LEVEL:
5313 case GL_TEXTURE_COMPARE_MODE:
5314 case GL_TEXTURE_COMPARE_FUNC:
5315 case GL_TEXTURE_MIN_LOD:
5316 case GL_TEXTURE_MAX_LOD:
5317 if (context->getClientMajorVersion() < 3)
5318 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005319 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005320 return false;
5321 }
5322 if (target == GL_TEXTURE_EXTERNAL_OES &&
5323 !context->getExtensions().eglImageExternalEssl3)
5324 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005325 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5326 "available without "
5327 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005328 return false;
5329 }
5330 break;
5331
5332 default:
5333 break;
5334 }
5335
JiangYizhou4cff8d62017-07-06 14:54:09 +08005336 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5337 {
5338 switch (pname)
5339 {
5340 case GL_TEXTURE_MIN_FILTER:
5341 case GL_TEXTURE_MAG_FILTER:
5342 case GL_TEXTURE_WRAP_S:
5343 case GL_TEXTURE_WRAP_T:
5344 case GL_TEXTURE_WRAP_R:
5345 case GL_TEXTURE_MIN_LOD:
5346 case GL_TEXTURE_MAX_LOD:
5347 case GL_TEXTURE_COMPARE_MODE:
5348 case GL_TEXTURE_COMPARE_FUNC:
5349 context->handleError(InvalidEnum()
5350 << "Invalid parameter for 2D multisampled textures.");
5351 return false;
5352 }
5353 }
5354
Jamie Madillbe849e42017-05-02 15:49:00 -04005355 switch (pname)
5356 {
5357 case GL_TEXTURE_WRAP_S:
5358 case GL_TEXTURE_WRAP_T:
5359 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005360 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005361 bool restrictedWrapModes =
5362 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5363 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5364 {
5365 return false;
5366 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005367 }
5368 break;
5369
5370 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005371 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005372 bool restrictedMinFilter =
5373 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5374 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5375 {
5376 return false;
5377 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005378 }
5379 break;
5380
5381 case GL_TEXTURE_MAG_FILTER:
5382 if (!ValidateTextureMagFilterValue(context, params))
5383 {
5384 return false;
5385 }
5386 break;
5387
5388 case GL_TEXTURE_USAGE_ANGLE:
5389 switch (ConvertToGLenum(params[0]))
5390 {
5391 case GL_NONE:
5392 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5393 break;
5394
5395 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005396 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005397 return false;
5398 }
5399 break;
5400
5401 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5402 if (!context->getExtensions().textureFilterAnisotropic)
5403 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005404 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005405 return false;
5406 }
5407
5408 // we assume the parameter passed to this validation method is truncated, not rounded
5409 if (params[0] < 1)
5410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005411 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005412 return false;
5413 }
5414 break;
5415
5416 case GL_TEXTURE_MIN_LOD:
5417 case GL_TEXTURE_MAX_LOD:
5418 // any value is permissible
5419 break;
5420
5421 case GL_TEXTURE_COMPARE_MODE:
5422 if (!ValidateTextureCompareModeValue(context, params))
5423 {
5424 return false;
5425 }
5426 break;
5427
5428 case GL_TEXTURE_COMPARE_FUNC:
5429 if (!ValidateTextureCompareFuncValue(context, params))
5430 {
5431 return false;
5432 }
5433 break;
5434
5435 case GL_TEXTURE_SWIZZLE_R:
5436 case GL_TEXTURE_SWIZZLE_G:
5437 case GL_TEXTURE_SWIZZLE_B:
5438 case GL_TEXTURE_SWIZZLE_A:
5439 switch (ConvertToGLenum(params[0]))
5440 {
5441 case GL_RED:
5442 case GL_GREEN:
5443 case GL_BLUE:
5444 case GL_ALPHA:
5445 case GL_ZERO:
5446 case GL_ONE:
5447 break;
5448
5449 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005450 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005451 return false;
5452 }
5453 break;
5454
5455 case GL_TEXTURE_BASE_LEVEL:
5456 if (params[0] < 0)
5457 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005458 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005459 return false;
5460 }
5461 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005463 context->handleError(InvalidOperation()
5464 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005465 return false;
5466 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005467 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5468 {
5469 context->handleError(InvalidOperation()
5470 << "Base level must be 0 for multisampled textures.");
5471 return false;
5472 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005473 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5474 {
5475 context->handleError(InvalidOperation()
5476 << "Base level must be 0 for rectangle textures.");
5477 return false;
5478 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005479 break;
5480
5481 case GL_TEXTURE_MAX_LEVEL:
5482 if (params[0] < 0)
5483 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005484 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005485 return false;
5486 }
5487 break;
5488
5489 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5490 if (context->getClientVersion() < Version(3, 1))
5491 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005492 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005493 return false;
5494 }
5495 switch (ConvertToGLenum(params[0]))
5496 {
5497 case GL_DEPTH_COMPONENT:
5498 case GL_STENCIL_INDEX:
5499 break;
5500
5501 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005502 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005503 return false;
5504 }
5505 break;
5506
5507 case GL_TEXTURE_SRGB_DECODE_EXT:
5508 if (!ValidateTextureSRGBDecodeValue(context, params))
5509 {
5510 return false;
5511 }
5512 break;
5513
5514 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005515 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005516 return false;
5517 }
5518
5519 return true;
5520}
5521
5522template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5523template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5524
Jamie Madill12e957f2017-08-26 21:42:26 -04005525bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5526{
5527 if (index >= MAX_VERTEX_ATTRIBS)
5528 {
5529 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5530 return false;
5531 }
5532
5533 return true;
5534}
5535
5536bool ValidateGetActiveUniformBlockivBase(Context *context,
5537 GLuint program,
5538 GLuint uniformBlockIndex,
5539 GLenum pname,
5540 GLsizei *length)
5541{
5542 if (length)
5543 {
5544 *length = 0;
5545 }
5546
5547 if (context->getClientMajorVersion() < 3)
5548 {
5549 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5550 return false;
5551 }
5552
5553 Program *programObject = GetValidProgram(context, program);
5554 if (!programObject)
5555 {
5556 return false;
5557 }
5558
5559 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5560 {
5561 context->handleError(InvalidValue()
5562 << "uniformBlockIndex exceeds active uniform block count.");
5563 return false;
5564 }
5565
5566 switch (pname)
5567 {
5568 case GL_UNIFORM_BLOCK_BINDING:
5569 case GL_UNIFORM_BLOCK_DATA_SIZE:
5570 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5571 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5572 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5573 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5574 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5575 break;
5576
5577 default:
5578 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5579 return false;
5580 }
5581
5582 if (length)
5583 {
5584 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5585 {
5586 const UniformBlock &uniformBlock =
5587 programObject->getUniformBlockByIndex(uniformBlockIndex);
5588 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5589 }
5590 else
5591 {
5592 *length = 1;
5593 }
5594 }
5595
5596 return true;
5597}
5598
Jamie Madill9696d072017-08-26 23:19:57 -04005599template <typename ParamType>
5600bool ValidateSamplerParameterBase(Context *context,
5601 GLuint sampler,
5602 GLenum pname,
5603 GLsizei bufSize,
5604 ParamType *params)
5605{
5606 if (context->getClientMajorVersion() < 3)
5607 {
5608 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5609 return false;
5610 }
5611
5612 if (!context->isSampler(sampler))
5613 {
5614 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5615 return false;
5616 }
5617
5618 const GLsizei minBufSize = 1;
5619 if (bufSize >= 0 && bufSize < minBufSize)
5620 {
5621 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5622 return false;
5623 }
5624
5625 switch (pname)
5626 {
5627 case GL_TEXTURE_WRAP_S:
5628 case GL_TEXTURE_WRAP_T:
5629 case GL_TEXTURE_WRAP_R:
5630 if (!ValidateTextureWrapModeValue(context, params, false))
5631 {
5632 return false;
5633 }
5634 break;
5635
5636 case GL_TEXTURE_MIN_FILTER:
5637 if (!ValidateTextureMinFilterValue(context, params, false))
5638 {
5639 return false;
5640 }
5641 break;
5642
5643 case GL_TEXTURE_MAG_FILTER:
5644 if (!ValidateTextureMagFilterValue(context, params))
5645 {
5646 return false;
5647 }
5648 break;
5649
5650 case GL_TEXTURE_MIN_LOD:
5651 case GL_TEXTURE_MAX_LOD:
5652 // any value is permissible
5653 break;
5654
5655 case GL_TEXTURE_COMPARE_MODE:
5656 if (!ValidateTextureCompareModeValue(context, params))
5657 {
5658 return false;
5659 }
5660 break;
5661
5662 case GL_TEXTURE_COMPARE_FUNC:
5663 if (!ValidateTextureCompareFuncValue(context, params))
5664 {
5665 return false;
5666 }
5667 break;
5668
5669 case GL_TEXTURE_SRGB_DECODE_EXT:
5670 if (!ValidateTextureSRGBDecodeValue(context, params))
5671 {
5672 return false;
5673 }
5674 break;
5675
5676 default:
5677 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5678 return false;
5679 }
5680
5681 return true;
5682}
5683
5684template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5685template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5686
5687bool ValidateGetSamplerParameterBase(Context *context,
5688 GLuint sampler,
5689 GLenum pname,
5690 GLsizei *length)
5691{
5692 if (length)
5693 {
5694 *length = 0;
5695 }
5696
5697 if (context->getClientMajorVersion() < 3)
5698 {
5699 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5700 return false;
5701 }
5702
5703 if (!context->isSampler(sampler))
5704 {
5705 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5706 return false;
5707 }
5708
5709 switch (pname)
5710 {
5711 case GL_TEXTURE_WRAP_S:
5712 case GL_TEXTURE_WRAP_T:
5713 case GL_TEXTURE_WRAP_R:
5714 case GL_TEXTURE_MIN_FILTER:
5715 case GL_TEXTURE_MAG_FILTER:
5716 case GL_TEXTURE_MIN_LOD:
5717 case GL_TEXTURE_MAX_LOD:
5718 case GL_TEXTURE_COMPARE_MODE:
5719 case GL_TEXTURE_COMPARE_FUNC:
5720 break;
5721
5722 case GL_TEXTURE_SRGB_DECODE_EXT:
5723 if (!context->getExtensions().textureSRGBDecode)
5724 {
5725 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5726 return false;
5727 }
5728 break;
5729
5730 default:
5731 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5732 return false;
5733 }
5734
5735 if (length)
5736 {
5737 *length = 1;
5738 }
5739 return true;
5740}
5741
5742bool ValidateGetInternalFormativBase(Context *context,
5743 GLenum target,
5744 GLenum internalformat,
5745 GLenum pname,
5746 GLsizei bufSize,
5747 GLsizei *numParams)
5748{
5749 if (numParams)
5750 {
5751 *numParams = 0;
5752 }
5753
5754 if (context->getClientMajorVersion() < 3)
5755 {
5756 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
5757 return false;
5758 }
5759
5760 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5761 if (!formatCaps.renderable)
5762 {
5763 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5764 return false;
5765 }
5766
5767 switch (target)
5768 {
5769 case GL_RENDERBUFFER:
5770 break;
5771
5772 case GL_TEXTURE_2D_MULTISAMPLE:
5773 if (context->getClientVersion() < ES_3_1)
5774 {
5775 context->handleError(InvalidOperation()
5776 << "Texture target requires at least OpenGL ES 3.1.");
5777 return false;
5778 }
5779 break;
5780
5781 default:
5782 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5783 return false;
5784 }
5785
5786 if (bufSize < 0)
5787 {
5788 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5789 return false;
5790 }
5791
5792 GLsizei maxWriteParams = 0;
5793 switch (pname)
5794 {
5795 case GL_NUM_SAMPLE_COUNTS:
5796 maxWriteParams = 1;
5797 break;
5798
5799 case GL_SAMPLES:
5800 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5801 break;
5802
5803 default:
5804 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5805 return false;
5806 }
5807
5808 if (numParams)
5809 {
5810 // glGetInternalFormativ will not overflow bufSize
5811 *numParams = std::min(bufSize, maxWriteParams);
5812 }
5813
5814 return true;
5815}
5816
Jamie Madillc29968b2016-01-20 11:17:23 -05005817} // namespace gl