blob: d62a270ec0b8c7c1a3bc1f51e95108d43f110b72 [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 }
2873 }
2874 else if (!indices)
2875 {
2876 // This is an application error that would normally result in a crash,
2877 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002878 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04002879 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002880 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002881 }
2882
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002883 // Use the parameter buffer to retrieve and cache the index range.
2884 // TODO: offer fast path, with disabled index validation.
2885 // TODO: also disable index checking on back-ends that are robust to out-of-range accesses.
2886 const auto &params = context->getParams<HasIndexRange>();
2887 const auto &indexRangeOpt = params.getIndexRange();
2888 if (!indexRangeOpt.valid())
2889 {
2890 // Unexpected error.
2891 return false;
2892 }
2893
2894 // If we use an index greater than our maximum supported index range, return an error.
2895 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2896 // return an error if possible here.
2897 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2898 {
2899 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2900 return false;
2901 }
2902
2903 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2904 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
Jamie Madillfd716582014-06-06 17:09:04 -04002905 {
2906 return false;
2907 }
2908
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002909 // No op if there are no real indices in the index data (all are primitive restart).
2910 return (indexRangeOpt.value().vertexIndexCount > 0);
Jamie Madillfd716582014-06-06 17:09:04 -04002911}
2912
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002913bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2914 GLenum mode,
2915 GLsizei count,
2916 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002917 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002918 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002919{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002920 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002921}
2922
Geoff Lang3edfe032015-09-04 16:38:24 -04002923bool ValidateDrawElementsInstancedANGLE(Context *context,
2924 GLenum mode,
2925 GLsizei count,
2926 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002927 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002928 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002929{
Corentin Wallez170efbf2017-05-02 13:45:01 -04002930 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002931 {
2932 return false;
2933 }
2934
Corentin Wallez0dc97812017-06-22 14:38:44 -04002935 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002936}
2937
He Yunchaoced53ae2016-11-29 15:00:51 +08002938bool ValidateFramebufferTextureBase(Context *context,
2939 GLenum target,
2940 GLenum attachment,
2941 GLuint texture,
2942 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002943{
Jamie Madill55ec3b12014-07-03 10:38:57 -04002944 if (!ValidFramebufferTarget(target))
2945 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002946 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002947 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002948 }
2949
2950 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002951 {
2952 return false;
2953 }
2954
Jamie Madill55ec3b12014-07-03 10:38:57 -04002955 if (texture != 0)
2956 {
2957 gl::Texture *tex = context->getTexture(texture);
2958
Jamie Madillbe849e42017-05-02 15:49:00 -04002959 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002960 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002961 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002962 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002963 }
2964
2965 if (level < 0)
2966 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002967 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002968 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002969 }
2970 }
2971
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002972 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002973 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002974
Jamie Madill84115c92015-04-23 15:00:07 -04002975 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002976 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002977 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002978 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002979 }
2980
2981 return true;
2982}
2983
Geoff Langb1196682014-07-23 13:47:29 -04002984bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04002985{
2986 if (program == 0)
2987 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002988 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002989 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002990 }
2991
Dian Xiang769769a2015-09-09 15:20:08 -07002992 gl::Program *programObject = GetValidProgram(context, program);
2993 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05002994 {
2995 return false;
2996 }
2997
Jamie Madill0063c512014-08-25 15:47:53 -04002998 if (!programObject || !programObject->isLinked())
2999 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003000 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003001 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003002 }
3003
Geoff Lang7dd2e102014-11-10 15:19:26 -05003004 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003006 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003007 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003008 }
3009
Jamie Madill0063c512014-08-25 15:47:53 -04003010 return true;
3011}
3012
Geoff Langf41d0ee2016-10-07 13:04:23 -04003013static bool ValidateSizedGetUniform(Context *context,
3014 GLuint program,
3015 GLint location,
3016 GLsizei bufSize,
3017 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003018{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003019 if (length)
3020 {
3021 *length = 0;
3022 }
3023
Jamie Madill78f41802014-08-25 15:47:55 -04003024 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003025 {
Jamie Madill78f41802014-08-25 15:47:55 -04003026 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003027 }
3028
Geoff Langf41d0ee2016-10-07 13:04:23 -04003029 if (bufSize < 0)
3030 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003031 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003032 return false;
3033 }
3034
Jamie Madilla502c742014-08-28 17:19:13 -04003035 gl::Program *programObject = context->getProgram(program);
3036 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003037
Jamie Madill78f41802014-08-25 15:47:55 -04003038 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003039 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003040 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003041 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003042 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003043 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003044 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003045 }
3046
Geoff Langf41d0ee2016-10-07 13:04:23 -04003047 if (length)
3048 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003049 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003050 }
3051
Jamie Madill0063c512014-08-25 15:47:53 -04003052 return true;
3053}
3054
He Yunchaoced53ae2016-11-29 15:00:51 +08003055bool ValidateGetnUniformfvEXT(Context *context,
3056 GLuint program,
3057 GLint location,
3058 GLsizei bufSize,
3059 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003060{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003061 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003062}
3063
He Yunchaoced53ae2016-11-29 15:00:51 +08003064bool ValidateGetnUniformivEXT(Context *context,
3065 GLuint program,
3066 GLint location,
3067 GLsizei bufSize,
3068 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003069{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003070 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3071}
3072
3073bool ValidateGetUniformfvRobustANGLE(Context *context,
3074 GLuint program,
3075 GLint location,
3076 GLsizei bufSize,
3077 GLsizei *length,
3078 GLfloat *params)
3079{
3080 if (!ValidateRobustEntryPoint(context, bufSize))
3081 {
3082 return false;
3083 }
3084
3085 // bufSize is validated in ValidateSizedGetUniform
3086 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3087}
3088
3089bool ValidateGetUniformivRobustANGLE(Context *context,
3090 GLuint program,
3091 GLint location,
3092 GLsizei bufSize,
3093 GLsizei *length,
3094 GLint *params)
3095{
3096 if (!ValidateRobustEntryPoint(context, bufSize))
3097 {
3098 return false;
3099 }
3100
3101 // bufSize is validated in ValidateSizedGetUniform
3102 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3103}
3104
3105bool ValidateGetUniformuivRobustANGLE(Context *context,
3106 GLuint program,
3107 GLint location,
3108 GLsizei bufSize,
3109 GLsizei *length,
3110 GLuint *params)
3111{
3112 if (!ValidateRobustEntryPoint(context, bufSize))
3113 {
3114 return false;
3115 }
3116
3117 if (context->getClientMajorVersion() < 3)
3118 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003119 context->handleError(InvalidOperation() << "Entry point requires at least OpenGL ES 3.0.");
Geoff Langf41d0ee2016-10-07 13:04:23 -04003120 return false;
3121 }
3122
3123 // bufSize is validated in ValidateSizedGetUniform
3124 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003125}
3126
He Yunchaoced53ae2016-11-29 15:00:51 +08003127bool ValidateDiscardFramebufferBase(Context *context,
3128 GLenum target,
3129 GLsizei numAttachments,
3130 const GLenum *attachments,
3131 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003132{
3133 if (numAttachments < 0)
3134 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003135 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003136 return false;
3137 }
3138
3139 for (GLsizei i = 0; i < numAttachments; ++i)
3140 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003141 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003142 {
3143 if (defaultFramebuffer)
3144 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003145 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003146 return false;
3147 }
3148
3149 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3150 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003151 context->handleError(InvalidOperation() << "Requested color attachment is "
3152 "greater than the maximum supported "
3153 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003154 return false;
3155 }
3156 }
3157 else
3158 {
3159 switch (attachments[i])
3160 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003161 case GL_DEPTH_ATTACHMENT:
3162 case GL_STENCIL_ATTACHMENT:
3163 case GL_DEPTH_STENCIL_ATTACHMENT:
3164 if (defaultFramebuffer)
3165 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003166 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3167 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003168 return false;
3169 }
3170 break;
3171 case GL_COLOR:
3172 case GL_DEPTH:
3173 case GL_STENCIL:
3174 if (!defaultFramebuffer)
3175 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003176 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3177 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003178 return false;
3179 }
3180 break;
3181 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003182 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003183 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003184 }
3185 }
3186 }
3187
3188 return true;
3189}
3190
Austin Kinross6ee1e782015-05-29 17:05:37 -07003191bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3192{
3193 // Note that debug marker calls must not set error state
3194
3195 if (length < 0)
3196 {
3197 return false;
3198 }
3199
3200 if (marker == nullptr)
3201 {
3202 return false;
3203 }
3204
3205 return true;
3206}
3207
3208bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3209{
3210 // Note that debug marker calls must not set error state
3211
3212 if (length < 0)
3213 {
3214 return false;
3215 }
3216
3217 if (length > 0 && marker == nullptr)
3218 {
3219 return false;
3220 }
3221
3222 return true;
3223}
3224
Geoff Langdcab33b2015-07-21 13:03:16 -04003225bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003226 GLenum target,
3227 egl::Image *image)
3228{
Geoff Langa8406172015-07-21 16:53:39 -04003229 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3230 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003231 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003232 return false;
3233 }
3234
3235 switch (target)
3236 {
3237 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003238 if (!context->getExtensions().eglImage)
3239 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003240 context->handleError(InvalidEnum()
3241 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003242 }
3243 break;
3244
3245 case GL_TEXTURE_EXTERNAL_OES:
3246 if (!context->getExtensions().eglImageExternal)
3247 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003248 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3249 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003250 }
Geoff Langa8406172015-07-21 16:53:39 -04003251 break;
3252
3253 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003254 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003255 return false;
3256 }
3257
Jamie Madill61e16b42017-06-19 11:13:23 -04003258 ASSERT(context->getCurrentDisplay());
3259 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003260 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003261 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003262 return false;
3263 }
3264
3265 if (image->getSamples() > 0)
3266 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003267 context->handleError(InvalidOperation()
3268 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003269 return false;
3270 }
3271
Geoff Langca271392017-04-05 12:30:00 -04003272 const TextureCaps &textureCaps =
3273 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003274 if (!textureCaps.texturable)
3275 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003276 context->handleError(InvalidOperation()
3277 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003278 return false;
3279 }
3280
Geoff Langdcab33b2015-07-21 13:03:16 -04003281 return true;
3282}
3283
3284bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003285 GLenum target,
3286 egl::Image *image)
3287{
Geoff Langa8406172015-07-21 16:53:39 -04003288 if (!context->getExtensions().eglImage)
3289 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003290 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003291 return false;
3292 }
3293
3294 switch (target)
3295 {
3296 case GL_RENDERBUFFER:
3297 break;
3298
3299 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003300 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003301 return false;
3302 }
3303
Jamie Madill61e16b42017-06-19 11:13:23 -04003304 ASSERT(context->getCurrentDisplay());
3305 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003306 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003307 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003308 return false;
3309 }
3310
Geoff Langca271392017-04-05 12:30:00 -04003311 const TextureCaps &textureCaps =
3312 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003313 if (!textureCaps.renderable)
3314 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003315 context->handleError(InvalidOperation()
3316 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003317 return false;
3318 }
3319
Geoff Langdcab33b2015-07-21 13:03:16 -04003320 return true;
3321}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003322
3323bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3324{
Geoff Lang36167ab2015-12-07 10:27:14 -05003325 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003326 {
3327 // The default VAO should always exist
3328 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003329 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003330 return false;
3331 }
3332
3333 return true;
3334}
3335
Geoff Langc5629752015-12-07 16:29:04 -05003336bool ValidateProgramBinaryBase(Context *context,
3337 GLuint program,
3338 GLenum binaryFormat,
3339 const void *binary,
3340 GLint length)
3341{
3342 Program *programObject = GetValidProgram(context, program);
3343 if (programObject == nullptr)
3344 {
3345 return false;
3346 }
3347
3348 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3349 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3350 programBinaryFormats.end())
3351 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003352 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003353 return false;
3354 }
3355
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003356 if (context->hasActiveTransformFeedback(program))
3357 {
3358 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003359 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3360 "is associated with an active transform "
3361 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003362 return false;
3363 }
3364
Geoff Langc5629752015-12-07 16:29:04 -05003365 return true;
3366}
3367
3368bool ValidateGetProgramBinaryBase(Context *context,
3369 GLuint program,
3370 GLsizei bufSize,
3371 GLsizei *length,
3372 GLenum *binaryFormat,
3373 void *binary)
3374{
3375 Program *programObject = GetValidProgram(context, program);
3376 if (programObject == nullptr)
3377 {
3378 return false;
3379 }
3380
3381 if (!programObject->isLinked())
3382 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003383 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003384 return false;
3385 }
3386
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003387 if (context->getCaps().programBinaryFormats.empty())
3388 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003389 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003390 return false;
3391 }
3392
Geoff Langc5629752015-12-07 16:29:04 -05003393 return true;
3394}
Jamie Madillc29968b2016-01-20 11:17:23 -05003395
Jamie Madillc29968b2016-01-20 11:17:23 -05003396bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3397{
3398 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003399 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003400 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003401 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3402 return false;
3403 }
3404 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3405 {
3406 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003407 return false;
3408 }
3409
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003410 ASSERT(context->getGLState().getDrawFramebuffer());
3411 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003412 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3413
3414 // This should come first before the check for the default frame buffer
3415 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3416 // rather than INVALID_OPERATION
3417 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3418 {
3419 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3420
3421 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003422 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3423 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003424 {
3425 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003426 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3427 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3428 // 3.1 is still a bit ambiguous about the error, but future specs are
3429 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003430 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003431 return false;
3432 }
3433 else if (bufs[colorAttachment] >= maxColorAttachment)
3434 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003435 context->handleError(InvalidOperation()
3436 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003437 return false;
3438 }
3439 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3440 frameBufferId != 0)
3441 {
3442 // INVALID_OPERATION-GL is bound to buffer and ith argument
3443 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003444 context->handleError(InvalidOperation()
3445 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003446 return false;
3447 }
3448 }
3449
3450 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3451 // and n is not 1 or bufs is bound to value other than BACK and NONE
3452 if (frameBufferId == 0)
3453 {
3454 if (n != 1)
3455 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003456 context->handleError(InvalidOperation()
3457 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003458 return false;
3459 }
3460
3461 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003463 context->handleError(
3464 InvalidOperation()
3465 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003466 return false;
3467 }
3468 }
3469
3470 return true;
3471}
3472
Geoff Lang496c02d2016-10-20 11:38:11 -07003473bool ValidateGetBufferPointervBase(Context *context,
3474 GLenum target,
3475 GLenum pname,
3476 GLsizei *length,
3477 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003478{
Geoff Lang496c02d2016-10-20 11:38:11 -07003479 if (length)
3480 {
3481 *length = 0;
3482 }
3483
3484 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3485 {
3486 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003487 InvalidOperation()
3488 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003489 return false;
3490 }
3491
Olli Etuaho4f667482016-03-30 15:56:35 +03003492 if (!ValidBufferTarget(context, target))
3493 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003494 context->handleError(InvalidEnum() << "Buffer target not valid: 0x" << std::hex
3495 << std::uppercase << target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003496 return false;
3497 }
3498
Geoff Lang496c02d2016-10-20 11:38:11 -07003499 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003500 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003501 case GL_BUFFER_MAP_POINTER:
3502 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003503
Geoff Lang496c02d2016-10-20 11:38:11 -07003504 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003505 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003506 return false;
3507 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003508
3509 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3510 // target bound to zero generate an INVALID_OPERATION error."
3511 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003512 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003513 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003514 context->handleError(InvalidOperation()
3515 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003516 return false;
3517 }
3518
Geoff Lang496c02d2016-10-20 11:38:11 -07003519 if (length)
3520 {
3521 *length = 1;
3522 }
3523
Olli Etuaho4f667482016-03-30 15:56:35 +03003524 return true;
3525}
3526
3527bool ValidateUnmapBufferBase(Context *context, GLenum target)
3528{
3529 if (!ValidBufferTarget(context, target))
3530 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003531 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003532 return false;
3533 }
3534
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003535 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003536
3537 if (buffer == nullptr || !buffer->isMapped())
3538 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003539 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003540 return false;
3541 }
3542
3543 return true;
3544}
3545
3546bool ValidateMapBufferRangeBase(Context *context,
3547 GLenum target,
3548 GLintptr offset,
3549 GLsizeiptr length,
3550 GLbitfield access)
3551{
3552 if (!ValidBufferTarget(context, target))
3553 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003554 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003555 return false;
3556 }
3557
Brandon Jones6cad5662017-06-14 13:25:13 -07003558 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003559 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003560 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3561 return false;
3562 }
3563
3564 if (length < 0)
3565 {
3566 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003567 return false;
3568 }
3569
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003570 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003571
3572 if (!buffer)
3573 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003574 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003575 return false;
3576 }
3577
3578 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003579 CheckedNumeric<size_t> checkedOffset(offset);
3580 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003581
Jamie Madille2e406c2016-06-02 13:04:10 -04003582 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003583 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003584 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003585 return false;
3586 }
3587
3588 // Check for invalid bits in the mask
3589 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3590 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3591 GL_MAP_UNSYNCHRONIZED_BIT;
3592
3593 if (access & ~(allAccessBits))
3594 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003595 context->handleError(InvalidValue()
3596 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003597 return false;
3598 }
3599
3600 if (length == 0)
3601 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003602 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003603 return false;
3604 }
3605
3606 if (buffer->isMapped())
3607 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003608 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003609 return false;
3610 }
3611
3612 // Check for invalid bit combinations
3613 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3614 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003615 context->handleError(InvalidOperation()
3616 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003617 return false;
3618 }
3619
3620 GLbitfield writeOnlyBits =
3621 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3622
3623 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003625 context->handleError(InvalidOperation()
3626 << "Invalid access bits when mapping buffer for reading: 0x"
3627 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003628 return false;
3629 }
3630
3631 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3632 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003633 context->handleError(
3634 InvalidOperation()
3635 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003636 return false;
3637 }
Geoff Lang79f71042017-08-14 16:43:43 -04003638
3639 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003640}
3641
3642bool ValidateFlushMappedBufferRangeBase(Context *context,
3643 GLenum target,
3644 GLintptr offset,
3645 GLsizeiptr length)
3646{
Brandon Jones6cad5662017-06-14 13:25:13 -07003647 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003648 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003649 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3650 return false;
3651 }
3652
3653 if (length < 0)
3654 {
3655 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003656 return false;
3657 }
3658
3659 if (!ValidBufferTarget(context, target))
3660 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003661 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003662 return false;
3663 }
3664
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003665 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003666
3667 if (buffer == nullptr)
3668 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003669 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003670 return false;
3671 }
3672
3673 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3674 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003675 context->handleError(InvalidOperation()
3676 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003677 return false;
3678 }
3679
3680 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003681 CheckedNumeric<size_t> checkedOffset(offset);
3682 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003683
Jamie Madille2e406c2016-06-02 13:04:10 -04003684 if (!checkedSize.IsValid() ||
3685 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003686 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003687 context->handleError(InvalidValue()
3688 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003689 return false;
3690 }
3691
3692 return true;
3693}
3694
Olli Etuaho41997e72016-03-10 13:38:39 +02003695bool ValidateGenOrDelete(Context *context, GLint n)
3696{
3697 if (n < 0)
3698 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003699 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003700 return false;
3701 }
3702 return true;
3703}
3704
Geoff Langff5b2d52016-09-07 11:32:23 -04003705bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3706{
3707 if (!context->getExtensions().robustClientMemory)
3708 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003709 context->handleError(InvalidOperation()
3710 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003711 return false;
3712 }
3713
3714 if (bufSize < 0)
3715 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003716 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003717 return false;
3718 }
3719
3720 return true;
3721}
3722
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003723bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3724{
3725 if (bufSize < numParams)
3726 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003727 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3728 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003729 return false;
3730 }
3731
3732 return true;
3733}
3734
Jamie Madillbe849e42017-05-02 15:49:00 -04003735bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3736 GLenum target,
3737 GLenum attachment,
3738 GLenum pname,
3739 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003740{
Geoff Langff5b2d52016-09-07 11:32:23 -04003741 if (!ValidFramebufferTarget(target))
3742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003743 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003744 return false;
3745 }
3746
3747 int clientVersion = context->getClientMajorVersion();
3748
3749 switch (pname)
3750 {
3751 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3752 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3753 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3754 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3755 break;
3756
Martin Radeve5285d22017-07-14 16:23:53 +03003757 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3758 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3759 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3760 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3761 if (clientVersion < 3 || !context->getExtensions().multiview)
3762 {
3763 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3764 return false;
3765 }
3766 break;
3767
Geoff Langff5b2d52016-09-07 11:32:23 -04003768 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3769 if (clientVersion < 3 && !context->getExtensions().sRGB)
3770 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003771 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003772 return false;
3773 }
3774 break;
3775
3776 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3777 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3778 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3779 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3780 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3781 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3782 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3783 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3784 if (clientVersion < 3)
3785 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003786 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003787 return false;
3788 }
3789 break;
3790
3791 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003792 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003793 return false;
3794 }
3795
3796 // Determine if the attachment is a valid enum
3797 switch (attachment)
3798 {
3799 case GL_BACK:
3800 case GL_FRONT:
3801 case GL_DEPTH:
3802 case GL_STENCIL:
3803 case GL_DEPTH_STENCIL_ATTACHMENT:
3804 if (clientVersion < 3)
3805 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003806 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003807 return false;
3808 }
3809 break;
3810
3811 case GL_DEPTH_ATTACHMENT:
3812 case GL_STENCIL_ATTACHMENT:
3813 break;
3814
3815 default:
3816 if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
3817 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3818 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003819 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003820 return false;
3821 }
3822 break;
3823 }
3824
3825 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3826 ASSERT(framebuffer);
3827
3828 if (framebuffer->id() == 0)
3829 {
3830 if (clientVersion < 3)
3831 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003832 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003833 return false;
3834 }
3835
3836 switch (attachment)
3837 {
3838 case GL_BACK:
3839 case GL_DEPTH:
3840 case GL_STENCIL:
3841 break;
3842
3843 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003844 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003845 return false;
3846 }
3847 }
3848 else
3849 {
3850 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3851 {
3852 // Valid attachment query
3853 }
3854 else
3855 {
3856 switch (attachment)
3857 {
3858 case GL_DEPTH_ATTACHMENT:
3859 case GL_STENCIL_ATTACHMENT:
3860 break;
3861
3862 case GL_DEPTH_STENCIL_ATTACHMENT:
3863 if (!framebuffer->hasValidDepthStencil())
3864 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003865 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003866 return false;
3867 }
3868 break;
3869
3870 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003871 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003872 return false;
3873 }
3874 }
3875 }
3876
3877 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3878 if (attachmentObject)
3879 {
3880 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3881 attachmentObject->type() == GL_TEXTURE ||
3882 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3883
3884 switch (pname)
3885 {
3886 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3887 if (attachmentObject->type() != GL_RENDERBUFFER &&
3888 attachmentObject->type() != GL_TEXTURE)
3889 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003890 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003891 return false;
3892 }
3893 break;
3894
3895 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3896 if (attachmentObject->type() != GL_TEXTURE)
3897 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003898 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003899 return false;
3900 }
3901 break;
3902
3903 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3904 if (attachmentObject->type() != GL_TEXTURE)
3905 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003906 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003907 return false;
3908 }
3909 break;
3910
3911 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3912 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3913 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003914 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003915 return false;
3916 }
3917 break;
3918
3919 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3920 if (attachmentObject->type() != GL_TEXTURE)
3921 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003922 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003923 return false;
3924 }
3925 break;
3926
3927 default:
3928 break;
3929 }
3930 }
3931 else
3932 {
3933 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3934 // is NONE, then querying any other pname will generate INVALID_ENUM.
3935
3936 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3937 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3938 // INVALID_OPERATION for all other pnames
3939
3940 switch (pname)
3941 {
3942 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3943 break;
3944
3945 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3946 if (clientVersion < 3)
3947 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003948 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07003949 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003950 return false;
3951 }
3952 break;
3953
3954 default:
3955 if (clientVersion < 3)
3956 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003957 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07003958 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003959 return false;
3960 }
3961 else
3962 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003963 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Brandon Jonesafa75152017-07-21 13:11:29 -07003964 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003965 return false;
3966 }
3967 }
3968 }
3969
Martin Radeve5285d22017-07-14 16:23:53 +03003970 if (numParams)
3971 {
3972 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
3973 {
3974 // Only when the viewport offsets are queried we can have a varying number of output
3975 // parameters.
3976 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
3977 *numParams = numViews * 2;
3978 }
3979 else
3980 {
3981 // For all other queries we can have only one output parameter.
3982 *numParams = 1;
3983 }
3984 }
3985
Geoff Langff5b2d52016-09-07 11:32:23 -04003986 return true;
3987}
3988
3989bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
3990 GLenum target,
3991 GLenum attachment,
3992 GLenum pname,
3993 GLsizei bufSize,
3994 GLsizei *numParams)
3995{
3996 if (!ValidateRobustEntryPoint(context, bufSize))
3997 {
3998 return false;
3999 }
4000
Jamie Madillbe849e42017-05-02 15:49:00 -04004001 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4002 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004003 {
4004 return false;
4005 }
4006
4007 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4008 {
4009 return false;
4010 }
4011
4012 return true;
4013}
4014
Geoff Langff5b2d52016-09-07 11:32:23 -04004015bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
4016 GLenum target,
4017 GLenum pname,
4018 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004019 GLsizei *length,
4020 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004021{
4022 if (!ValidateRobustEntryPoint(context, bufSize))
4023 {
4024 return false;
4025 }
4026
Geoff Langebebe1c2016-10-14 12:01:31 -04004027 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004028 {
4029 return false;
4030 }
4031
Geoff Langebebe1c2016-10-14 12:01:31 -04004032 if (!ValidateRobustBufferSize(context, bufSize, *length))
4033 {
4034 return false;
4035 }
4036
4037 return true;
4038}
4039
Geoff Langebebe1c2016-10-14 12:01:31 -04004040bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
4041 GLenum target,
4042 GLenum pname,
4043 GLsizei bufSize,
4044 GLsizei *length,
4045 GLint64 *params)
4046{
4047 if (!ValidateRobustEntryPoint(context, bufSize))
4048 {
4049 return false;
4050 }
4051
4052 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4053 {
4054 return false;
4055 }
4056
4057 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004058 {
4059 return false;
4060 }
4061
4062 return true;
4063}
4064
Jamie Madillbe849e42017-05-02 15:49:00 -04004065bool ValidateGetProgramivBase(ValidationContext *context,
4066 GLuint program,
4067 GLenum pname,
4068 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004069{
4070 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004071 if (numParams)
4072 {
4073 *numParams = 1;
4074 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004075
4076 Program *programObject = GetValidProgram(context, program);
4077 if (!programObject)
4078 {
4079 return false;
4080 }
4081
4082 switch (pname)
4083 {
4084 case GL_DELETE_STATUS:
4085 case GL_LINK_STATUS:
4086 case GL_VALIDATE_STATUS:
4087 case GL_INFO_LOG_LENGTH:
4088 case GL_ATTACHED_SHADERS:
4089 case GL_ACTIVE_ATTRIBUTES:
4090 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4091 case GL_ACTIVE_UNIFORMS:
4092 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4093 break;
4094
4095 case GL_PROGRAM_BINARY_LENGTH:
4096 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4097 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004098 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4099 "requires GL_OES_get_program_binary or "
4100 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004101 return false;
4102 }
4103 break;
4104
4105 case GL_ACTIVE_UNIFORM_BLOCKS:
4106 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4107 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4108 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4109 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4110 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4111 if (context->getClientMajorVersion() < 3)
4112 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004113 context->handleError(InvalidEnum() << "Querying requires at least ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004114 return false;
4115 }
4116 break;
4117
Yunchao He61afff12017-03-14 15:34:03 +08004118 case GL_PROGRAM_SEPARABLE:
4119 if (context->getClientVersion() < Version(3, 1))
4120 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004121 context->handleError(InvalidEnum() << "Querying requires at least ES 3.1.");
Yunchao He61afff12017-03-14 15:34:03 +08004122 return false;
4123 }
4124 break;
4125
Geoff Langff5b2d52016-09-07 11:32:23 -04004126 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004127 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004128 return false;
4129 }
4130
4131 return true;
4132}
4133
4134bool ValidateGetProgramivRobustANGLE(Context *context,
4135 GLuint program,
4136 GLenum pname,
4137 GLsizei bufSize,
4138 GLsizei *numParams)
4139{
4140 if (!ValidateRobustEntryPoint(context, bufSize))
4141 {
4142 return false;
4143 }
4144
Jamie Madillbe849e42017-05-02 15:49:00 -04004145 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004146 {
4147 return false;
4148 }
4149
4150 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4151 {
4152 return false;
4153 }
4154
4155 return true;
4156}
4157
Geoff Lang740d9022016-10-07 11:20:52 -04004158bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4159 GLenum target,
4160 GLenum pname,
4161 GLsizei bufSize,
4162 GLsizei *length,
4163 GLint *params)
4164{
4165 if (!ValidateRobustEntryPoint(context, bufSize))
4166 {
4167 return false;
4168 }
4169
4170 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4171 {
4172 return false;
4173 }
4174
4175 if (!ValidateRobustBufferSize(context, bufSize, *length))
4176 {
4177 return false;
4178 }
4179
4180 return true;
4181}
4182
Geoff Langd7d0ed32016-10-07 11:33:51 -04004183bool ValidateGetShaderivRobustANGLE(Context *context,
4184 GLuint shader,
4185 GLenum pname,
4186 GLsizei bufSize,
4187 GLsizei *length,
4188 GLint *params)
4189{
4190 if (!ValidateRobustEntryPoint(context, bufSize))
4191 {
4192 return false;
4193 }
4194
4195 if (!ValidateGetShaderivBase(context, shader, pname, length))
4196 {
4197 return false;
4198 }
4199
4200 if (!ValidateRobustBufferSize(context, bufSize, *length))
4201 {
4202 return false;
4203 }
4204
4205 return true;
4206}
4207
Geoff Langc1984ed2016-10-07 12:41:00 -04004208bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4209 GLenum target,
4210 GLenum pname,
4211 GLsizei bufSize,
4212 GLsizei *length,
4213 GLfloat *params)
4214{
4215 if (!ValidateRobustEntryPoint(context, bufSize))
4216 {
4217 return false;
4218 }
4219
4220 if (!ValidateGetTexParameterBase(context, target, pname, length))
4221 {
4222 return false;
4223 }
4224
4225 if (!ValidateRobustBufferSize(context, bufSize, *length))
4226 {
4227 return false;
4228 }
4229
4230 return true;
4231}
4232
Geoff Langc1984ed2016-10-07 12:41:00 -04004233bool ValidateGetTexParameterivRobustANGLE(Context *context,
4234 GLenum target,
4235 GLenum pname,
4236 GLsizei bufSize,
4237 GLsizei *length,
4238 GLint *params)
4239{
4240 if (!ValidateRobustEntryPoint(context, bufSize))
4241 {
4242 return false;
4243 }
4244
4245 if (!ValidateGetTexParameterBase(context, target, pname, length))
4246 {
4247 return false;
4248 }
4249
4250 if (!ValidateRobustBufferSize(context, bufSize, *length))
4251 {
4252 return false;
4253 }
4254
4255 return true;
4256}
4257
Geoff Langc1984ed2016-10-07 12:41:00 -04004258bool ValidateTexParameterfvRobustANGLE(Context *context,
4259 GLenum target,
4260 GLenum pname,
4261 GLsizei bufSize,
4262 const GLfloat *params)
4263{
4264 if (!ValidateRobustEntryPoint(context, bufSize))
4265 {
4266 return false;
4267 }
4268
4269 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4270}
4271
Geoff Langc1984ed2016-10-07 12:41:00 -04004272bool ValidateTexParameterivRobustANGLE(Context *context,
4273 GLenum target,
4274 GLenum pname,
4275 GLsizei bufSize,
4276 const GLint *params)
4277{
4278 if (!ValidateRobustEntryPoint(context, bufSize))
4279 {
4280 return false;
4281 }
4282
4283 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4284}
4285
Geoff Langc1984ed2016-10-07 12:41:00 -04004286bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4287 GLuint sampler,
4288 GLenum pname,
4289 GLuint bufSize,
4290 GLsizei *length,
4291 GLfloat *params)
4292{
4293 if (!ValidateRobustEntryPoint(context, bufSize))
4294 {
4295 return false;
4296 }
4297
4298 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4299 {
4300 return false;
4301 }
4302
4303 if (!ValidateRobustBufferSize(context, bufSize, *length))
4304 {
4305 return false;
4306 }
4307
4308 return true;
4309}
4310
Geoff Langc1984ed2016-10-07 12:41:00 -04004311bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4312 GLuint sampler,
4313 GLenum pname,
4314 GLuint bufSize,
4315 GLsizei *length,
4316 GLint *params)
4317{
4318 if (!ValidateRobustEntryPoint(context, bufSize))
4319 {
4320 return false;
4321 }
4322
4323 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4324 {
4325 return false;
4326 }
4327
4328 if (!ValidateRobustBufferSize(context, bufSize, *length))
4329 {
4330 return false;
4331 }
4332
4333 return true;
4334}
4335
Geoff Langc1984ed2016-10-07 12:41:00 -04004336bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4337 GLuint sampler,
4338 GLenum pname,
4339 GLsizei bufSize,
4340 const GLfloat *params)
4341{
4342 if (!ValidateRobustEntryPoint(context, bufSize))
4343 {
4344 return false;
4345 }
4346
4347 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4348}
4349
Geoff Langc1984ed2016-10-07 12:41:00 -04004350bool ValidateSamplerParameterivRobustANGLE(Context *context,
4351 GLuint sampler,
4352 GLenum pname,
4353 GLsizei bufSize,
4354 const GLint *params)
4355{
4356 if (!ValidateRobustEntryPoint(context, bufSize))
4357 {
4358 return false;
4359 }
4360
4361 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4362}
4363
Geoff Lang0b031062016-10-13 14:30:04 -04004364bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4365 GLuint index,
4366 GLenum pname,
4367 GLsizei bufSize,
4368 GLsizei *length,
4369 GLfloat *params)
4370{
4371 if (!ValidateRobustEntryPoint(context, bufSize))
4372 {
4373 return false;
4374 }
4375
4376 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4377 {
4378 return false;
4379 }
4380
4381 if (!ValidateRobustBufferSize(context, bufSize, *length))
4382 {
4383 return false;
4384 }
4385
4386 return true;
4387}
4388
Geoff Lang0b031062016-10-13 14:30:04 -04004389bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4390 GLuint index,
4391 GLenum pname,
4392 GLsizei bufSize,
4393 GLsizei *length,
4394 GLint *params)
4395{
4396 if (!ValidateRobustEntryPoint(context, bufSize))
4397 {
4398 return false;
4399 }
4400
4401 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4402 {
4403 return false;
4404 }
4405
4406 if (!ValidateRobustBufferSize(context, bufSize, *length))
4407 {
4408 return false;
4409 }
4410
4411 return true;
4412}
4413
Geoff Lang0b031062016-10-13 14:30:04 -04004414bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4415 GLuint index,
4416 GLenum pname,
4417 GLsizei bufSize,
4418 GLsizei *length,
4419 void **pointer)
4420{
4421 if (!ValidateRobustEntryPoint(context, bufSize))
4422 {
4423 return false;
4424 }
4425
4426 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4427 {
4428 return false;
4429 }
4430
4431 if (!ValidateRobustBufferSize(context, bufSize, *length))
4432 {
4433 return false;
4434 }
4435
4436 return true;
4437}
4438
Geoff Lang0b031062016-10-13 14:30:04 -04004439bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4440 GLuint index,
4441 GLenum pname,
4442 GLsizei bufSize,
4443 GLsizei *length,
4444 GLint *params)
4445{
4446 if (!ValidateRobustEntryPoint(context, bufSize))
4447 {
4448 return false;
4449 }
4450
4451 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4452 {
4453 return false;
4454 }
4455
4456 if (!ValidateRobustBufferSize(context, bufSize, *length))
4457 {
4458 return false;
4459 }
4460
4461 return true;
4462}
4463
Geoff Lang0b031062016-10-13 14:30:04 -04004464bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4465 GLuint index,
4466 GLenum pname,
4467 GLsizei bufSize,
4468 GLsizei *length,
4469 GLuint *params)
4470{
4471 if (!ValidateRobustEntryPoint(context, bufSize))
4472 {
4473 return false;
4474 }
4475
4476 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4477 {
4478 return false;
4479 }
4480
4481 if (!ValidateRobustBufferSize(context, bufSize, *length))
4482 {
4483 return false;
4484 }
4485
4486 return true;
4487}
4488
Geoff Lang6899b872016-10-14 11:30:13 -04004489bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4490 GLuint program,
4491 GLuint uniformBlockIndex,
4492 GLenum pname,
4493 GLsizei bufSize,
4494 GLsizei *length,
4495 GLint *params)
4496{
4497 if (!ValidateRobustEntryPoint(context, bufSize))
4498 {
4499 return false;
4500 }
4501
4502 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4503 {
4504 return false;
4505 }
4506
4507 if (!ValidateRobustBufferSize(context, bufSize, *length))
4508 {
4509 return false;
4510 }
4511
4512 return true;
4513}
4514
Geoff Lang0a9661f2016-10-20 10:59:20 -07004515bool ValidateGetInternalFormativRobustANGLE(Context *context,
4516 GLenum target,
4517 GLenum internalformat,
4518 GLenum pname,
4519 GLsizei bufSize,
4520 GLsizei *length,
4521 GLint *params)
4522{
4523 if (!ValidateRobustEntryPoint(context, bufSize))
4524 {
4525 return false;
4526 }
4527
4528 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4529 {
4530 return false;
4531 }
4532
4533 if (!ValidateRobustBufferSize(context, bufSize, *length))
4534 {
4535 return false;
4536 }
4537
4538 return true;
4539}
4540
Shao80957d92017-02-20 21:25:59 +08004541bool ValidateVertexFormatBase(ValidationContext *context,
4542 GLuint attribIndex,
4543 GLint size,
4544 GLenum type,
4545 GLboolean pureInteger)
4546{
4547 const Caps &caps = context->getCaps();
4548 if (attribIndex >= caps.maxVertexAttributes)
4549 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004550 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004551 return false;
4552 }
4553
4554 if (size < 1 || size > 4)
4555 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004556 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004557 return false;
Shao80957d92017-02-20 21:25:59 +08004558 }
4559
4560 switch (type)
4561 {
4562 case GL_BYTE:
4563 case GL_UNSIGNED_BYTE:
4564 case GL_SHORT:
4565 case GL_UNSIGNED_SHORT:
4566 break;
4567
4568 case GL_INT:
4569 case GL_UNSIGNED_INT:
4570 if (context->getClientMajorVersion() < 3)
4571 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004572 context->handleError(InvalidEnum()
4573 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004574 return false;
4575 }
4576 break;
4577
4578 case GL_FIXED:
4579 case GL_FLOAT:
4580 if (pureInteger)
4581 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004582 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004583 return false;
4584 }
4585 break;
4586
4587 case GL_HALF_FLOAT:
4588 if (context->getClientMajorVersion() < 3)
4589 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004590 context->handleError(InvalidEnum()
4591 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004592 return false;
4593 }
4594 if (pureInteger)
4595 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004596 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004597 return false;
4598 }
4599 break;
4600
4601 case GL_INT_2_10_10_10_REV:
4602 case GL_UNSIGNED_INT_2_10_10_10_REV:
4603 if (context->getClientMajorVersion() < 3)
4604 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004605 context->handleError(InvalidEnum()
4606 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004607 return false;
4608 }
4609 if (pureInteger)
4610 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004611 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004612 return false;
4613 }
4614 if (size != 4)
4615 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004616 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4617 "UNSIGNED_INT_2_10_10_10_REV and "
4618 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004619 return false;
4620 }
4621 break;
4622
4623 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004624 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004625 return false;
4626 }
4627
4628 return true;
4629}
4630
Geoff Lang76e65652017-03-27 14:58:02 -04004631// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4632// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4633// specified clear value and the type of a buffer that is being cleared generates an
4634// INVALID_OPERATION error instead of producing undefined results
4635bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4636 GLint drawbuffer,
4637 const GLenum *validComponentTypes,
4638 size_t validComponentTypeCount)
4639{
4640 const FramebufferAttachment *attachment =
4641 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4642 if (attachment)
4643 {
4644 GLenum componentType = attachment->getFormat().info->componentType;
4645 const GLenum *end = validComponentTypes + validComponentTypeCount;
4646 if (std::find(validComponentTypes, end, componentType) == end)
4647 {
4648 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004649 InvalidOperation()
4650 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004651 return false;
4652 }
4653 }
4654
4655 return true;
4656}
4657
Corentin Wallezb2931602017-04-11 15:58:57 -04004658bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4659 GLsizei imageSize,
4660 GLsizei dataSize)
4661{
4662 if (!ValidateRobustEntryPoint(context, dataSize))
4663 {
4664 return false;
4665 }
4666
4667 gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
4668 if (pixelUnpackBuffer == nullptr)
4669 {
4670 if (dataSize < imageSize)
4671 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004672 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004673 }
4674 }
4675 return true;
4676}
4677
Jamie Madillbe849e42017-05-02 15:49:00 -04004678bool ValidateGetBufferParameterBase(ValidationContext *context,
4679 GLenum target,
4680 GLenum pname,
4681 bool pointerVersion,
4682 GLsizei *numParams)
4683{
4684 if (numParams)
4685 {
4686 *numParams = 0;
4687 }
4688
4689 if (!ValidBufferTarget(context, target))
4690 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004691 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004692 return false;
4693 }
4694
4695 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4696 if (!buffer)
4697 {
4698 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004699 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004700 return false;
4701 }
4702
4703 const Extensions &extensions = context->getExtensions();
4704
4705 switch (pname)
4706 {
4707 case GL_BUFFER_USAGE:
4708 case GL_BUFFER_SIZE:
4709 break;
4710
4711 case GL_BUFFER_ACCESS_OES:
4712 if (!extensions.mapBuffer)
4713 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004714 context->handleError(InvalidEnum()
4715 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004716 return false;
4717 }
4718 break;
4719
4720 case GL_BUFFER_MAPPED:
4721 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4722 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4723 !extensions.mapBufferRange)
4724 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004725 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4726 "GL_OES_mapbuffer or "
4727 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004728 return false;
4729 }
4730 break;
4731
4732 case GL_BUFFER_MAP_POINTER:
4733 if (!pointerVersion)
4734 {
4735 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004736 InvalidEnum()
4737 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004738 return false;
4739 }
4740 break;
4741
4742 case GL_BUFFER_ACCESS_FLAGS:
4743 case GL_BUFFER_MAP_OFFSET:
4744 case GL_BUFFER_MAP_LENGTH:
4745 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4746 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004747 context->handleError(InvalidEnum()
4748 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004749 return false;
4750 }
4751 break;
4752
4753 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004754 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004755 return false;
4756 }
4757
4758 // All buffer parameter queries return one value.
4759 if (numParams)
4760 {
4761 *numParams = 1;
4762 }
4763
4764 return true;
4765}
4766
4767bool ValidateGetRenderbufferParameterivBase(Context *context,
4768 GLenum target,
4769 GLenum pname,
4770 GLsizei *length)
4771{
4772 if (length)
4773 {
4774 *length = 0;
4775 }
4776
4777 if (target != GL_RENDERBUFFER)
4778 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004779 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004780 return false;
4781 }
4782
4783 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4784 if (renderbuffer == nullptr)
4785 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004786 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004787 return false;
4788 }
4789
4790 switch (pname)
4791 {
4792 case GL_RENDERBUFFER_WIDTH:
4793 case GL_RENDERBUFFER_HEIGHT:
4794 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4795 case GL_RENDERBUFFER_RED_SIZE:
4796 case GL_RENDERBUFFER_GREEN_SIZE:
4797 case GL_RENDERBUFFER_BLUE_SIZE:
4798 case GL_RENDERBUFFER_ALPHA_SIZE:
4799 case GL_RENDERBUFFER_DEPTH_SIZE:
4800 case GL_RENDERBUFFER_STENCIL_SIZE:
4801 break;
4802
4803 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4804 if (!context->getExtensions().framebufferMultisample)
4805 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004806 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004807 return false;
4808 }
4809 break;
4810
4811 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004812 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004813 return false;
4814 }
4815
4816 if (length)
4817 {
4818 *length = 1;
4819 }
4820 return true;
4821}
4822
4823bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4824{
4825 if (length)
4826 {
4827 *length = 0;
4828 }
4829
4830 if (GetValidShader(context, shader) == nullptr)
4831 {
4832 return false;
4833 }
4834
4835 switch (pname)
4836 {
4837 case GL_SHADER_TYPE:
4838 case GL_DELETE_STATUS:
4839 case GL_COMPILE_STATUS:
4840 case GL_INFO_LOG_LENGTH:
4841 case GL_SHADER_SOURCE_LENGTH:
4842 break;
4843
4844 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4845 if (!context->getExtensions().translatedShaderSource)
4846 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004847 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004848 return false;
4849 }
4850 break;
4851
4852 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004853 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004854 return false;
4855 }
4856
4857 if (length)
4858 {
4859 *length = 1;
4860 }
4861 return true;
4862}
4863
4864bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4865{
4866 if (length)
4867 {
4868 *length = 0;
4869 }
4870
4871 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4872 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004873 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004874 return false;
4875 }
4876
4877 if (context->getTargetTexture(target) == nullptr)
4878 {
4879 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004880 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004881 return false;
4882 }
4883
4884 switch (pname)
4885 {
4886 case GL_TEXTURE_MAG_FILTER:
4887 case GL_TEXTURE_MIN_FILTER:
4888 case GL_TEXTURE_WRAP_S:
4889 case GL_TEXTURE_WRAP_T:
4890 break;
4891
4892 case GL_TEXTURE_USAGE_ANGLE:
4893 if (!context->getExtensions().textureUsage)
4894 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004895 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004896 return false;
4897 }
4898 break;
4899
4900 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4901 if (!context->getExtensions().textureFilterAnisotropic)
4902 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004903 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004904 return false;
4905 }
4906 break;
4907
4908 case GL_TEXTURE_IMMUTABLE_FORMAT:
4909 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4910 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004911 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004912 return false;
4913 }
4914 break;
4915
4916 case GL_TEXTURE_WRAP_R:
4917 case GL_TEXTURE_IMMUTABLE_LEVELS:
4918 case GL_TEXTURE_SWIZZLE_R:
4919 case GL_TEXTURE_SWIZZLE_G:
4920 case GL_TEXTURE_SWIZZLE_B:
4921 case GL_TEXTURE_SWIZZLE_A:
4922 case GL_TEXTURE_BASE_LEVEL:
4923 case GL_TEXTURE_MAX_LEVEL:
4924 case GL_TEXTURE_MIN_LOD:
4925 case GL_TEXTURE_MAX_LOD:
4926 case GL_TEXTURE_COMPARE_MODE:
4927 case GL_TEXTURE_COMPARE_FUNC:
4928 if (context->getClientMajorVersion() < 3)
4929 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004930 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004931 return false;
4932 }
4933 break;
4934
4935 case GL_TEXTURE_SRGB_DECODE_EXT:
4936 if (!context->getExtensions().textureSRGBDecode)
4937 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004938 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004939 return false;
4940 }
4941 break;
4942
4943 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004944 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004945 return false;
4946 }
4947
4948 if (length)
4949 {
4950 *length = 1;
4951 }
4952 return true;
4953}
4954
4955bool ValidateGetVertexAttribBase(Context *context,
4956 GLuint index,
4957 GLenum pname,
4958 GLsizei *length,
4959 bool pointer,
4960 bool pureIntegerEntryPoint)
4961{
4962 if (length)
4963 {
4964 *length = 0;
4965 }
4966
4967 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
4968 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004969 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004970 return false;
4971 }
4972
4973 if (index >= context->getCaps().maxVertexAttributes)
4974 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004975 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04004976 return false;
4977 }
4978
4979 if (pointer)
4980 {
4981 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
4982 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004983 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004984 return false;
4985 }
4986 }
4987 else
4988 {
4989 switch (pname)
4990 {
4991 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
4992 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
4993 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
4994 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
4995 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
4996 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
4997 case GL_CURRENT_VERTEX_ATTRIB:
4998 break;
4999
5000 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5001 static_assert(
5002 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5003 "ANGLE extension enums not equal to GL enums.");
5004 if (context->getClientMajorVersion() < 3 &&
5005 !context->getExtensions().instancedArrays)
5006 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005007 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5008 "requires OpenGL ES 3.0 or "
5009 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005010 return false;
5011 }
5012 break;
5013
5014 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5015 if (context->getClientMajorVersion() < 3)
5016 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005017 context->handleError(
5018 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005019 return false;
5020 }
5021 break;
5022
5023 case GL_VERTEX_ATTRIB_BINDING:
5024 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5025 if (context->getClientVersion() < ES_3_1)
5026 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005027 context->handleError(InvalidEnum()
5028 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005029 return false;
5030 }
5031 break;
5032
5033 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005034 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005035 return false;
5036 }
5037 }
5038
5039 if (length)
5040 {
5041 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5042 {
5043 *length = 4;
5044 }
5045 else
5046 {
5047 *length = 1;
5048 }
5049 }
5050
5051 return true;
5052}
5053
Jamie Madill4928b7c2017-06-20 12:57:39 -04005054bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005055 GLint x,
5056 GLint y,
5057 GLsizei width,
5058 GLsizei height,
5059 GLenum format,
5060 GLenum type,
5061 GLsizei bufSize,
5062 GLsizei *length,
5063 GLsizei *columns,
5064 GLsizei *rows,
5065 void *pixels)
5066{
5067 if (length != nullptr)
5068 {
5069 *length = 0;
5070 }
5071 if (rows != nullptr)
5072 {
5073 *rows = 0;
5074 }
5075 if (columns != nullptr)
5076 {
5077 *columns = 0;
5078 }
5079
5080 if (width < 0 || height < 0)
5081 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005082 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005083 return false;
5084 }
5085
5086 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5087
5088 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5089 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005090 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005091 return false;
5092 }
5093
5094 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5095 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005096 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005097 return false;
5098 }
5099
5100 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5101 ASSERT(framebuffer);
5102
5103 if (framebuffer->getReadBufferState() == GL_NONE)
5104 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005106 return false;
5107 }
5108
5109 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5110 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5111 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5112 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5113 // situation is an application error that would lead to a crash in ANGLE.
5114 if (readBuffer == nullptr)
5115 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005116 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005117 return false;
5118 }
5119
Martin Radev28031682017-07-28 14:47:56 +03005120 // ANGLE_multiview, Revision 1:
5121 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5122 // current read framebuffer is not NONE.
5123 if (readBuffer->getMultiviewLayout() != GL_NONE)
5124 {
5125 context->handleError(InvalidFramebufferOperation()
5126 << "Attempting to read from a multi-view framebuffer.");
5127 return false;
5128 }
5129
Geoff Lang280ba992017-04-18 16:30:58 -04005130 if (context->getExtensions().webglCompatibility)
5131 {
5132 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5133 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5134 // and type before validating the combination of format and type. However, the
5135 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5136 // verifies that GL_INVALID_OPERATION is generated.
5137 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5138 // dEQP/WebGL.
5139 if (!ValidReadPixelsFormatEnum(context, format))
5140 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005141 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005142 return false;
5143 }
5144
5145 if (!ValidReadPixelsTypeEnum(context, type))
5146 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005147 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005148 return false;
5149 }
5150 }
5151
Jamie Madill4928b7c2017-06-20 12:57:39 -04005152 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5153 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005154 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5155
5156 bool validFormatTypeCombination =
5157 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5158
5159 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5160 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005161 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005162 return false;
5163 }
5164
5165 // Check for pixel pack buffer related API errors
5166 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_PACK_BUFFER);
5167 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5168 {
5169 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005170 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005171 return false;
5172 }
5173
5174 // .. the data would be packed to the buffer object such that the memory writes required
5175 // would exceed the data store size.
5176 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5177 const gl::Extents size(width, height, 1);
5178 const auto &pack = context->getGLState().getPackState();
5179
5180 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5181 if (endByteOrErr.isError())
5182 {
5183 context->handleError(endByteOrErr.getError());
5184 return false;
5185 }
5186
5187 size_t endByte = endByteOrErr.getResult();
5188 if (bufSize >= 0)
5189 {
5190 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5191 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005192 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005193 return false;
5194 }
5195 }
5196
5197 if (pixelPackBuffer != nullptr)
5198 {
5199 CheckedNumeric<size_t> checkedEndByte(endByte);
5200 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5201 checkedEndByte += checkedOffset;
5202
5203 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5204 {
5205 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005206 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005207 return false;
5208 }
5209 }
5210
5211 if (pixelPackBuffer == nullptr && length != nullptr)
5212 {
5213 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5214 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005215 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005216 return false;
5217 }
5218
5219 *length = static_cast<GLsizei>(endByte);
5220 }
5221
5222 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5223 angle::CheckedNumeric<int> clippedExtent(length);
5224 if (start < 0)
5225 {
5226 // "subtract" the area that is less than 0
5227 clippedExtent += start;
5228 }
5229
5230 const int readExtent = start + length;
5231 if (readExtent > bufferSize)
5232 {
5233 // Subtract the region to the right of the read buffer
5234 clippedExtent -= (readExtent - bufferSize);
5235 }
5236
5237 if (!clippedExtent.IsValid())
5238 {
5239 return 0;
5240 }
5241
5242 return std::max(clippedExtent.ValueOrDie(), 0);
5243 };
5244
5245 if (columns != nullptr)
5246 {
5247 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5248 }
5249
5250 if (rows != nullptr)
5251 {
5252 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5253 }
5254
5255 return true;
5256}
5257
5258template <typename ParamType>
5259bool ValidateTexParameterBase(Context *context,
5260 GLenum target,
5261 GLenum pname,
5262 GLsizei bufSize,
5263 const ParamType *params)
5264{
5265 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5266 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005267 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005268 return false;
5269 }
5270
5271 if (context->getTargetTexture(target) == nullptr)
5272 {
5273 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005274 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005275 return false;
5276 }
5277
5278 const GLsizei minBufSize = 1;
5279 if (bufSize >= 0 && bufSize < minBufSize)
5280 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005281 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005282 return false;
5283 }
5284
5285 switch (pname)
5286 {
5287 case GL_TEXTURE_WRAP_R:
5288 case GL_TEXTURE_SWIZZLE_R:
5289 case GL_TEXTURE_SWIZZLE_G:
5290 case GL_TEXTURE_SWIZZLE_B:
5291 case GL_TEXTURE_SWIZZLE_A:
5292 case GL_TEXTURE_BASE_LEVEL:
5293 case GL_TEXTURE_MAX_LEVEL:
5294 case GL_TEXTURE_COMPARE_MODE:
5295 case GL_TEXTURE_COMPARE_FUNC:
5296 case GL_TEXTURE_MIN_LOD:
5297 case GL_TEXTURE_MAX_LOD:
5298 if (context->getClientMajorVersion() < 3)
5299 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005300 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005301 return false;
5302 }
5303 if (target == GL_TEXTURE_EXTERNAL_OES &&
5304 !context->getExtensions().eglImageExternalEssl3)
5305 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005306 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5307 "available without "
5308 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005309 return false;
5310 }
5311 break;
5312
5313 default:
5314 break;
5315 }
5316
JiangYizhou4cff8d62017-07-06 14:54:09 +08005317 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5318 {
5319 switch (pname)
5320 {
5321 case GL_TEXTURE_MIN_FILTER:
5322 case GL_TEXTURE_MAG_FILTER:
5323 case GL_TEXTURE_WRAP_S:
5324 case GL_TEXTURE_WRAP_T:
5325 case GL_TEXTURE_WRAP_R:
5326 case GL_TEXTURE_MIN_LOD:
5327 case GL_TEXTURE_MAX_LOD:
5328 case GL_TEXTURE_COMPARE_MODE:
5329 case GL_TEXTURE_COMPARE_FUNC:
5330 context->handleError(InvalidEnum()
5331 << "Invalid parameter for 2D multisampled textures.");
5332 return false;
5333 }
5334 }
5335
Jamie Madillbe849e42017-05-02 15:49:00 -04005336 switch (pname)
5337 {
5338 case GL_TEXTURE_WRAP_S:
5339 case GL_TEXTURE_WRAP_T:
5340 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005341 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005342 bool restrictedWrapModes =
5343 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5344 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5345 {
5346 return false;
5347 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005348 }
5349 break;
5350
5351 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005352 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005353 bool restrictedMinFilter =
5354 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5355 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5356 {
5357 return false;
5358 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005359 }
5360 break;
5361
5362 case GL_TEXTURE_MAG_FILTER:
5363 if (!ValidateTextureMagFilterValue(context, params))
5364 {
5365 return false;
5366 }
5367 break;
5368
5369 case GL_TEXTURE_USAGE_ANGLE:
5370 switch (ConvertToGLenum(params[0]))
5371 {
5372 case GL_NONE:
5373 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5374 break;
5375
5376 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005377 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005378 return false;
5379 }
5380 break;
5381
5382 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5383 if (!context->getExtensions().textureFilterAnisotropic)
5384 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005385 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005386 return false;
5387 }
5388
5389 // we assume the parameter passed to this validation method is truncated, not rounded
5390 if (params[0] < 1)
5391 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005392 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005393 return false;
5394 }
5395 break;
5396
5397 case GL_TEXTURE_MIN_LOD:
5398 case GL_TEXTURE_MAX_LOD:
5399 // any value is permissible
5400 break;
5401
5402 case GL_TEXTURE_COMPARE_MODE:
5403 if (!ValidateTextureCompareModeValue(context, params))
5404 {
5405 return false;
5406 }
5407 break;
5408
5409 case GL_TEXTURE_COMPARE_FUNC:
5410 if (!ValidateTextureCompareFuncValue(context, params))
5411 {
5412 return false;
5413 }
5414 break;
5415
5416 case GL_TEXTURE_SWIZZLE_R:
5417 case GL_TEXTURE_SWIZZLE_G:
5418 case GL_TEXTURE_SWIZZLE_B:
5419 case GL_TEXTURE_SWIZZLE_A:
5420 switch (ConvertToGLenum(params[0]))
5421 {
5422 case GL_RED:
5423 case GL_GREEN:
5424 case GL_BLUE:
5425 case GL_ALPHA:
5426 case GL_ZERO:
5427 case GL_ONE:
5428 break;
5429
5430 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005431 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005432 return false;
5433 }
5434 break;
5435
5436 case GL_TEXTURE_BASE_LEVEL:
5437 if (params[0] < 0)
5438 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005439 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005440 return false;
5441 }
5442 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5443 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005444 context->handleError(InvalidOperation()
5445 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005446 return false;
5447 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005448 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5449 {
5450 context->handleError(InvalidOperation()
5451 << "Base level must be 0 for multisampled textures.");
5452 return false;
5453 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005454 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5455 {
5456 context->handleError(InvalidOperation()
5457 << "Base level must be 0 for rectangle textures.");
5458 return false;
5459 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005460 break;
5461
5462 case GL_TEXTURE_MAX_LEVEL:
5463 if (params[0] < 0)
5464 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005465 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005466 return false;
5467 }
5468 break;
5469
5470 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5471 if (context->getClientVersion() < Version(3, 1))
5472 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005473 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005474 return false;
5475 }
5476 switch (ConvertToGLenum(params[0]))
5477 {
5478 case GL_DEPTH_COMPONENT:
5479 case GL_STENCIL_INDEX:
5480 break;
5481
5482 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005483 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005484 return false;
5485 }
5486 break;
5487
5488 case GL_TEXTURE_SRGB_DECODE_EXT:
5489 if (!ValidateTextureSRGBDecodeValue(context, params))
5490 {
5491 return false;
5492 }
5493 break;
5494
5495 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005496 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005497 return false;
5498 }
5499
5500 return true;
5501}
5502
5503template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5504template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5505
Jamie Madill12e957f2017-08-26 21:42:26 -04005506bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5507{
5508 if (index >= MAX_VERTEX_ATTRIBS)
5509 {
5510 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5511 return false;
5512 }
5513
5514 return true;
5515}
5516
5517bool ValidateGetActiveUniformBlockivBase(Context *context,
5518 GLuint program,
5519 GLuint uniformBlockIndex,
5520 GLenum pname,
5521 GLsizei *length)
5522{
5523 if (length)
5524 {
5525 *length = 0;
5526 }
5527
5528 if (context->getClientMajorVersion() < 3)
5529 {
5530 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5531 return false;
5532 }
5533
5534 Program *programObject = GetValidProgram(context, program);
5535 if (!programObject)
5536 {
5537 return false;
5538 }
5539
5540 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5541 {
5542 context->handleError(InvalidValue()
5543 << "uniformBlockIndex exceeds active uniform block count.");
5544 return false;
5545 }
5546
5547 switch (pname)
5548 {
5549 case GL_UNIFORM_BLOCK_BINDING:
5550 case GL_UNIFORM_BLOCK_DATA_SIZE:
5551 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5552 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5553 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5554 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5555 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5556 break;
5557
5558 default:
5559 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5560 return false;
5561 }
5562
5563 if (length)
5564 {
5565 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5566 {
5567 const UniformBlock &uniformBlock =
5568 programObject->getUniformBlockByIndex(uniformBlockIndex);
5569 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5570 }
5571 else
5572 {
5573 *length = 1;
5574 }
5575 }
5576
5577 return true;
5578}
5579
Jamie Madill9696d072017-08-26 23:19:57 -04005580template <typename ParamType>
5581bool ValidateSamplerParameterBase(Context *context,
5582 GLuint sampler,
5583 GLenum pname,
5584 GLsizei bufSize,
5585 ParamType *params)
5586{
5587 if (context->getClientMajorVersion() < 3)
5588 {
5589 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5590 return false;
5591 }
5592
5593 if (!context->isSampler(sampler))
5594 {
5595 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5596 return false;
5597 }
5598
5599 const GLsizei minBufSize = 1;
5600 if (bufSize >= 0 && bufSize < minBufSize)
5601 {
5602 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5603 return false;
5604 }
5605
5606 switch (pname)
5607 {
5608 case GL_TEXTURE_WRAP_S:
5609 case GL_TEXTURE_WRAP_T:
5610 case GL_TEXTURE_WRAP_R:
5611 if (!ValidateTextureWrapModeValue(context, params, false))
5612 {
5613 return false;
5614 }
5615 break;
5616
5617 case GL_TEXTURE_MIN_FILTER:
5618 if (!ValidateTextureMinFilterValue(context, params, false))
5619 {
5620 return false;
5621 }
5622 break;
5623
5624 case GL_TEXTURE_MAG_FILTER:
5625 if (!ValidateTextureMagFilterValue(context, params))
5626 {
5627 return false;
5628 }
5629 break;
5630
5631 case GL_TEXTURE_MIN_LOD:
5632 case GL_TEXTURE_MAX_LOD:
5633 // any value is permissible
5634 break;
5635
5636 case GL_TEXTURE_COMPARE_MODE:
5637 if (!ValidateTextureCompareModeValue(context, params))
5638 {
5639 return false;
5640 }
5641 break;
5642
5643 case GL_TEXTURE_COMPARE_FUNC:
5644 if (!ValidateTextureCompareFuncValue(context, params))
5645 {
5646 return false;
5647 }
5648 break;
5649
5650 case GL_TEXTURE_SRGB_DECODE_EXT:
5651 if (!ValidateTextureSRGBDecodeValue(context, params))
5652 {
5653 return false;
5654 }
5655 break;
5656
5657 default:
5658 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5659 return false;
5660 }
5661
5662 return true;
5663}
5664
5665template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5666template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5667
5668bool ValidateGetSamplerParameterBase(Context *context,
5669 GLuint sampler,
5670 GLenum pname,
5671 GLsizei *length)
5672{
5673 if (length)
5674 {
5675 *length = 0;
5676 }
5677
5678 if (context->getClientMajorVersion() < 3)
5679 {
5680 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5681 return false;
5682 }
5683
5684 if (!context->isSampler(sampler))
5685 {
5686 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5687 return false;
5688 }
5689
5690 switch (pname)
5691 {
5692 case GL_TEXTURE_WRAP_S:
5693 case GL_TEXTURE_WRAP_T:
5694 case GL_TEXTURE_WRAP_R:
5695 case GL_TEXTURE_MIN_FILTER:
5696 case GL_TEXTURE_MAG_FILTER:
5697 case GL_TEXTURE_MIN_LOD:
5698 case GL_TEXTURE_MAX_LOD:
5699 case GL_TEXTURE_COMPARE_MODE:
5700 case GL_TEXTURE_COMPARE_FUNC:
5701 break;
5702
5703 case GL_TEXTURE_SRGB_DECODE_EXT:
5704 if (!context->getExtensions().textureSRGBDecode)
5705 {
5706 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5707 return false;
5708 }
5709 break;
5710
5711 default:
5712 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5713 return false;
5714 }
5715
5716 if (length)
5717 {
5718 *length = 1;
5719 }
5720 return true;
5721}
5722
5723bool ValidateGetInternalFormativBase(Context *context,
5724 GLenum target,
5725 GLenum internalformat,
5726 GLenum pname,
5727 GLsizei bufSize,
5728 GLsizei *numParams)
5729{
5730 if (numParams)
5731 {
5732 *numParams = 0;
5733 }
5734
5735 if (context->getClientMajorVersion() < 3)
5736 {
5737 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
5738 return false;
5739 }
5740
5741 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5742 if (!formatCaps.renderable)
5743 {
5744 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5745 return false;
5746 }
5747
5748 switch (target)
5749 {
5750 case GL_RENDERBUFFER:
5751 break;
5752
5753 case GL_TEXTURE_2D_MULTISAMPLE:
5754 if (context->getClientVersion() < ES_3_1)
5755 {
5756 context->handleError(InvalidOperation()
5757 << "Texture target requires at least OpenGL ES 3.1.");
5758 return false;
5759 }
5760 break;
5761
5762 default:
5763 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5764 return false;
5765 }
5766
5767 if (bufSize < 0)
5768 {
5769 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5770 return false;
5771 }
5772
5773 GLsizei maxWriteParams = 0;
5774 switch (pname)
5775 {
5776 case GL_NUM_SAMPLE_COUNTS:
5777 maxWriteParams = 1;
5778 break;
5779
5780 case GL_SAMPLES:
5781 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5782 break;
5783
5784 default:
5785 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5786 return false;
5787 }
5788
5789 if (numParams)
5790 {
5791 // glGetInternalFormativ will not overflow bufSize
5792 *numParams = std::min(bufSize, maxWriteParams);
5793 }
5794
5795 return true;
5796}
5797
Jamie Madillc29968b2016-01-20 11:17:23 -05005798} // namespace gl