blob: ad66edead92741d02977bb34716cab80500d04eb [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
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002890 // Use the parameter buffer to retrieve and cache the index range.
2891 // TODO: offer fast path, with disabled index validation.
2892 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
2893 const auto &params = context->getParams<HasIndexRange>();
2894 const auto &indexRangeOpt = params.getIndexRange();
2895 if (!indexRangeOpt.valid())
2896 {
2897 // Unexpected error.
2898 return false;
2899 }
2900
2901 // If we use an index greater than our maximum supported index range, return an error.
2902 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2903 // return an error if possible here.
2904 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2905 {
2906 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2907 return false;
2908 }
2909
2910 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2911 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04002912 {
2913 return false;
2914 }
2915
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002916 // No op if there are no real indices in the index data (all are primitive restart).
2917 return (indexRangeOpt.value().vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04002918}
2919
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002920bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2921 GLenum mode,
2922 GLsizei count,
2923 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002924 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002925 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002926{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002927 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002928}
2929
Geoff Lang3edfe032015-09-04 16:38:24 -04002930bool ValidateDrawElementsInstancedANGLE(Context *context,
2931 GLenum mode,
2932 GLsizei count,
2933 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002934 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002935 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002936{
Corentin Wallez170efbf2017-05-02 13:45:01 -04002937 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002938 {
2939 return false;
2940 }
2941
Corentin Wallez0dc97812017-06-22 14:38:44 -04002942 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002943}
2944
He Yunchaoced53ae2016-11-29 15:00:51 +08002945bool ValidateFramebufferTextureBase(Context *context,
2946 GLenum target,
2947 GLenum attachment,
2948 GLuint texture,
2949 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002950{
Jamie Madill55ec3b12014-07-03 10:38:57 -04002951 if (!ValidFramebufferTarget(target))
2952 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002953 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002954 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002955 }
2956
2957 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002958 {
2959 return false;
2960 }
2961
Jamie Madill55ec3b12014-07-03 10:38:57 -04002962 if (texture != 0)
2963 {
2964 gl::Texture *tex = context->getTexture(texture);
2965
Jamie Madillbe849e42017-05-02 15:49:00 -04002966 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002967 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002968 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002969 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002970 }
2971
2972 if (level < 0)
2973 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002974 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002975 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002976 }
2977 }
2978
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002979 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002980 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002981
Jamie Madill84115c92015-04-23 15:00:07 -04002982 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002983 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002984 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002985 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002986 }
2987
2988 return true;
2989}
2990
Geoff Langb1196682014-07-23 13:47:29 -04002991bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04002992{
2993 if (program == 0)
2994 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002995 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002996 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002997 }
2998
Dian Xiang769769a2015-09-09 15:20:08 -07002999 gl::Program *programObject = GetValidProgram(context, program);
3000 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003001 {
3002 return false;
3003 }
3004
Jamie Madill0063c512014-08-25 15:47:53 -04003005 if (!programObject || !programObject->isLinked())
3006 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003007 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003008 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003009 }
3010
Geoff Lang7dd2e102014-11-10 15:19:26 -05003011 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003012 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003013 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003014 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003015 }
3016
Jamie Madill0063c512014-08-25 15:47:53 -04003017 return true;
3018}
3019
Geoff Langf41d0ee2016-10-07 13:04:23 -04003020static bool ValidateSizedGetUniform(Context *context,
3021 GLuint program,
3022 GLint location,
3023 GLsizei bufSize,
3024 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003025{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003026 if (length)
3027 {
3028 *length = 0;
3029 }
3030
Jamie Madill78f41802014-08-25 15:47:55 -04003031 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003032 {
Jamie Madill78f41802014-08-25 15:47:55 -04003033 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003034 }
3035
Geoff Langf41d0ee2016-10-07 13:04:23 -04003036 if (bufSize < 0)
3037 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003038 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003039 return false;
3040 }
3041
Jamie Madilla502c742014-08-28 17:19:13 -04003042 gl::Program *programObject = context->getProgram(program);
3043 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003044
Jamie Madill78f41802014-08-25 15:47:55 -04003045 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003046 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003047 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003048 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003049 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003050 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003051 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003052 }
3053
Geoff Langf41d0ee2016-10-07 13:04:23 -04003054 if (length)
3055 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003056 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003057 }
3058
Jamie Madill0063c512014-08-25 15:47:53 -04003059 return true;
3060}
3061
He Yunchaoced53ae2016-11-29 15:00:51 +08003062bool ValidateGetnUniformfvEXT(Context *context,
3063 GLuint program,
3064 GLint location,
3065 GLsizei bufSize,
3066 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003067{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003068 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003069}
3070
He Yunchaoced53ae2016-11-29 15:00:51 +08003071bool ValidateGetnUniformivEXT(Context *context,
3072 GLuint program,
3073 GLint location,
3074 GLsizei bufSize,
3075 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003076{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003077 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3078}
3079
3080bool ValidateGetUniformfvRobustANGLE(Context *context,
3081 GLuint program,
3082 GLint location,
3083 GLsizei bufSize,
3084 GLsizei *length,
3085 GLfloat *params)
3086{
3087 if (!ValidateRobustEntryPoint(context, bufSize))
3088 {
3089 return false;
3090 }
3091
3092 // bufSize is validated in ValidateSizedGetUniform
3093 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3094}
3095
3096bool ValidateGetUniformivRobustANGLE(Context *context,
3097 GLuint program,
3098 GLint location,
3099 GLsizei bufSize,
3100 GLsizei *length,
3101 GLint *params)
3102{
3103 if (!ValidateRobustEntryPoint(context, bufSize))
3104 {
3105 return false;
3106 }
3107
3108 // bufSize is validated in ValidateSizedGetUniform
3109 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3110}
3111
3112bool ValidateGetUniformuivRobustANGLE(Context *context,
3113 GLuint program,
3114 GLint location,
3115 GLsizei bufSize,
3116 GLsizei *length,
3117 GLuint *params)
3118{
3119 if (!ValidateRobustEntryPoint(context, bufSize))
3120 {
3121 return false;
3122 }
3123
3124 if (context->getClientMajorVersion() < 3)
3125 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003126 context->handleError(InvalidOperation() << "Entry point requires at least OpenGL ES 3.0.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003127 return false;
3128 }
3129
3130 // bufSize is validated in ValidateSizedGetUniform
3131 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003132}
3133
He Yunchaoced53ae2016-11-29 15:00:51 +08003134bool ValidateDiscardFramebufferBase(Context *context,
3135 GLenum target,
3136 GLsizei numAttachments,
3137 const GLenum *attachments,
3138 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003139{
3140 if (numAttachments < 0)
3141 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003142 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003143 return false;
3144 }
3145
3146 for (GLsizei i = 0; i < numAttachments; ++i)
3147 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003148 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003149 {
3150 if (defaultFramebuffer)
3151 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003152 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003153 return false;
3154 }
3155
3156 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3157 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003158 context->handleError(InvalidOperation() << "Requested color attachment is "
3159 "greater than the maximum supported "
3160 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003161 return false;
3162 }
3163 }
3164 else
3165 {
3166 switch (attachments[i])
3167 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003168 case GL_DEPTH_ATTACHMENT:
3169 case GL_STENCIL_ATTACHMENT:
3170 case GL_DEPTH_STENCIL_ATTACHMENT:
3171 if (defaultFramebuffer)
3172 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003173 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3174 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003175 return false;
3176 }
3177 break;
3178 case GL_COLOR:
3179 case GL_DEPTH:
3180 case GL_STENCIL:
3181 if (!defaultFramebuffer)
3182 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003183 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3184 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003185 return false;
3186 }
3187 break;
3188 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003189 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003190 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003191 }
3192 }
3193 }
3194
3195 return true;
3196}
3197
Austin Kinross6ee1e782015-05-29 17:05:37 -07003198bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3199{
3200 // Note that debug marker calls must not set error state
3201
3202 if (length < 0)
3203 {
3204 return false;
3205 }
3206
3207 if (marker == nullptr)
3208 {
3209 return false;
3210 }
3211
3212 return true;
3213}
3214
3215bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3216{
3217 // Note that debug marker calls must not set error state
3218
3219 if (length < 0)
3220 {
3221 return false;
3222 }
3223
3224 if (length > 0 && marker == nullptr)
3225 {
3226 return false;
3227 }
3228
3229 return true;
3230}
3231
Geoff Langdcab33b2015-07-21 13:03:16 -04003232bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003233 GLenum target,
3234 egl::Image *image)
3235{
Geoff Langa8406172015-07-21 16:53:39 -04003236 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3237 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003238 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003239 return false;
3240 }
3241
3242 switch (target)
3243 {
3244 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003245 if (!context->getExtensions().eglImage)
3246 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003247 context->handleError(InvalidEnum()
3248 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003249 }
3250 break;
3251
3252 case GL_TEXTURE_EXTERNAL_OES:
3253 if (!context->getExtensions().eglImageExternal)
3254 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003255 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3256 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003257 }
Geoff Langa8406172015-07-21 16:53:39 -04003258 break;
3259
3260 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003261 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003262 return false;
3263 }
3264
Jamie Madill61e16b42017-06-19 11:13:23 -04003265 ASSERT(context->getCurrentDisplay());
3266 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003267 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003268 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003269 return false;
3270 }
3271
3272 if (image->getSamples() > 0)
3273 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003274 context->handleError(InvalidOperation()
3275 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003276 return false;
3277 }
3278
Geoff Langca271392017-04-05 12:30:00 -04003279 const TextureCaps &textureCaps =
3280 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003281 if (!textureCaps.texturable)
3282 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003283 context->handleError(InvalidOperation()
3284 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003285 return false;
3286 }
3287
Geoff Langdcab33b2015-07-21 13:03:16 -04003288 return true;
3289}
3290
3291bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003292 GLenum target,
3293 egl::Image *image)
3294{
Geoff Langa8406172015-07-21 16:53:39 -04003295 if (!context->getExtensions().eglImage)
3296 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003297 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003298 return false;
3299 }
3300
3301 switch (target)
3302 {
3303 case GL_RENDERBUFFER:
3304 break;
3305
3306 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003307 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003308 return false;
3309 }
3310
Jamie Madill61e16b42017-06-19 11:13:23 -04003311 ASSERT(context->getCurrentDisplay());
3312 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003313 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003314 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003315 return false;
3316 }
3317
Geoff Langca271392017-04-05 12:30:00 -04003318 const TextureCaps &textureCaps =
3319 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003320 if (!textureCaps.renderable)
3321 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003322 context->handleError(InvalidOperation()
3323 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003324 return false;
3325 }
3326
Geoff Langdcab33b2015-07-21 13:03:16 -04003327 return true;
3328}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003329
3330bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3331{
Geoff Lang36167ab2015-12-07 10:27:14 -05003332 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003333 {
3334 // The default VAO should always exist
3335 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003336 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003337 return false;
3338 }
3339
3340 return true;
3341}
3342
Geoff Langc5629752015-12-07 16:29:04 -05003343bool ValidateProgramBinaryBase(Context *context,
3344 GLuint program,
3345 GLenum binaryFormat,
3346 const void *binary,
3347 GLint length)
3348{
3349 Program *programObject = GetValidProgram(context, program);
3350 if (programObject == nullptr)
3351 {
3352 return false;
3353 }
3354
3355 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3356 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3357 programBinaryFormats.end())
3358 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003359 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003360 return false;
3361 }
3362
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003363 if (context->hasActiveTransformFeedback(program))
3364 {
3365 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003366 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3367 "is associated with an active transform "
3368 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003369 return false;
3370 }
3371
Geoff Langc5629752015-12-07 16:29:04 -05003372 return true;
3373}
3374
3375bool ValidateGetProgramBinaryBase(Context *context,
3376 GLuint program,
3377 GLsizei bufSize,
3378 GLsizei *length,
3379 GLenum *binaryFormat,
3380 void *binary)
3381{
3382 Program *programObject = GetValidProgram(context, program);
3383 if (programObject == nullptr)
3384 {
3385 return false;
3386 }
3387
3388 if (!programObject->isLinked())
3389 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003390 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003391 return false;
3392 }
3393
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003394 if (context->getCaps().programBinaryFormats.empty())
3395 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003396 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003397 return false;
3398 }
3399
Geoff Langc5629752015-12-07 16:29:04 -05003400 return true;
3401}
Jamie Madillc29968b2016-01-20 11:17:23 -05003402
Jamie Madillc29968b2016-01-20 11:17:23 -05003403bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3404{
3405 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003406 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003407 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003408 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3409 return false;
3410 }
3411 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3412 {
3413 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003414 return false;
3415 }
3416
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003417 ASSERT(context->getGLState().getDrawFramebuffer());
3418 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003419 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3420
3421 // This should come first before the check for the default frame buffer
3422 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3423 // rather than INVALID_OPERATION
3424 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3425 {
3426 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3427
3428 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003429 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3430 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003431 {
3432 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003433 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3434 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3435 // 3.1 is still a bit ambiguous about the error, but future specs are
3436 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003437 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003438 return false;
3439 }
3440 else if (bufs[colorAttachment] >= maxColorAttachment)
3441 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003442 context->handleError(InvalidOperation()
3443 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003444 return false;
3445 }
3446 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3447 frameBufferId != 0)
3448 {
3449 // INVALID_OPERATION-GL is bound to buffer and ith argument
3450 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003451 context->handleError(InvalidOperation()
3452 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003453 return false;
3454 }
3455 }
3456
3457 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3458 // and n is not 1 or bufs is bound to value other than BACK and NONE
3459 if (frameBufferId == 0)
3460 {
3461 if (n != 1)
3462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003463 context->handleError(InvalidOperation()
3464 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003465 return false;
3466 }
3467
3468 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3469 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003470 context->handleError(
3471 InvalidOperation()
3472 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003473 return false;
3474 }
3475 }
3476
3477 return true;
3478}
3479
Geoff Lang496c02d2016-10-20 11:38:11 -07003480bool ValidateGetBufferPointervBase(Context *context,
3481 GLenum target,
3482 GLenum pname,
3483 GLsizei *length,
3484 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003485{
Geoff Lang496c02d2016-10-20 11:38:11 -07003486 if (length)
3487 {
3488 *length = 0;
3489 }
3490
3491 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3492 {
3493 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003494 InvalidOperation()
3495 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003496 return false;
3497 }
3498
Olli Etuaho4f667482016-03-30 15:56:35 +03003499 if (!ValidBufferTarget(context, target))
3500 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003501 context->handleError(InvalidEnum() << "Buffer target not valid: 0x" << std::hex
3502 << std::uppercase << target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003503 return false;
3504 }
3505
Geoff Lang496c02d2016-10-20 11:38:11 -07003506 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003507 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003508 case GL_BUFFER_MAP_POINTER:
3509 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003510
Geoff Lang496c02d2016-10-20 11:38:11 -07003511 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003512 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003513 return false;
3514 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003515
3516 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3517 // target bound to zero generate an INVALID_OPERATION error."
3518 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003519 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003521 context->handleError(InvalidOperation()
3522 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003523 return false;
3524 }
3525
Geoff Lang496c02d2016-10-20 11:38:11 -07003526 if (length)
3527 {
3528 *length = 1;
3529 }
3530
Olli Etuaho4f667482016-03-30 15:56:35 +03003531 return true;
3532}
3533
3534bool ValidateUnmapBufferBase(Context *context, GLenum target)
3535{
3536 if (!ValidBufferTarget(context, target))
3537 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003538 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003539 return false;
3540 }
3541
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003542 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003543
3544 if (buffer == nullptr || !buffer->isMapped())
3545 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003546 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003547 return false;
3548 }
3549
3550 return true;
3551}
3552
3553bool ValidateMapBufferRangeBase(Context *context,
3554 GLenum target,
3555 GLintptr offset,
3556 GLsizeiptr length,
3557 GLbitfield access)
3558{
3559 if (!ValidBufferTarget(context, target))
3560 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003561 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003562 return false;
3563 }
3564
Brandon Jones6cad5662017-06-14 13:25:13 -07003565 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003566 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003567 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3568 return false;
3569 }
3570
3571 if (length < 0)
3572 {
3573 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003574 return false;
3575 }
3576
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003577 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003578
3579 if (!buffer)
3580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003581 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003582 return false;
3583 }
3584
3585 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003586 CheckedNumeric<size_t> checkedOffset(offset);
3587 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003588
Jamie Madille2e406c2016-06-02 13:04:10 -04003589 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003590 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003591 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003592 return false;
3593 }
3594
3595 // Check for invalid bits in the mask
3596 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3597 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3598 GL_MAP_UNSYNCHRONIZED_BIT;
3599
3600 if (access & ~(allAccessBits))
3601 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003602 context->handleError(InvalidValue()
3603 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003604 return false;
3605 }
3606
3607 if (length == 0)
3608 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003609 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003610 return false;
3611 }
3612
3613 if (buffer->isMapped())
3614 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003615 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003616 return false;
3617 }
3618
3619 // Check for invalid bit combinations
3620 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3621 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003622 context->handleError(InvalidOperation()
3623 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003624 return false;
3625 }
3626
3627 GLbitfield writeOnlyBits =
3628 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3629
3630 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3631 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003632 context->handleError(InvalidOperation()
3633 << "Invalid access bits when mapping buffer for reading: 0x"
3634 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003635 return false;
3636 }
3637
3638 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3639 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003640 context->handleError(
3641 InvalidOperation()
3642 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003643 return false;
3644 }
Geoff Lang79f71042017-08-14 16:43:43 -04003645
3646 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003647}
3648
3649bool ValidateFlushMappedBufferRangeBase(Context *context,
3650 GLenum target,
3651 GLintptr offset,
3652 GLsizeiptr length)
3653{
Brandon Jones6cad5662017-06-14 13:25:13 -07003654 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003655 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003656 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3657 return false;
3658 }
3659
3660 if (length < 0)
3661 {
3662 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003663 return false;
3664 }
3665
3666 if (!ValidBufferTarget(context, target))
3667 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003668 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003669 return false;
3670 }
3671
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003672 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003673
3674 if (buffer == nullptr)
3675 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003676 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003677 return false;
3678 }
3679
3680 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3681 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003682 context->handleError(InvalidOperation()
3683 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003684 return false;
3685 }
3686
3687 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003688 CheckedNumeric<size_t> checkedOffset(offset);
3689 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003690
Jamie Madille2e406c2016-06-02 13:04:10 -04003691 if (!checkedSize.IsValid() ||
3692 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003693 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003694 context->handleError(InvalidValue()
3695 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003696 return false;
3697 }
3698
3699 return true;
3700}
3701
Olli Etuaho41997e72016-03-10 13:38:39 +02003702bool ValidateGenOrDelete(Context *context, GLint n)
3703{
3704 if (n < 0)
3705 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003706 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003707 return false;
3708 }
3709 return true;
3710}
3711
Geoff Langff5b2d52016-09-07 11:32:23 -04003712bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3713{
3714 if (!context->getExtensions().robustClientMemory)
3715 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003716 context->handleError(InvalidOperation()
3717 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003718 return false;
3719 }
3720
3721 if (bufSize < 0)
3722 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003723 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003724 return false;
3725 }
3726
3727 return true;
3728}
3729
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003730bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3731{
3732 if (bufSize < numParams)
3733 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003734 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3735 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003736 return false;
3737 }
3738
3739 return true;
3740}
3741
Jamie Madillbe849e42017-05-02 15:49:00 -04003742bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3743 GLenum target,
3744 GLenum attachment,
3745 GLenum pname,
3746 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003747{
Geoff Langff5b2d52016-09-07 11:32:23 -04003748 if (!ValidFramebufferTarget(target))
3749 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003750 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003751 return false;
3752 }
3753
3754 int clientVersion = context->getClientMajorVersion();
3755
3756 switch (pname)
3757 {
3758 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3759 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3760 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3761 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3762 break;
3763
Martin Radeve5285d22017-07-14 16:23:53 +03003764 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3765 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3766 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3767 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3768 if (clientVersion < 3 || !context->getExtensions().multiview)
3769 {
3770 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3771 return false;
3772 }
3773 break;
3774
Geoff Langff5b2d52016-09-07 11:32:23 -04003775 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3776 if (clientVersion < 3 && !context->getExtensions().sRGB)
3777 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003778 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003779 return false;
3780 }
3781 break;
3782
3783 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3784 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3785 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3786 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3787 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3788 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3789 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3790 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3791 if (clientVersion < 3)
3792 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003793 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003794 return false;
3795 }
3796 break;
3797
3798 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003799 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003800 return false;
3801 }
3802
3803 // Determine if the attachment is a valid enum
3804 switch (attachment)
3805 {
3806 case GL_BACK:
3807 case GL_FRONT:
3808 case GL_DEPTH:
3809 case GL_STENCIL:
3810 case GL_DEPTH_STENCIL_ATTACHMENT:
3811 if (clientVersion < 3)
3812 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003813 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003814 return false;
3815 }
3816 break;
3817
3818 case GL_DEPTH_ATTACHMENT:
3819 case GL_STENCIL_ATTACHMENT:
3820 break;
3821
3822 default:
3823 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
3824 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3825 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003826 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003827 return false;
3828 }
3829 break;
3830 }
3831
3832 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3833 ASSERT(framebuffer);
3834
3835 if (framebuffer->id() == 0)
3836 {
3837 if (clientVersion < 3)
3838 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003839 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003840 return false;
3841 }
3842
3843 switch (attachment)
3844 {
3845 case GL_BACK:
3846 case GL_DEPTH:
3847 case GL_STENCIL:
3848 break;
3849
3850 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003851 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003852 return false;
3853 }
3854 }
3855 else
3856 {
3857 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3858 {
3859 // Valid attachment query
3860 }
3861 else
3862 {
3863 switch (attachment)
3864 {
3865 case GL_DEPTH_ATTACHMENT:
3866 case GL_STENCIL_ATTACHMENT:
3867 break;
3868
3869 case GL_DEPTH_STENCIL_ATTACHMENT:
3870 if (!framebuffer->hasValidDepthStencil())
3871 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003872 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003873 return false;
3874 }
3875 break;
3876
3877 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003878 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003879 return false;
3880 }
3881 }
3882 }
3883
3884 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3885 if (attachmentObject)
3886 {
3887 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3888 attachmentObject->type() == GL_TEXTURE ||
3889 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3890
3891 switch (pname)
3892 {
3893 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3894 if (attachmentObject->type() != GL_RENDERBUFFER &&
3895 attachmentObject->type() != GL_TEXTURE)
3896 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003897 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003898 return false;
3899 }
3900 break;
3901
3902 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3903 if (attachmentObject->type() != GL_TEXTURE)
3904 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003905 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003906 return false;
3907 }
3908 break;
3909
3910 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3911 if (attachmentObject->type() != GL_TEXTURE)
3912 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003913 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003914 return false;
3915 }
3916 break;
3917
3918 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3919 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3920 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003921 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003922 return false;
3923 }
3924 break;
3925
3926 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3927 if (attachmentObject->type() != GL_TEXTURE)
3928 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003929 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003930 return false;
3931 }
3932 break;
3933
3934 default:
3935 break;
3936 }
3937 }
3938 else
3939 {
3940 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3941 // is NONE, then querying any other pname will generate INVALID_ENUM.
3942
3943 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3944 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3945 // INVALID_OPERATION for all other pnames
3946
3947 switch (pname)
3948 {
3949 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3950 break;
3951
3952 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3953 if (clientVersion < 3)
3954 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003955 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07003956 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003957 return false;
3958 }
3959 break;
3960
3961 default:
3962 if (clientVersion < 3)
3963 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003964 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07003965 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003966 return false;
3967 }
3968 else
3969 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003970 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Brandon Jonesafa75152017-07-21 13:11:29 -07003971 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003972 return false;
3973 }
3974 }
3975 }
3976
Martin Radeve5285d22017-07-14 16:23:53 +03003977 if (numParams)
3978 {
3979 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
3980 {
3981 // Only when the viewport offsets are queried we can have a varying number of output
3982 // parameters.
3983 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
3984 *numParams = numViews * 2;
3985 }
3986 else
3987 {
3988 // For all other queries we can have only one output parameter.
3989 *numParams = 1;
3990 }
3991 }
3992
Geoff Langff5b2d52016-09-07 11:32:23 -04003993 return true;
3994}
3995
3996bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
3997 GLenum target,
3998 GLenum attachment,
3999 GLenum pname,
4000 GLsizei bufSize,
4001 GLsizei *numParams)
4002{
4003 if (!ValidateRobustEntryPoint(context, bufSize))
4004 {
4005 return false;
4006 }
4007
Jamie Madillbe849e42017-05-02 15:49:00 -04004008 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4009 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004010 {
4011 return false;
4012 }
4013
4014 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4015 {
4016 return false;
4017 }
4018
4019 return true;
4020}
4021
Geoff Langff5b2d52016-09-07 11:32:23 -04004022bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4023 GLenum target,
4024 GLenum pname,
4025 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004026 GLsizei *length,
4027 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004028{
4029 if (!ValidateRobustEntryPoint(context, bufSize))
4030 {
4031 return false;
4032 }
4033
Geoff Langebebe1c2016-10-14 12:01:31 -04004034 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004035 {
4036 return false;
4037 }
4038
Geoff Langebebe1c2016-10-14 12:01:31 -04004039 if (!ValidateRobustBufferSize(context, bufSize, *length))
4040 {
4041 return false;
4042 }
4043
4044 return true;
4045}
4046
Geoff Langebebe1c2016-10-14 12:01:31 -04004047bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4048 GLenum target,
4049 GLenum pname,
4050 GLsizei bufSize,
4051 GLsizei *length,
4052 GLint64 *params)
4053{
4054 if (!ValidateRobustEntryPoint(context, bufSize))
4055 {
4056 return false;
4057 }
4058
4059 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4060 {
4061 return false;
4062 }
4063
4064 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004065 {
4066 return false;
4067 }
4068
4069 return true;
4070}
4071
Jamie Madillbe849e42017-05-02 15:49:00 -04004072bool ValidateGetProgramivBase(ValidationContext *context,
4073 GLuint program,
4074 GLenum pname,
4075 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004076{
4077 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004078 if (numParams)
4079 {
4080 *numParams = 1;
4081 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004082
4083 Program *programObject = GetValidProgram(context, program);
4084 if (!programObject)
4085 {
4086 return false;
4087 }
4088
4089 switch (pname)
4090 {
4091 case GL_DELETE_STATUS:
4092 case GL_LINK_STATUS:
4093 case GL_VALIDATE_STATUS:
4094 case GL_INFO_LOG_LENGTH:
4095 case GL_ATTACHED_SHADERS:
4096 case GL_ACTIVE_ATTRIBUTES:
4097 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4098 case GL_ACTIVE_UNIFORMS:
4099 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4100 break;
4101
4102 case GL_PROGRAM_BINARY_LENGTH:
4103 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4104 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004105 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4106 "requires GL_OES_get_program_binary or "
4107 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004108 return false;
4109 }
4110 break;
4111
4112 case GL_ACTIVE_UNIFORM_BLOCKS:
4113 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4114 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4115 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4116 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4117 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4118 if (context->getClientMajorVersion() < 3)
4119 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004120 context->handleError(InvalidEnum() << "Querying requires at least ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004121 return false;
4122 }
4123 break;
4124
Yunchao He61afff12017-03-14 15:34:03 +08004125 case GL_PROGRAM_SEPARABLE:
4126 if (context->getClientVersion() < Version(3, 1))
4127 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004128 context->handleError(InvalidEnum() << "Querying requires at least ES 3.1.");
Yunchao He61afff12017-03-14 15:34:03 +08004129 return false;
4130 }
4131 break;
4132
Geoff Langff5b2d52016-09-07 11:32:23 -04004133 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004134 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004135 return false;
4136 }
4137
4138 return true;
4139}
4140
4141bool ValidateGetProgramivRobustANGLE(Context *context,
4142 GLuint program,
4143 GLenum pname,
4144 GLsizei bufSize,
4145 GLsizei *numParams)
4146{
4147 if (!ValidateRobustEntryPoint(context, bufSize))
4148 {
4149 return false;
4150 }
4151
Jamie Madillbe849e42017-05-02 15:49:00 -04004152 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004153 {
4154 return false;
4155 }
4156
4157 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4158 {
4159 return false;
4160 }
4161
4162 return true;
4163}
4164
Geoff Lang740d9022016-10-07 11:20:52 -04004165bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4166 GLenum target,
4167 GLenum pname,
4168 GLsizei bufSize,
4169 GLsizei *length,
4170 GLint *params)
4171{
4172 if (!ValidateRobustEntryPoint(context, bufSize))
4173 {
4174 return false;
4175 }
4176
4177 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4178 {
4179 return false;
4180 }
4181
4182 if (!ValidateRobustBufferSize(context, bufSize, *length))
4183 {
4184 return false;
4185 }
4186
4187 return true;
4188}
4189
Geoff Langd7d0ed32016-10-07 11:33:51 -04004190bool ValidateGetShaderivRobustANGLE(Context *context,
4191 GLuint shader,
4192 GLenum pname,
4193 GLsizei bufSize,
4194 GLsizei *length,
4195 GLint *params)
4196{
4197 if (!ValidateRobustEntryPoint(context, bufSize))
4198 {
4199 return false;
4200 }
4201
4202 if (!ValidateGetShaderivBase(context, shader, pname, length))
4203 {
4204 return false;
4205 }
4206
4207 if (!ValidateRobustBufferSize(context, bufSize, *length))
4208 {
4209 return false;
4210 }
4211
4212 return true;
4213}
4214
Geoff Langc1984ed2016-10-07 12:41:00 -04004215bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4216 GLenum target,
4217 GLenum pname,
4218 GLsizei bufSize,
4219 GLsizei *length,
4220 GLfloat *params)
4221{
4222 if (!ValidateRobustEntryPoint(context, bufSize))
4223 {
4224 return false;
4225 }
4226
4227 if (!ValidateGetTexParameterBase(context, target, pname, length))
4228 {
4229 return false;
4230 }
4231
4232 if (!ValidateRobustBufferSize(context, bufSize, *length))
4233 {
4234 return false;
4235 }
4236
4237 return true;
4238}
4239
Geoff Langc1984ed2016-10-07 12:41:00 -04004240bool ValidateGetTexParameterivRobustANGLE(Context *context,
4241 GLenum target,
4242 GLenum pname,
4243 GLsizei bufSize,
4244 GLsizei *length,
4245 GLint *params)
4246{
4247 if (!ValidateRobustEntryPoint(context, bufSize))
4248 {
4249 return false;
4250 }
4251
4252 if (!ValidateGetTexParameterBase(context, target, pname, length))
4253 {
4254 return false;
4255 }
4256
4257 if (!ValidateRobustBufferSize(context, bufSize, *length))
4258 {
4259 return false;
4260 }
4261
4262 return true;
4263}
4264
Geoff Langc1984ed2016-10-07 12:41:00 -04004265bool ValidateTexParameterfvRobustANGLE(Context *context,
4266 GLenum target,
4267 GLenum pname,
4268 GLsizei bufSize,
4269 const GLfloat *params)
4270{
4271 if (!ValidateRobustEntryPoint(context, bufSize))
4272 {
4273 return false;
4274 }
4275
4276 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4277}
4278
Geoff Langc1984ed2016-10-07 12:41:00 -04004279bool ValidateTexParameterivRobustANGLE(Context *context,
4280 GLenum target,
4281 GLenum pname,
4282 GLsizei bufSize,
4283 const GLint *params)
4284{
4285 if (!ValidateRobustEntryPoint(context, bufSize))
4286 {
4287 return false;
4288 }
4289
4290 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4291}
4292
Geoff Langc1984ed2016-10-07 12:41:00 -04004293bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4294 GLuint sampler,
4295 GLenum pname,
4296 GLuint bufSize,
4297 GLsizei *length,
4298 GLfloat *params)
4299{
4300 if (!ValidateRobustEntryPoint(context, bufSize))
4301 {
4302 return false;
4303 }
4304
4305 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4306 {
4307 return false;
4308 }
4309
4310 if (!ValidateRobustBufferSize(context, bufSize, *length))
4311 {
4312 return false;
4313 }
4314
4315 return true;
4316}
4317
Geoff Langc1984ed2016-10-07 12:41:00 -04004318bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4319 GLuint sampler,
4320 GLenum pname,
4321 GLuint bufSize,
4322 GLsizei *length,
4323 GLint *params)
4324{
4325 if (!ValidateRobustEntryPoint(context, bufSize))
4326 {
4327 return false;
4328 }
4329
4330 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4331 {
4332 return false;
4333 }
4334
4335 if (!ValidateRobustBufferSize(context, bufSize, *length))
4336 {
4337 return false;
4338 }
4339
4340 return true;
4341}
4342
Geoff Langc1984ed2016-10-07 12:41:00 -04004343bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4344 GLuint sampler,
4345 GLenum pname,
4346 GLsizei bufSize,
4347 const GLfloat *params)
4348{
4349 if (!ValidateRobustEntryPoint(context, bufSize))
4350 {
4351 return false;
4352 }
4353
4354 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4355}
4356
Geoff Langc1984ed2016-10-07 12:41:00 -04004357bool ValidateSamplerParameterivRobustANGLE(Context *context,
4358 GLuint sampler,
4359 GLenum pname,
4360 GLsizei bufSize,
4361 const GLint *params)
4362{
4363 if (!ValidateRobustEntryPoint(context, bufSize))
4364 {
4365 return false;
4366 }
4367
4368 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4369}
4370
Geoff Lang0b031062016-10-13 14:30:04 -04004371bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4372 GLuint index,
4373 GLenum pname,
4374 GLsizei bufSize,
4375 GLsizei *length,
4376 GLfloat *params)
4377{
4378 if (!ValidateRobustEntryPoint(context, bufSize))
4379 {
4380 return false;
4381 }
4382
4383 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4384 {
4385 return false;
4386 }
4387
4388 if (!ValidateRobustBufferSize(context, bufSize, *length))
4389 {
4390 return false;
4391 }
4392
4393 return true;
4394}
4395
Geoff Lang0b031062016-10-13 14:30:04 -04004396bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4397 GLuint index,
4398 GLenum pname,
4399 GLsizei bufSize,
4400 GLsizei *length,
4401 GLint *params)
4402{
4403 if (!ValidateRobustEntryPoint(context, bufSize))
4404 {
4405 return false;
4406 }
4407
4408 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4409 {
4410 return false;
4411 }
4412
4413 if (!ValidateRobustBufferSize(context, bufSize, *length))
4414 {
4415 return false;
4416 }
4417
4418 return true;
4419}
4420
Geoff Lang0b031062016-10-13 14:30:04 -04004421bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4422 GLuint index,
4423 GLenum pname,
4424 GLsizei bufSize,
4425 GLsizei *length,
4426 void **pointer)
4427{
4428 if (!ValidateRobustEntryPoint(context, bufSize))
4429 {
4430 return false;
4431 }
4432
4433 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4434 {
4435 return false;
4436 }
4437
4438 if (!ValidateRobustBufferSize(context, bufSize, *length))
4439 {
4440 return false;
4441 }
4442
4443 return true;
4444}
4445
Geoff Lang0b031062016-10-13 14:30:04 -04004446bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4447 GLuint index,
4448 GLenum pname,
4449 GLsizei bufSize,
4450 GLsizei *length,
4451 GLint *params)
4452{
4453 if (!ValidateRobustEntryPoint(context, bufSize))
4454 {
4455 return false;
4456 }
4457
4458 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4459 {
4460 return false;
4461 }
4462
4463 if (!ValidateRobustBufferSize(context, bufSize, *length))
4464 {
4465 return false;
4466 }
4467
4468 return true;
4469}
4470
Geoff Lang0b031062016-10-13 14:30:04 -04004471bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4472 GLuint index,
4473 GLenum pname,
4474 GLsizei bufSize,
4475 GLsizei *length,
4476 GLuint *params)
4477{
4478 if (!ValidateRobustEntryPoint(context, bufSize))
4479 {
4480 return false;
4481 }
4482
4483 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4484 {
4485 return false;
4486 }
4487
4488 if (!ValidateRobustBufferSize(context, bufSize, *length))
4489 {
4490 return false;
4491 }
4492
4493 return true;
4494}
4495
Geoff Lang6899b872016-10-14 11:30:13 -04004496bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4497 GLuint program,
4498 GLuint uniformBlockIndex,
4499 GLenum pname,
4500 GLsizei bufSize,
4501 GLsizei *length,
4502 GLint *params)
4503{
4504 if (!ValidateRobustEntryPoint(context, bufSize))
4505 {
4506 return false;
4507 }
4508
4509 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4510 {
4511 return false;
4512 }
4513
4514 if (!ValidateRobustBufferSize(context, bufSize, *length))
4515 {
4516 return false;
4517 }
4518
4519 return true;
4520}
4521
Geoff Lang0a9661f2016-10-20 10:59:20 -07004522bool ValidateGetInternalFormativRobustANGLE(Context *context,
4523 GLenum target,
4524 GLenum internalformat,
4525 GLenum pname,
4526 GLsizei bufSize,
4527 GLsizei *length,
4528 GLint *params)
4529{
4530 if (!ValidateRobustEntryPoint(context, bufSize))
4531 {
4532 return false;
4533 }
4534
4535 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4536 {
4537 return false;
4538 }
4539
4540 if (!ValidateRobustBufferSize(context, bufSize, *length))
4541 {
4542 return false;
4543 }
4544
4545 return true;
4546}
4547
Shao80957d92017-02-20 21:25:59 +08004548bool ValidateVertexFormatBase(ValidationContext *context,
4549 GLuint attribIndex,
4550 GLint size,
4551 GLenum type,
4552 GLboolean pureInteger)
4553{
4554 const Caps &caps = context->getCaps();
4555 if (attribIndex >= caps.maxVertexAttributes)
4556 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004557 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004558 return false;
4559 }
4560
4561 if (size < 1 || size > 4)
4562 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004563 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004564 return false;
Shao80957d92017-02-20 21:25:59 +08004565 }
4566
4567 switch (type)
4568 {
4569 case GL_BYTE:
4570 case GL_UNSIGNED_BYTE:
4571 case GL_SHORT:
4572 case GL_UNSIGNED_SHORT:
4573 break;
4574
4575 case GL_INT:
4576 case GL_UNSIGNED_INT:
4577 if (context->getClientMajorVersion() < 3)
4578 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004579 context->handleError(InvalidEnum()
4580 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004581 return false;
4582 }
4583 break;
4584
4585 case GL_FIXED:
4586 case GL_FLOAT:
4587 if (pureInteger)
4588 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004589 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004590 return false;
4591 }
4592 break;
4593
4594 case GL_HALF_FLOAT:
4595 if (context->getClientMajorVersion() < 3)
4596 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004597 context->handleError(InvalidEnum()
4598 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004599 return false;
4600 }
4601 if (pureInteger)
4602 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004603 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004604 return false;
4605 }
4606 break;
4607
4608 case GL_INT_2_10_10_10_REV:
4609 case GL_UNSIGNED_INT_2_10_10_10_REV:
4610 if (context->getClientMajorVersion() < 3)
4611 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004612 context->handleError(InvalidEnum()
4613 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004614 return false;
4615 }
4616 if (pureInteger)
4617 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004618 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004619 return false;
4620 }
4621 if (size != 4)
4622 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004623 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4624 "UNSIGNED_INT_2_10_10_10_REV and "
4625 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004626 return false;
4627 }
4628 break;
4629
4630 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004631 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004632 return false;
4633 }
4634
4635 return true;
4636}
4637
Geoff Lang76e65652017-03-27 14:58:02 -04004638// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4639// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4640// specified clear value and the type of a buffer that is being cleared generates an
4641// INVALID_OPERATION error instead of producing undefined results
4642bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4643 GLint drawbuffer,
4644 const GLenum *validComponentTypes,
4645 size_t validComponentTypeCount)
4646{
4647 const FramebufferAttachment *attachment =
4648 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4649 if (attachment)
4650 {
4651 GLenum componentType = attachment->getFormat().info->componentType;
4652 const GLenum *end = validComponentTypes + validComponentTypeCount;
4653 if (std::find(validComponentTypes, end, componentType) == end)
4654 {
4655 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004656 InvalidOperation()
4657 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004658 return false;
4659 }
4660 }
4661
4662 return true;
4663}
4664
Corentin Wallezb2931602017-04-11 15:58:57 -04004665bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4666 GLsizei imageSize,
4667 GLsizei dataSize)
4668{
4669 if (!ValidateRobustEntryPoint(context, dataSize))
4670 {
4671 return false;
4672 }
4673
4674 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
4675 if (pixelUnpackBuffer == nullptr)
4676 {
4677 if (dataSize < imageSize)
4678 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004679 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004680 }
4681 }
4682 return true;
4683}
4684
Jamie Madillbe849e42017-05-02 15:49:00 -04004685bool ValidateGetBufferParameterBase(ValidationContext *context,
4686 GLenum target,
4687 GLenum pname,
4688 bool pointerVersion,
4689 GLsizei *numParams)
4690{
4691 if (numParams)
4692 {
4693 *numParams = 0;
4694 }
4695
4696 if (!ValidBufferTarget(context, target))
4697 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004698 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004699 return false;
4700 }
4701
4702 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4703 if (!buffer)
4704 {
4705 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004706 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004707 return false;
4708 }
4709
4710 const Extensions &extensions = context->getExtensions();
4711
4712 switch (pname)
4713 {
4714 case GL_BUFFER_USAGE:
4715 case GL_BUFFER_SIZE:
4716 break;
4717
4718 case GL_BUFFER_ACCESS_OES:
4719 if (!extensions.mapBuffer)
4720 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004721 context->handleError(InvalidEnum()
4722 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004723 return false;
4724 }
4725 break;
4726
4727 case GL_BUFFER_MAPPED:
4728 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4729 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4730 !extensions.mapBufferRange)
4731 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004732 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4733 "GL_OES_mapbuffer or "
4734 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004735 return false;
4736 }
4737 break;
4738
4739 case GL_BUFFER_MAP_POINTER:
4740 if (!pointerVersion)
4741 {
4742 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004743 InvalidEnum()
4744 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004745 return false;
4746 }
4747 break;
4748
4749 case GL_BUFFER_ACCESS_FLAGS:
4750 case GL_BUFFER_MAP_OFFSET:
4751 case GL_BUFFER_MAP_LENGTH:
4752 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4753 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004754 context->handleError(InvalidEnum()
4755 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004756 return false;
4757 }
4758 break;
4759
4760 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004761 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004762 return false;
4763 }
4764
4765 // All buffer parameter queries return one value.
4766 if (numParams)
4767 {
4768 *numParams = 1;
4769 }
4770
4771 return true;
4772}
4773
4774bool ValidateGetRenderbufferParameterivBase(Context *context,
4775 GLenum target,
4776 GLenum pname,
4777 GLsizei *length)
4778{
4779 if (length)
4780 {
4781 *length = 0;
4782 }
4783
4784 if (target != GL_RENDERBUFFER)
4785 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004786 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004787 return false;
4788 }
4789
4790 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4791 if (renderbuffer == nullptr)
4792 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004793 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004794 return false;
4795 }
4796
4797 switch (pname)
4798 {
4799 case GL_RENDERBUFFER_WIDTH:
4800 case GL_RENDERBUFFER_HEIGHT:
4801 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4802 case GL_RENDERBUFFER_RED_SIZE:
4803 case GL_RENDERBUFFER_GREEN_SIZE:
4804 case GL_RENDERBUFFER_BLUE_SIZE:
4805 case GL_RENDERBUFFER_ALPHA_SIZE:
4806 case GL_RENDERBUFFER_DEPTH_SIZE:
4807 case GL_RENDERBUFFER_STENCIL_SIZE:
4808 break;
4809
4810 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4811 if (!context->getExtensions().framebufferMultisample)
4812 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004813 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004814 return false;
4815 }
4816 break;
4817
4818 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004819 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004820 return false;
4821 }
4822
4823 if (length)
4824 {
4825 *length = 1;
4826 }
4827 return true;
4828}
4829
4830bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4831{
4832 if (length)
4833 {
4834 *length = 0;
4835 }
4836
4837 if (GetValidShader(context, shader) == nullptr)
4838 {
4839 return false;
4840 }
4841
4842 switch (pname)
4843 {
4844 case GL_SHADER_TYPE:
4845 case GL_DELETE_STATUS:
4846 case GL_COMPILE_STATUS:
4847 case GL_INFO_LOG_LENGTH:
4848 case GL_SHADER_SOURCE_LENGTH:
4849 break;
4850
4851 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4852 if (!context->getExtensions().translatedShaderSource)
4853 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004854 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004855 return false;
4856 }
4857 break;
4858
4859 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004860 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004861 return false;
4862 }
4863
4864 if (length)
4865 {
4866 *length = 1;
4867 }
4868 return true;
4869}
4870
4871bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4872{
4873 if (length)
4874 {
4875 *length = 0;
4876 }
4877
4878 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4879 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004880 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004881 return false;
4882 }
4883
4884 if (context->getTargetTexture(target) == nullptr)
4885 {
4886 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004887 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004888 return false;
4889 }
4890
4891 switch (pname)
4892 {
4893 case GL_TEXTURE_MAG_FILTER:
4894 case GL_TEXTURE_MIN_FILTER:
4895 case GL_TEXTURE_WRAP_S:
4896 case GL_TEXTURE_WRAP_T:
4897 break;
4898
4899 case GL_TEXTURE_USAGE_ANGLE:
4900 if (!context->getExtensions().textureUsage)
4901 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004902 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004903 return false;
4904 }
4905 break;
4906
4907 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4908 if (!context->getExtensions().textureFilterAnisotropic)
4909 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004910 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004911 return false;
4912 }
4913 break;
4914
4915 case GL_TEXTURE_IMMUTABLE_FORMAT:
4916 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4917 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004918 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004919 return false;
4920 }
4921 break;
4922
4923 case GL_TEXTURE_WRAP_R:
4924 case GL_TEXTURE_IMMUTABLE_LEVELS:
4925 case GL_TEXTURE_SWIZZLE_R:
4926 case GL_TEXTURE_SWIZZLE_G:
4927 case GL_TEXTURE_SWIZZLE_B:
4928 case GL_TEXTURE_SWIZZLE_A:
4929 case GL_TEXTURE_BASE_LEVEL:
4930 case GL_TEXTURE_MAX_LEVEL:
4931 case GL_TEXTURE_MIN_LOD:
4932 case GL_TEXTURE_MAX_LOD:
4933 case GL_TEXTURE_COMPARE_MODE:
4934 case GL_TEXTURE_COMPARE_FUNC:
4935 if (context->getClientMajorVersion() < 3)
4936 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004937 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004938 return false;
4939 }
4940 break;
4941
4942 case GL_TEXTURE_SRGB_DECODE_EXT:
4943 if (!context->getExtensions().textureSRGBDecode)
4944 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004945 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004946 return false;
4947 }
4948 break;
4949
4950 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004951 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004952 return false;
4953 }
4954
4955 if (length)
4956 {
4957 *length = 1;
4958 }
4959 return true;
4960}
4961
4962bool ValidateGetVertexAttribBase(Context *context,
4963 GLuint index,
4964 GLenum pname,
4965 GLsizei *length,
4966 bool pointer,
4967 bool pureIntegerEntryPoint)
4968{
4969 if (length)
4970 {
4971 *length = 0;
4972 }
4973
4974 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
4975 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004976 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004977 return false;
4978 }
4979
4980 if (index >= context->getCaps().maxVertexAttributes)
4981 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004982 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04004983 return false;
4984 }
4985
4986 if (pointer)
4987 {
4988 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
4989 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004990 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004991 return false;
4992 }
4993 }
4994 else
4995 {
4996 switch (pname)
4997 {
4998 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4999 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5000 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5001 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5002 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5003 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5004 case GL_CURRENT_VERTEX_ATTRIB:
5005 break;
5006
5007 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5008 static_assert(
5009 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5010 "ANGLE extension enums not equal to GL enums.");
5011 if (context->getClientMajorVersion() < 3 &&
5012 !context->getExtensions().instancedArrays)
5013 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005014 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5015 "requires OpenGL ES 3.0 or "
5016 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005017 return false;
5018 }
5019 break;
5020
5021 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5022 if (context->getClientMajorVersion() < 3)
5023 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005024 context->handleError(
5025 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005026 return false;
5027 }
5028 break;
5029
5030 case GL_VERTEX_ATTRIB_BINDING:
5031 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5032 if (context->getClientVersion() < ES_3_1)
5033 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005034 context->handleError(InvalidEnum()
5035 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005036 return false;
5037 }
5038 break;
5039
5040 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005041 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005042 return false;
5043 }
5044 }
5045
5046 if (length)
5047 {
5048 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5049 {
5050 *length = 4;
5051 }
5052 else
5053 {
5054 *length = 1;
5055 }
5056 }
5057
5058 return true;
5059}
5060
Jamie Madill4928b7c2017-06-20 12:57:39 -04005061bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005062 GLint x,
5063 GLint y,
5064 GLsizei width,
5065 GLsizei height,
5066 GLenum format,
5067 GLenum type,
5068 GLsizei bufSize,
5069 GLsizei *length,
5070 GLsizei *columns,
5071 GLsizei *rows,
5072 void *pixels)
5073{
5074 if (length != nullptr)
5075 {
5076 *length = 0;
5077 }
5078 if (rows != nullptr)
5079 {
5080 *rows = 0;
5081 }
5082 if (columns != nullptr)
5083 {
5084 *columns = 0;
5085 }
5086
5087 if (width < 0 || height < 0)
5088 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005089 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005090 return false;
5091 }
5092
5093 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5094
5095 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5096 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005097 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005098 return false;
5099 }
5100
5101 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5102 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005103 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005104 return false;
5105 }
5106
5107 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5108 ASSERT(framebuffer);
5109
5110 if (framebuffer->getReadBufferState() == GL_NONE)
5111 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005112 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005113 return false;
5114 }
5115
5116 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5117 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5118 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5119 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5120 // situation is an application error that would lead to a crash in ANGLE.
5121 if (readBuffer == nullptr)
5122 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005123 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005124 return false;
5125 }
5126
Martin Radev28031682017-07-28 14:47:56 +03005127 // ANGLE_multiview, Revision 1:
5128 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5129 // current read framebuffer is not NONE.
5130 if (readBuffer->getMultiviewLayout() != GL_NONE)
5131 {
5132 context->handleError(InvalidFramebufferOperation()
5133 << "Attempting to read from a multi-view framebuffer.");
5134 return false;
5135 }
5136
Geoff Lang280ba992017-04-18 16:30:58 -04005137 if (context->getExtensions().webglCompatibility)
5138 {
5139 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5140 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5141 // and type before validating the combination of format and type. However, the
5142 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5143 // verifies that GL_INVALID_OPERATION is generated.
5144 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5145 // dEQP/WebGL.
5146 if (!ValidReadPixelsFormatEnum(context, format))
5147 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005148 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005149 return false;
5150 }
5151
5152 if (!ValidReadPixelsTypeEnum(context, type))
5153 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005154 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005155 return false;
5156 }
5157 }
5158
Jamie Madill4928b7c2017-06-20 12:57:39 -04005159 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5160 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005161 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5162
5163 bool validFormatTypeCombination =
5164 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5165
5166 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5167 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005168 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005169 return false;
5170 }
5171
5172 // Check for pixel pack buffer related API errors
5173 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5174 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5175 {
5176 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005177 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005178 return false;
5179 }
5180
5181 // .. the data would be packed to the buffer object such that the memory writes required
5182 // would exceed the data store size.
5183 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5184 const gl::Extents size(width, height, 1);
5185 const auto &pack = context->getGLState().getPackState();
5186
5187 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5188 if (endByteOrErr.isError())
5189 {
5190 context->handleError(endByteOrErr.getError());
5191 return false;
5192 }
5193
5194 size_t endByte = endByteOrErr.getResult();
5195 if (bufSize >= 0)
5196 {
5197 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5198 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005199 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005200 return false;
5201 }
5202 }
5203
5204 if (pixelPackBuffer != nullptr)
5205 {
5206 CheckedNumeric<size_t> checkedEndByte(endByte);
5207 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5208 checkedEndByte += checkedOffset;
5209
5210 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5211 {
5212 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005213 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005214 return false;
5215 }
5216 }
5217
5218 if (pixelPackBuffer == nullptr && length != nullptr)
5219 {
5220 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5221 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005222 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005223 return false;
5224 }
5225
5226 *length = static_cast<GLsizei>(endByte);
5227 }
5228
5229 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5230 angle::CheckedNumeric<int> clippedExtent(length);
5231 if (start < 0)
5232 {
5233 // "subtract" the area that is less than 0
5234 clippedExtent += start;
5235 }
5236
5237 const int readExtent = start + length;
5238 if (readExtent > bufferSize)
5239 {
5240 // Subtract the region to the right of the read buffer
5241 clippedExtent -= (readExtent - bufferSize);
5242 }
5243
5244 if (!clippedExtent.IsValid())
5245 {
5246 return 0;
5247 }
5248
5249 return std::max(clippedExtent.ValueOrDie(), 0);
5250 };
5251
5252 if (columns != nullptr)
5253 {
5254 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5255 }
5256
5257 if (rows != nullptr)
5258 {
5259 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5260 }
5261
5262 return true;
5263}
5264
5265template <typename ParamType>
5266bool ValidateTexParameterBase(Context *context,
5267 GLenum target,
5268 GLenum pname,
5269 GLsizei bufSize,
5270 const ParamType *params)
5271{
5272 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5273 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005274 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005275 return false;
5276 }
5277
5278 if (context->getTargetTexture(target) == nullptr)
5279 {
5280 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005281 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005282 return false;
5283 }
5284
5285 const GLsizei minBufSize = 1;
5286 if (bufSize >= 0 && bufSize < minBufSize)
5287 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005288 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005289 return false;
5290 }
5291
5292 switch (pname)
5293 {
5294 case GL_TEXTURE_WRAP_R:
5295 case GL_TEXTURE_SWIZZLE_R:
5296 case GL_TEXTURE_SWIZZLE_G:
5297 case GL_TEXTURE_SWIZZLE_B:
5298 case GL_TEXTURE_SWIZZLE_A:
5299 case GL_TEXTURE_BASE_LEVEL:
5300 case GL_TEXTURE_MAX_LEVEL:
5301 case GL_TEXTURE_COMPARE_MODE:
5302 case GL_TEXTURE_COMPARE_FUNC:
5303 case GL_TEXTURE_MIN_LOD:
5304 case GL_TEXTURE_MAX_LOD:
5305 if (context->getClientMajorVersion() < 3)
5306 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005307 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005308 return false;
5309 }
5310 if (target == GL_TEXTURE_EXTERNAL_OES &&
5311 !context->getExtensions().eglImageExternalEssl3)
5312 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005313 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5314 "available without "
5315 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005316 return false;
5317 }
5318 break;
5319
5320 default:
5321 break;
5322 }
5323
JiangYizhou4cff8d62017-07-06 14:54:09 +08005324 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5325 {
5326 switch (pname)
5327 {
5328 case GL_TEXTURE_MIN_FILTER:
5329 case GL_TEXTURE_MAG_FILTER:
5330 case GL_TEXTURE_WRAP_S:
5331 case GL_TEXTURE_WRAP_T:
5332 case GL_TEXTURE_WRAP_R:
5333 case GL_TEXTURE_MIN_LOD:
5334 case GL_TEXTURE_MAX_LOD:
5335 case GL_TEXTURE_COMPARE_MODE:
5336 case GL_TEXTURE_COMPARE_FUNC:
5337 context->handleError(InvalidEnum()
5338 << "Invalid parameter for 2D multisampled textures.");
5339 return false;
5340 }
5341 }
5342
Jamie Madillbe849e42017-05-02 15:49:00 -04005343 switch (pname)
5344 {
5345 case GL_TEXTURE_WRAP_S:
5346 case GL_TEXTURE_WRAP_T:
5347 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005348 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005349 bool restrictedWrapModes =
5350 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5351 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5352 {
5353 return false;
5354 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005355 }
5356 break;
5357
5358 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005359 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005360 bool restrictedMinFilter =
5361 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5362 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5363 {
5364 return false;
5365 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005366 }
5367 break;
5368
5369 case GL_TEXTURE_MAG_FILTER:
5370 if (!ValidateTextureMagFilterValue(context, params))
5371 {
5372 return false;
5373 }
5374 break;
5375
5376 case GL_TEXTURE_USAGE_ANGLE:
5377 switch (ConvertToGLenum(params[0]))
5378 {
5379 case GL_NONE:
5380 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5381 break;
5382
5383 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005384 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005385 return false;
5386 }
5387 break;
5388
5389 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5390 if (!context->getExtensions().textureFilterAnisotropic)
5391 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005392 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005393 return false;
5394 }
5395
5396 // we assume the parameter passed to this validation method is truncated, not rounded
5397 if (params[0] < 1)
5398 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005399 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005400 return false;
5401 }
5402 break;
5403
5404 case GL_TEXTURE_MIN_LOD:
5405 case GL_TEXTURE_MAX_LOD:
5406 // any value is permissible
5407 break;
5408
5409 case GL_TEXTURE_COMPARE_MODE:
5410 if (!ValidateTextureCompareModeValue(context, params))
5411 {
5412 return false;
5413 }
5414 break;
5415
5416 case GL_TEXTURE_COMPARE_FUNC:
5417 if (!ValidateTextureCompareFuncValue(context, params))
5418 {
5419 return false;
5420 }
5421 break;
5422
5423 case GL_TEXTURE_SWIZZLE_R:
5424 case GL_TEXTURE_SWIZZLE_G:
5425 case GL_TEXTURE_SWIZZLE_B:
5426 case GL_TEXTURE_SWIZZLE_A:
5427 switch (ConvertToGLenum(params[0]))
5428 {
5429 case GL_RED:
5430 case GL_GREEN:
5431 case GL_BLUE:
5432 case GL_ALPHA:
5433 case GL_ZERO:
5434 case GL_ONE:
5435 break;
5436
5437 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005438 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005439 return false;
5440 }
5441 break;
5442
5443 case GL_TEXTURE_BASE_LEVEL:
5444 if (params[0] < 0)
5445 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005446 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005447 return false;
5448 }
5449 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5450 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005451 context->handleError(InvalidOperation()
5452 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005453 return false;
5454 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005455 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5456 {
5457 context->handleError(InvalidOperation()
5458 << "Base level must be 0 for multisampled textures.");
5459 return false;
5460 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005461 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5462 {
5463 context->handleError(InvalidOperation()
5464 << "Base level must be 0 for rectangle textures.");
5465 return false;
5466 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005467 break;
5468
5469 case GL_TEXTURE_MAX_LEVEL:
5470 if (params[0] < 0)
5471 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005472 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005473 return false;
5474 }
5475 break;
5476
5477 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5478 if (context->getClientVersion() < Version(3, 1))
5479 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005480 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005481 return false;
5482 }
5483 switch (ConvertToGLenum(params[0]))
5484 {
5485 case GL_DEPTH_COMPONENT:
5486 case GL_STENCIL_INDEX:
5487 break;
5488
5489 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005490 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005491 return false;
5492 }
5493 break;
5494
5495 case GL_TEXTURE_SRGB_DECODE_EXT:
5496 if (!ValidateTextureSRGBDecodeValue(context, params))
5497 {
5498 return false;
5499 }
5500 break;
5501
5502 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005503 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005504 return false;
5505 }
5506
5507 return true;
5508}
5509
5510template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5511template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5512
Jamie Madill12e957f2017-08-26 21:42:26 -04005513bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5514{
5515 if (index >= MAX_VERTEX_ATTRIBS)
5516 {
5517 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5518 return false;
5519 }
5520
5521 return true;
5522}
5523
5524bool ValidateGetActiveUniformBlockivBase(Context *context,
5525 GLuint program,
5526 GLuint uniformBlockIndex,
5527 GLenum pname,
5528 GLsizei *length)
5529{
5530 if (length)
5531 {
5532 *length = 0;
5533 }
5534
5535 if (context->getClientMajorVersion() < 3)
5536 {
5537 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5538 return false;
5539 }
5540
5541 Program *programObject = GetValidProgram(context, program);
5542 if (!programObject)
5543 {
5544 return false;
5545 }
5546
5547 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5548 {
5549 context->handleError(InvalidValue()
5550 << "uniformBlockIndex exceeds active uniform block count.");
5551 return false;
5552 }
5553
5554 switch (pname)
5555 {
5556 case GL_UNIFORM_BLOCK_BINDING:
5557 case GL_UNIFORM_BLOCK_DATA_SIZE:
5558 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5559 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5560 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5561 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5562 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5563 break;
5564
5565 default:
5566 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5567 return false;
5568 }
5569
5570 if (length)
5571 {
5572 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5573 {
5574 const UniformBlock &uniformBlock =
5575 programObject->getUniformBlockByIndex(uniformBlockIndex);
5576 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5577 }
5578 else
5579 {
5580 *length = 1;
5581 }
5582 }
5583
5584 return true;
5585}
5586
Jamie Madill9696d072017-08-26 23:19:57 -04005587template <typename ParamType>
5588bool ValidateSamplerParameterBase(Context *context,
5589 GLuint sampler,
5590 GLenum pname,
5591 GLsizei bufSize,
5592 ParamType *params)
5593{
5594 if (context->getClientMajorVersion() < 3)
5595 {
5596 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5597 return false;
5598 }
5599
5600 if (!context->isSampler(sampler))
5601 {
5602 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5603 return false;
5604 }
5605
5606 const GLsizei minBufSize = 1;
5607 if (bufSize >= 0 && bufSize < minBufSize)
5608 {
5609 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5610 return false;
5611 }
5612
5613 switch (pname)
5614 {
5615 case GL_TEXTURE_WRAP_S:
5616 case GL_TEXTURE_WRAP_T:
5617 case GL_TEXTURE_WRAP_R:
5618 if (!ValidateTextureWrapModeValue(context, params, false))
5619 {
5620 return false;
5621 }
5622 break;
5623
5624 case GL_TEXTURE_MIN_FILTER:
5625 if (!ValidateTextureMinFilterValue(context, params, false))
5626 {
5627 return false;
5628 }
5629 break;
5630
5631 case GL_TEXTURE_MAG_FILTER:
5632 if (!ValidateTextureMagFilterValue(context, params))
5633 {
5634 return false;
5635 }
5636 break;
5637
5638 case GL_TEXTURE_MIN_LOD:
5639 case GL_TEXTURE_MAX_LOD:
5640 // any value is permissible
5641 break;
5642
5643 case GL_TEXTURE_COMPARE_MODE:
5644 if (!ValidateTextureCompareModeValue(context, params))
5645 {
5646 return false;
5647 }
5648 break;
5649
5650 case GL_TEXTURE_COMPARE_FUNC:
5651 if (!ValidateTextureCompareFuncValue(context, params))
5652 {
5653 return false;
5654 }
5655 break;
5656
5657 case GL_TEXTURE_SRGB_DECODE_EXT:
5658 if (!ValidateTextureSRGBDecodeValue(context, params))
5659 {
5660 return false;
5661 }
5662 break;
5663
5664 default:
5665 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5666 return false;
5667 }
5668
5669 return true;
5670}
5671
5672template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5673template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5674
5675bool ValidateGetSamplerParameterBase(Context *context,
5676 GLuint sampler,
5677 GLenum pname,
5678 GLsizei *length)
5679{
5680 if (length)
5681 {
5682 *length = 0;
5683 }
5684
5685 if (context->getClientMajorVersion() < 3)
5686 {
5687 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5688 return false;
5689 }
5690
5691 if (!context->isSampler(sampler))
5692 {
5693 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5694 return false;
5695 }
5696
5697 switch (pname)
5698 {
5699 case GL_TEXTURE_WRAP_S:
5700 case GL_TEXTURE_WRAP_T:
5701 case GL_TEXTURE_WRAP_R:
5702 case GL_TEXTURE_MIN_FILTER:
5703 case GL_TEXTURE_MAG_FILTER:
5704 case GL_TEXTURE_MIN_LOD:
5705 case GL_TEXTURE_MAX_LOD:
5706 case GL_TEXTURE_COMPARE_MODE:
5707 case GL_TEXTURE_COMPARE_FUNC:
5708 break;
5709
5710 case GL_TEXTURE_SRGB_DECODE_EXT:
5711 if (!context->getExtensions().textureSRGBDecode)
5712 {
5713 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5714 return false;
5715 }
5716 break;
5717
5718 default:
5719 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5720 return false;
5721 }
5722
5723 if (length)
5724 {
5725 *length = 1;
5726 }
5727 return true;
5728}
5729
5730bool ValidateGetInternalFormativBase(Context *context,
5731 GLenum target,
5732 GLenum internalformat,
5733 GLenum pname,
5734 GLsizei bufSize,
5735 GLsizei *numParams)
5736{
5737 if (numParams)
5738 {
5739 *numParams = 0;
5740 }
5741
5742 if (context->getClientMajorVersion() < 3)
5743 {
5744 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
5745 return false;
5746 }
5747
5748 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5749 if (!formatCaps.renderable)
5750 {
5751 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5752 return false;
5753 }
5754
5755 switch (target)
5756 {
5757 case GL_RENDERBUFFER:
5758 break;
5759
5760 case GL_TEXTURE_2D_MULTISAMPLE:
5761 if (context->getClientVersion() < ES_3_1)
5762 {
5763 context->handleError(InvalidOperation()
5764 << "Texture target requires at least OpenGL ES 3.1.");
5765 return false;
5766 }
5767 break;
5768
5769 default:
5770 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5771 return false;
5772 }
5773
5774 if (bufSize < 0)
5775 {
5776 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5777 return false;
5778 }
5779
5780 GLsizei maxWriteParams = 0;
5781 switch (pname)
5782 {
5783 case GL_NUM_SAMPLE_COUNTS:
5784 maxWriteParams = 1;
5785 break;
5786
5787 case GL_SAMPLES:
5788 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5789 break;
5790
5791 default:
5792 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5793 return false;
5794 }
5795
5796 if (numParams)
5797 {
5798 // glGetInternalFormativ will not overflow bufSize
5799 *numParams = std::min(bufSize, maxWriteParams);
5800 }
5801
5802 return true;
5803}
5804
Jamie Madillc29968b2016-01-20 11:17:23 -05005805} // namespace gl