blob: 5b9e41be526cfdfd20156ab32fe5cbeaf9cc4ef0 [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"
jchen10a99ed552017-09-22 08:10:32 +080024#include "libANGLE/queryconversions.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040025#include "libANGLE/validationES2.h"
26#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040027
28#include "common/mathutil.h"
29#include "common/utilities.h"
30
Jamie Madille2e406c2016-06-02 13:04:10 -040031using namespace angle;
32
Geoff Lange8ebe7f2013-08-05 15:03:13 -040033namespace gl
34{
Jamie Madill1ca74672015-07-21 15:14:11 -040035namespace
36{
jchen10a99ed552017-09-22 08:10:32 +080037
Corentin Wallez92db6942016-12-09 13:10:36 -050038bool ValidateDrawAttribs(ValidationContext *context,
39 GLint primcount,
40 GLint maxVertex,
41 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040042{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070043 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040044 const gl::Program *program = state.getProgram();
45
Corentin Wallez327411e2016-12-09 11:09:17 -050046 bool webglCompatibility = context->getExtensions().webglCompatibility;
47
Jamie Madill231c7f52017-04-26 13:45:37 -040048 const VertexArray *vao = state.getVertexArray();
49 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080050 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madill231c7f52017-04-26 13:45:37 -040051 size_t maxEnabledAttrib = vao->getMaxEnabledAttribute();
Jamie Madill1ca74672015-07-21 15:14:11 -040052 for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex)
53 {
54 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallez672f7f32017-06-15 17:42:17 -040055
56 // No need to range check for disabled attribs.
57 if (!attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040058 {
Corentin Wallezfd456442016-12-21 17:57:00 -050059 continue;
60 }
Jamie Madill1ca74672015-07-21 15:14:11 -040061
Jamie Madill231c7f52017-04-26 13:45:37 -040062 // If we have no buffer, then we either get an error, or there are no more checks to be
63 // done.
Corentin Wallez672f7f32017-06-15 17:42:17 -040064 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
65 gl::Buffer *buffer = binding.getBuffer().get();
Corentin Wallezfd456442016-12-21 17:57:00 -050066 if (!buffer)
67 {
Geoff Langfeb8c682017-02-13 16:07:35 -050068 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -050069 {
70 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050071 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
72 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
73 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
74 // error.
Brandon Jonesafa75152017-07-21 13:11:29 -070075 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
Corentin Wallezfd456442016-12-21 17:57:00 -050076 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050077 }
Corentin Wallezfd456442016-12-21 17:57:00 -050078 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040079 {
80 // This is an application error that would normally result in a crash,
81 // but we catch it and return an error
Brandon Jonesafa75152017-07-21 13:11:29 -070082 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
Jamie Madill1ca74672015-07-21 15:14:11 -040083 return false;
84 }
Corentin Wallezfd456442016-12-21 17:57:00 -050085 continue;
86 }
87
Corentin Wallez672f7f32017-06-15 17:42:17 -040088 // This needs to come after the check for client arrays as even unused attributes cannot use
89 // client-side arrays
90 if (!program->isAttribLocationActive(attributeIndex))
91 {
92 continue;
93 }
94
Corentin Wallezfd456442016-12-21 17:57:00 -050095 // If we're drawing zero vertices, we have enough data.
96 if (vertexCount <= 0 || primcount <= 0)
97 {
98 continue;
99 }
100
101 GLint maxVertexElement = 0;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300102 GLuint divisor = binding.getDivisor();
103 if (divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500104 {
105 maxVertexElement = maxVertex;
106 }
107 else
108 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300109 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500110 }
111
112 // We do manual overflow checks here instead of using safe_math.h because it was
113 // a bottleneck. Thanks to some properties of GL we know inequalities that can
114 // help us make the overflow checks faster.
115
116 // The max possible attribSize is 16 for a vector of 4 32 bit values.
117 constexpr uint64_t kMaxAttribSize = 16;
118 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
119 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
120
121 // We know attribStride is given as a GLsizei which is typedefed to int.
122 // We also know an upper bound for attribSize.
123 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800124 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500125 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
126 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
127
128 // Computing the max offset using uint64_t without attrib.offset is overflow
129 // safe. Note: Last vertex element does not take the full stride!
130 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
131 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
132
133 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800134 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
135 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500136 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700137 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500138 return false;
139 }
140 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
141
142 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
143 // We can return INVALID_OPERATION if our vertex attribute does not have
144 // enough backing data.
145 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
146 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700147 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500148 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400149 }
150 }
151
152 return true;
153}
154
Geoff Lang280ba992017-04-18 16:30:58 -0400155bool ValidReadPixelsTypeEnum(ValidationContext *context, GLenum type)
156{
157 switch (type)
158 {
159 // Types referenced in Table 3.4 of the ES 2.0.25 spec
160 case GL_UNSIGNED_BYTE:
161 case GL_UNSIGNED_SHORT_4_4_4_4:
162 case GL_UNSIGNED_SHORT_5_5_5_1:
163 case GL_UNSIGNED_SHORT_5_6_5:
164 return context->getClientVersion() >= ES_2_0;
165
166 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
167 case GL_BYTE:
168 case GL_INT:
169 case GL_SHORT:
170 case GL_UNSIGNED_INT:
171 case GL_UNSIGNED_INT_10F_11F_11F_REV:
172 case GL_UNSIGNED_INT_24_8:
173 case GL_UNSIGNED_INT_2_10_10_10_REV:
174 case GL_UNSIGNED_INT_5_9_9_9_REV:
175 case GL_UNSIGNED_SHORT:
176 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
177 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
178 return context->getClientVersion() >= ES_3_0;
179
180 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400181 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
182 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400183
184 case GL_HALF_FLOAT:
185 return context->getClientVersion() >= ES_3_0 ||
186 context->getExtensions().textureHalfFloat;
187
188 case GL_HALF_FLOAT_OES:
189 return context->getExtensions().colorBufferHalfFloat;
190
191 default:
192 return false;
193 }
194}
195
196bool ValidReadPixelsFormatEnum(ValidationContext *context, GLenum format)
197{
198 switch (format)
199 {
200 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
201 case GL_RGBA:
202 case GL_RGB:
203 case GL_ALPHA:
204 return context->getClientVersion() >= ES_2_0;
205
206 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
207 case GL_RG:
208 case GL_RED:
209 case GL_RGBA_INTEGER:
210 case GL_RGB_INTEGER:
211 case GL_RG_INTEGER:
212 case GL_RED_INTEGER:
213 return context->getClientVersion() >= ES_3_0;
214
215 case GL_SRGB_ALPHA_EXT:
216 case GL_SRGB_EXT:
217 return context->getExtensions().sRGB;
218
219 case GL_BGRA_EXT:
220 return context->getExtensions().readFormatBGRA;
221
222 default:
223 return false;
224 }
225}
226
Geoff Langf607c602016-09-21 11:46:48 -0400227bool ValidReadPixelsFormatType(ValidationContext *context,
228 GLenum framebufferComponentType,
229 GLenum format,
230 GLenum type)
231{
232 switch (framebufferComponentType)
233 {
234 case GL_UNSIGNED_NORMALIZED:
235 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
236 // ReadPixels with BGRA even if the extension is not present
237 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
238 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
239 type == GL_UNSIGNED_BYTE);
240
241 case GL_SIGNED_NORMALIZED:
242 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
243
244 case GL_INT:
245 return (format == GL_RGBA_INTEGER && type == GL_INT);
246
247 case GL_UNSIGNED_INT:
248 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
249
250 case GL_FLOAT:
251 return (format == GL_RGBA && type == GL_FLOAT);
252
253 default:
254 UNREACHABLE();
255 return false;
256 }
257}
258
Geoff Langc1984ed2016-10-07 12:41:00 -0400259template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400260bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400261{
262 switch (ConvertToGLenum(params[0]))
263 {
264 case GL_CLAMP_TO_EDGE:
265 break;
266
267 case GL_REPEAT:
268 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400269 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400270 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400271 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700272 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400273 return false;
274 }
275 break;
276
277 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700278 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400279 return false;
280 }
281
282 return true;
283}
284
285template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400286bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400287{
288 switch (ConvertToGLenum(params[0]))
289 {
290 case GL_NEAREST:
291 case GL_LINEAR:
292 break;
293
294 case GL_NEAREST_MIPMAP_NEAREST:
295 case GL_LINEAR_MIPMAP_NEAREST:
296 case GL_NEAREST_MIPMAP_LINEAR:
297 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400298 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400299 {
300 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700301 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400302 return false;
303 }
304 break;
305
306 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700307 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400308 return false;
309 }
310
311 return true;
312}
313
314template <typename ParamType>
315bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
316{
317 switch (ConvertToGLenum(params[0]))
318 {
319 case GL_NEAREST:
320 case GL_LINEAR:
321 break;
322
323 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700324 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400325 return false;
326 }
327
328 return true;
329}
330
331template <typename ParamType>
332bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
333{
334 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
335 switch (ConvertToGLenum(params[0]))
336 {
337 case GL_NONE:
338 case GL_COMPARE_REF_TO_TEXTURE:
339 break;
340
341 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700342 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400343 return false;
344 }
345
346 return true;
347}
348
349template <typename ParamType>
350bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
351{
352 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
353 switch (ConvertToGLenum(params[0]))
354 {
355 case GL_LEQUAL:
356 case GL_GEQUAL:
357 case GL_LESS:
358 case GL_GREATER:
359 case GL_EQUAL:
360 case GL_NOTEQUAL:
361 case GL_ALWAYS:
362 case GL_NEVER:
363 break;
364
365 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700366 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400367 return false;
368 }
369
370 return true;
371}
372
373template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700374bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
375{
376 if (!context->getExtensions().textureSRGBDecode)
377 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700378 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700379 return false;
380 }
381
382 switch (ConvertToGLenum(params[0]))
383 {
384 case GL_DECODE_EXT:
385 case GL_SKIP_DECODE_EXT:
386 break;
387
388 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700389 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700390 return false;
391 }
392
393 return true;
394}
395
Jamie Madillc1d770e2017-04-13 17:31:24 -0400396bool ValidateUniformCommonBase(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500397 gl::Program *program,
398 GLint location,
399 GLsizei count,
400 const LinkedUniform **uniformOut)
401{
402 // TODO(Jiajia): Add image uniform check in future.
403 if (count < 0)
404 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700405 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500406 return false;
407 }
408
Brandon Jones6cad5662017-06-14 13:25:13 -0700409 if (!program)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500410 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700411 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
412 return false;
413 }
414
415 if (!program->isLinked())
416 {
417 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500418 return false;
419 }
420
421 if (location == -1)
422 {
423 // Silently ignore the uniform command
424 return false;
425 }
426
427 const auto &uniformLocations = program->getUniformLocations();
Jamie Madillbe849e42017-05-02 15:49:00 -0400428 size_t castedLocation = static_cast<size_t>(location);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500429 if (castedLocation >= uniformLocations.size())
430 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500431 context->handleError(InvalidOperation() << "Invalid uniform location");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500432 return false;
433 }
434
435 const auto &uniformLocation = uniformLocations[castedLocation];
436 if (uniformLocation.ignored)
437 {
438 // Silently ignore the uniform command
439 return false;
440 }
441
Jamie Madillfb997ec2017-09-20 15:44:27 -0400442 if (!uniformLocation.used())
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500443 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500444 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500445 return false;
446 }
447
448 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
449
450 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
451 if (!uniform.isArray() && count > 1)
452 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500453 context->handleError(InvalidOperation());
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500454 return false;
455 }
456
457 *uniformOut = &uniform;
458 return true;
459}
460
Frank Henigman999b0fd2017-02-02 21:45:55 -0500461bool ValidateUniform1ivValue(ValidationContext *context,
Frank Henigmana98a6472017-02-02 21:38:32 -0500462 GLenum uniformType,
463 GLsizei count,
464 const GLint *value)
465{
466 // Value type is GL_INT, because we only get here from glUniform1i{v}.
467 // It is compatible with INT or BOOL.
468 // Do these cheap tests first, for a little extra speed.
469 if (GL_INT == uniformType || GL_BOOL == uniformType)
470 {
471 return true;
472 }
473
474 if (IsSamplerType(uniformType))
475 {
Frank Henigman999b0fd2017-02-02 21:45:55 -0500476 // Check that the values are in range.
477 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
478 for (GLsizei i = 0; i < count; ++i)
479 {
480 if (value[i] < 0 || value[i] >= max)
481 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500482 context->handleError(InvalidValue() << "sampler uniform value out of range");
Frank Henigman999b0fd2017-02-02 21:45:55 -0500483 return false;
484 }
485 }
Frank Henigmana98a6472017-02-02 21:38:32 -0500486 return true;
487 }
488
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500489 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmana98a6472017-02-02 21:38:32 -0500490 return false;
491}
492
Jamie Madillc1d770e2017-04-13 17:31:24 -0400493bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500494{
495 // Check that the value type is compatible with uniform type.
Frank Henigmana98a6472017-02-02 21:38:32 -0500496 // Do the cheaper test first, for a little extra speed.
497 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500498 {
499 return true;
500 }
501
Brandon Jonesafa75152017-07-21 13:11:29 -0700502 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500503 return false;
504}
505
Jamie Madillc1d770e2017-04-13 17:31:24 -0400506bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500507{
508 // Check that the value type is compatible with uniform type.
509 if (valueType == uniformType)
510 {
511 return true;
512 }
513
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500514 context->handleError(InvalidOperation() << "wrong type of value for uniform");
Frank Henigmanf5f74ae2017-02-02 21:14:23 -0500515 return false;
516}
517
Geoff Lange0cff192017-05-30 13:04:56 -0400518bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
519{
520 const Program *program = context->getGLState().getProgram();
521 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
522
523 const auto &programOutputTypes = program->getOutputVariableTypes();
524 for (size_t drawBufferIdx = 0; drawBufferIdx < programOutputTypes.size(); drawBufferIdx++)
525 {
526 GLenum outputType = programOutputTypes[drawBufferIdx];
527 GLenum inputType = framebuffer->getDrawbufferWriteType(drawBufferIdx);
528 if (outputType != GL_NONE && inputType != GL_NONE && inputType != outputType)
529 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500530 context->handleError(InvalidOperation() << "Fragment shader output type does not "
531 "match the bound framebuffer attachment "
532 "type.");
Geoff Lange0cff192017-05-30 13:04:56 -0400533 return false;
534 }
535 }
536
537 return true;
538}
539
Geoff Lang9ab5b822017-05-30 16:19:23 -0400540bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
541{
Jamie Madillcac94a92017-11-10 10:09:32 -0500542 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400543 const Program *program = context->getGLState().getProgram();
544 const VertexArray *vao = context->getGLState().getVertexArray();
Jamie Madillcac94a92017-11-10 10:09:32 -0500545 const auto &vertexAttribs = vao->getVertexAttributes();
546 const auto &currentValues = glState.getVertexAttribCurrentValues();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400547
Jamie Madillcac94a92017-11-10 10:09:32 -0500548 for (const sh::Attribute &shaderAttribute : program->getAttributes())
Geoff Lang9ab5b822017-05-30 16:19:23 -0400549 {
Geoff Lang69df2422017-07-05 12:42:31 -0400550 // gl_VertexID and gl_InstanceID are active attributes but don't have a bound attribute.
551 if (shaderAttribute.isBuiltIn())
552 {
553 continue;
554 }
555
Geoff Lang9ab5b822017-05-30 16:19:23 -0400556 GLenum shaderInputType = VariableComponentType(shaderAttribute.type);
557
Jamie Madillcac94a92017-11-10 10:09:32 -0500558 const auto &attrib = vertexAttribs[shaderAttribute.location];
559 GLenum vertexType = attrib.enabled ? GetVertexAttributeBaseType(attrib)
560 : currentValues[shaderAttribute.location].Type;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400561
562 if (shaderInputType != GL_NONE && vertexType != GL_NONE && shaderInputType != vertexType)
563 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500564 context->handleError(InvalidOperation() << "Vertex shader input type does not "
565 "match the type of the bound vertex "
566 "attribute.");
Geoff Lang9ab5b822017-05-30 16:19:23 -0400567 return false;
568 }
569 }
570
571 return true;
572}
573
Geoff Langf41a7152016-09-19 15:11:17 -0400574} // anonymous namespace
575
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500576bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400577{
Jamie Madilld7460c72014-01-21 16:38:14 -0500578 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400579 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800580 case GL_TEXTURE_2D:
581 case GL_TEXTURE_CUBE_MAP:
582 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400583
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400584 case GL_TEXTURE_RECTANGLE_ANGLE:
585 return context->getExtensions().textureRectangle;
586
He Yunchaoced53ae2016-11-29 15:00:51 +0800587 case GL_TEXTURE_3D:
588 case GL_TEXTURE_2D_ARRAY:
589 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500590
He Yunchaoced53ae2016-11-29 15:00:51 +0800591 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800592 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400593
He Yunchaoced53ae2016-11-29 15:00:51 +0800594 default:
595 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500596 }
Jamie Madill35d15012013-10-07 10:46:37 -0400597}
598
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500599bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
600{
601 switch (target)
602 {
603 case GL_TEXTURE_2D:
604 case GL_TEXTURE_CUBE_MAP:
605 return true;
606
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400607 case GL_TEXTURE_RECTANGLE_ANGLE:
608 return context->getExtensions().textureRectangle;
609
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500610 default:
611 return false;
612 }
613}
614
615bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
616{
617 switch (target)
618 {
619 case GL_TEXTURE_3D:
620 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300621 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500622
623 default:
624 return false;
625 }
626}
627
Ian Ewellbda75592016-04-18 17:25:54 -0400628// Most texture GL calls are not compatible with external textures, so we have a separate validation
629// function for use in the GL calls that do
630bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
631{
632 return (target == GL_TEXTURE_EXTERNAL_OES) &&
633 (context->getExtensions().eglImageExternal ||
634 context->getExtensions().eglStreamConsumerExternal);
635}
636
Shannon Woods4dfed832014-03-17 20:03:39 -0400637// This function differs from ValidTextureTarget in that the target must be
638// usable as the destination of a 2D operation-- so a cube face is valid, but
639// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400640// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500641bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400642{
643 switch (target)
644 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800645 case GL_TEXTURE_2D:
646 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
647 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
648 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
649 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
650 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
651 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
652 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400653 case GL_TEXTURE_RECTANGLE_ANGLE:
654 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800655 default:
656 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500657 }
658}
659
Jamie Madillbe849e42017-05-02 15:49:00 -0400660bool ValidateDrawElementsInstancedBase(ValidationContext *context,
661 GLenum mode,
662 GLsizei count,
663 GLenum type,
664 const GLvoid *indices,
665 GLsizei primcount)
666{
667 if (primcount < 0)
668 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700669 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400670 return false;
671 }
672
673 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
674 {
675 return false;
676 }
677
678 // No-op zero primitive count
679 return (primcount > 0);
680}
681
682bool ValidateDrawArraysInstancedBase(Context *context,
683 GLenum mode,
684 GLint first,
685 GLsizei count,
686 GLsizei primcount)
687{
688 if (primcount < 0)
689 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700690 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400691 return false;
692 }
693
694 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
695 {
696 return false;
697 }
698
699 // No-op if zero primitive count
700 return (primcount > 0);
701}
702
Corentin Wallez0dc97812017-06-22 14:38:44 -0400703bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400704{
705 // Verify there is at least one active attribute with a divisor of zero
706 const State &state = context->getGLState();
707
708 Program *program = state.getProgram();
709
710 const auto &attribs = state.getVertexArray()->getVertexAttributes();
711 const auto &bindings = state.getVertexArray()->getVertexBindings();
712 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
713 {
714 const VertexAttribute &attrib = attribs[attributeIndex];
715 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300716 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400717 {
718 return true;
719 }
720 }
721
Brandon Jonesafa75152017-07-21 13:11:29 -0700722 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400723 return false;
724}
725
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500726bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
727{
728 switch (target)
729 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800730 case GL_TEXTURE_3D:
731 case GL_TEXTURE_2D_ARRAY:
732 return true;
733 default:
734 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400735 }
736}
737
He Yunchao11b038b2016-11-22 21:24:04 +0800738bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
739{
740 switch (target)
741 {
742 case GL_TEXTURE_2D:
743 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
744 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
745 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
746 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
747 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
748 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
749 case GL_TEXTURE_3D:
750 case GL_TEXTURE_2D_ARRAY:
751 case GL_TEXTURE_2D_MULTISAMPLE:
752 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400753 case GL_TEXTURE_RECTANGLE_ANGLE:
754 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800755 default:
756 return false;
757 }
758}
759
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500760bool ValidFramebufferTarget(GLenum target)
761{
He Yunchaoced53ae2016-11-29 15:00:51 +0800762 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
763 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400764 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500765
766 switch (target)
767 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800768 case GL_FRAMEBUFFER:
769 return true;
770 case GL_READ_FRAMEBUFFER:
771 return true;
772 case GL_DRAW_FRAMEBUFFER:
773 return true;
774 default:
775 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500776 }
777}
778
Corentin Wallez336129f2017-10-17 15:55:40 -0400779bool ValidBufferType(const ValidationContext *context, BufferBinding target)
Jamie Madill8c96d582014-03-05 15:01:23 -0500780{
781 switch (target)
782 {
Corentin Wallez336129f2017-10-17 15:55:40 -0400783 case BufferBinding::ElementArray:
784 case BufferBinding::Array:
He Yunchaoced53ae2016-11-29 15:00:51 +0800785 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -0500786
Corentin Wallez336129f2017-10-17 15:55:40 -0400787 case BufferBinding::PixelPack:
788 case BufferBinding::PixelUnpack:
He Yunchaoced53ae2016-11-29 15:00:51 +0800789 return (context->getExtensions().pixelBufferObject ||
790 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -0400791
Corentin Wallez336129f2017-10-17 15:55:40 -0400792 case BufferBinding::CopyRead:
793 case BufferBinding::CopyWrite:
794 case BufferBinding::TransformFeedback:
795 case BufferBinding::Uniform:
He Yunchaoced53ae2016-11-29 15:00:51 +0800796 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -0500797
Corentin Wallez336129f2017-10-17 15:55:40 -0400798 case BufferBinding::AtomicCounter:
799 case BufferBinding::ShaderStorage:
800 case BufferBinding::DrawIndirect:
801 case BufferBinding::DispatchIndirect:
He Yunchaoced53ae2016-11-29 15:00:51 +0800802 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -0400803
He Yunchaoced53ae2016-11-29 15:00:51 +0800804 default:
805 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -0500806 }
807}
808
Jamie Madillc29968b2016-01-20 11:17:23 -0500809bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400810{
Jamie Madillc29968b2016-01-20 11:17:23 -0500811 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400812 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -0400813 switch (target)
814 {
Jamie Madillc29968b2016-01-20 11:17:23 -0500815 case GL_TEXTURE_2D:
816 maxDimension = caps.max2DTextureSize;
817 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800818 case GL_TEXTURE_CUBE_MAP:
819 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
820 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
821 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
822 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
823 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
824 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
825 maxDimension = caps.maxCubeMapTextureSize;
826 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400827 case GL_TEXTURE_RECTANGLE_ANGLE:
828 return level == 0;
He Yunchaoced53ae2016-11-29 15:00:51 +0800829 case GL_TEXTURE_3D:
830 maxDimension = caps.max3DTextureSize;
831 break;
832 case GL_TEXTURE_2D_ARRAY:
833 maxDimension = caps.max2DTextureSize;
834 break;
He Yunchao11b038b2016-11-22 21:24:04 +0800835 case GL_TEXTURE_2D_MULTISAMPLE:
836 maxDimension = caps.max2DTextureSize;
837 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800838 default:
839 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400840 }
841
Brandon Jones6cad5662017-06-14 13:25:13 -0700842 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400843}
844
Brandon Jones6cad5662017-06-14 13:25:13 -0700845bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -0700846 GLenum target,
847 GLint level,
848 GLsizei width,
849 GLsizei height,
850 GLsizei depth,
851 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400852{
Brandon Jones6cad5662017-06-14 13:25:13 -0700853 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400854 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700855 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400856 return false;
857 }
Austin Kinross08528e12015-10-07 16:24:40 -0700858 // TexSubImage parameters can be NPOT without textureNPOT extension,
859 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500860 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500861 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500862 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400863 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400864 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700865 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400866 return false;
867 }
868
869 if (!ValidMipLevel(context, target, level))
870 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700871 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400872 return false;
873 }
874
875 return true;
876}
877
Geoff Lang0d8b7242015-09-09 14:56:53 -0400878bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
879{
880 // List of compressed format that require that the texture size is smaller than or a multiple of
881 // the compressed block size.
882 switch (internalFormat)
883 {
884 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
885 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
886 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
887 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langfff7a7d2017-06-02 10:39:17 -0400888 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
889 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
890 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
891 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
Minmin Gonge3939b92015-12-01 15:36:51 -0800892 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800893 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
894 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
895 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
896 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
897 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
898 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -0400899 return true;
900
901 default:
902 return false;
903 }
904}
905
Geoff Lang966c9402017-04-18 12:38:27 -0400906bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
907{
908 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
909 (size % blockSize == 0);
910}
911
Jamie Madillc29968b2016-01-20 11:17:23 -0500912bool ValidCompressedImageSize(const ValidationContext *context,
913 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400914 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500915 GLsizei width,
916 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400917{
Geoff Langca271392017-04-05 12:30:00 -0400918 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400919 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400920 {
921 return false;
922 }
923
Geoff Lang966c9402017-04-18 12:38:27 -0400924 if (width < 0 || height < 0)
925 {
926 return false;
927 }
928
929 if (CompressedTextureFormatRequiresExactSize(internalFormat))
930 {
931 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
932 // block size for level 0 but WebGL disallows this.
933 bool smallerThanBlockSizeAllowed =
934 level > 0 || !context->getExtensions().webglCompatibility;
935
936 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
937 smallerThanBlockSizeAllowed) ||
938 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
939 smallerThanBlockSizeAllowed))
940 {
941 return false;
942 }
943 }
944
945 return true;
946}
947
948bool ValidCompressedSubImageSize(const ValidationContext *context,
949 GLenum internalFormat,
950 GLint xoffset,
951 GLint yoffset,
952 GLsizei width,
953 GLsizei height,
954 size_t textureWidth,
955 size_t textureHeight)
956{
957 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
958 if (!formatInfo.compressed)
959 {
960 return false;
961 }
962
Geoff Lang44ff5a72017-02-03 15:15:43 -0500963 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400964 {
965 return false;
966 }
967
Geoff Lang0d8b7242015-09-09 14:56:53 -0400968 if (CompressedTextureFormatRequiresExactSize(internalFormat))
969 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500970 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400971 yoffset % formatInfo.compressedBlockHeight != 0)
972 {
973 return false;
974 }
975
976 // Allowed to either have data that is a multiple of block size or is smaller than the block
977 // size but fills the entire mip
978 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
979 static_cast<size_t>(width) == textureWidth &&
980 static_cast<size_t>(height) == textureHeight;
981 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
982 (height % formatInfo.compressedBlockHeight) == 0;
983 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400984 {
985 return false;
986 }
987 }
988
Geoff Langd4f180b2013-09-24 13:57:44 -0400989 return true;
990}
991
Geoff Langff5b2d52016-09-07 11:32:23 -0400992bool ValidImageDataSize(ValidationContext *context,
993 GLenum textureTarget,
994 GLsizei width,
995 GLsizei height,
996 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400997 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400998 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400999 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001000 GLsizei imageSize)
1001{
Corentin Wallez336129f2017-10-17 15:55:40 -04001002 gl::Buffer *pixelUnpackBuffer =
1003 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -04001004 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1005 {
1006 // Checks are not required
1007 return true;
1008 }
1009
1010 // ...the data would be unpacked from the buffer object such that the memory reads required
1011 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -04001012 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
1013 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -04001014 const gl::Extents size(width, height, depth);
1015 const auto &unpack = context->getGLState().getUnpackState();
1016
1017 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1018 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1019 if (endByteOrErr.isError())
1020 {
1021 context->handleError(endByteOrErr.getError());
1022 return false;
1023 }
1024
1025 GLuint endByte = endByteOrErr.getResult();
1026
1027 if (pixelUnpackBuffer)
1028 {
1029 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1030 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1031 checkedEndByte += checkedOffset;
1032
1033 if (!checkedEndByte.IsValid() ||
1034 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1035 {
1036 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001037 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04001038 return false;
1039 }
1040 }
1041 else
1042 {
1043 ASSERT(imageSize >= 0);
1044 if (pixels == nullptr && imageSize != 0)
1045 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001046 context->handleError(InvalidOperation()
1047 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001048 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001049 }
1050
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001051 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001052 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001053 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001054 return false;
1055 }
1056 }
1057
1058 return true;
1059}
1060
Geoff Lang37dde692014-01-31 16:34:54 -05001061bool ValidQueryType(const Context *context, GLenum queryType)
1062{
He Yunchaoced53ae2016-11-29 15:00:51 +08001063 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1064 "GL extension enums not equal.");
1065 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1066 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001067
1068 switch (queryType)
1069 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001070 case GL_ANY_SAMPLES_PASSED:
1071 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001072 return context->getClientMajorVersion() >= 3 ||
1073 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +08001074 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1075 return (context->getClientMajorVersion() >= 3);
1076 case GL_TIME_ELAPSED_EXT:
1077 return context->getExtensions().disjointTimerQuery;
1078 case GL_COMMANDS_COMPLETED_CHROMIUM:
1079 return context->getExtensions().syncQuery;
1080 default:
1081 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001082 }
1083}
1084
Geoff Lang2d62ab72017-03-23 16:54:40 -04001085bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
1086 GLenum type,
1087 GLboolean normalized,
1088 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001089 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001090 bool pureInteger)
1091{
1092 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001093 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1094 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1095 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1096 // parameter exceeds 255.
1097 constexpr GLsizei kMaxWebGLStride = 255;
1098 if (stride > kMaxWebGLStride)
1099 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001100 context->handleError(InvalidValue()
1101 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001102 return false;
1103 }
1104
1105 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1106 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1107 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1108 // or an INVALID_OPERATION error is generated.
1109 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1110 size_t typeSize = GetVertexFormatTypeSize(internalType);
1111
1112 ASSERT(isPow2(typeSize) && typeSize > 0);
1113 size_t sizeMask = (typeSize - 1);
1114 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1115 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001116 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001117 return false;
1118 }
1119
1120 if ((stride & sizeMask) != 0)
1121 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001122 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001123 return false;
1124 }
1125
1126 return true;
1127}
1128
Jamie Madillef300b12016-10-07 15:12:09 -04001129Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001130{
He Yunchaoced53ae2016-11-29 15:00:51 +08001131 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1132 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1133 // or program object and INVALID_OPERATION if the provided name identifies an object
1134 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001135
Dian Xiang769769a2015-09-09 15:20:08 -07001136 Program *validProgram = context->getProgram(id);
1137
1138 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001139 {
Dian Xiang769769a2015-09-09 15:20:08 -07001140 if (context->getShader(id))
1141 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001142 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001143 }
1144 else
1145 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001146 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001147 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001148 }
Dian Xiang769769a2015-09-09 15:20:08 -07001149
1150 return validProgram;
1151}
1152
Jamie Madillef300b12016-10-07 15:12:09 -04001153Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001154{
1155 // See ValidProgram for spec details.
1156
1157 Shader *validShader = context->getShader(id);
1158
1159 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001160 {
Dian Xiang769769a2015-09-09 15:20:08 -07001161 if (context->getProgram(id))
1162 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001163 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001164 }
1165 else
1166 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001167 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001168 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001169 }
Dian Xiang769769a2015-09-09 15:20:08 -07001170
1171 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001172}
1173
Geoff Langb1196682014-07-23 13:47:29 -04001174bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001175{
Geoff Langfa125c92017-10-24 13:01:46 -04001176 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001177 {
Geoff Langfa125c92017-10-24 13:01:46 -04001178 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1179 {
1180 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1181 return false;
1182 }
Jamie Madillb4472272014-07-03 10:38:55 -04001183
Geoff Langfa125c92017-10-24 13:01:46 -04001184 // Color attachment 0 is validated below because it is always valid
1185 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001186 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001187 {
Geoff Langfa125c92017-10-24 13:01:46 -04001188 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001189 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001190 }
1191 }
1192 else
1193 {
1194 switch (attachment)
1195 {
Geoff Langfa125c92017-10-24 13:01:46 -04001196 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001197 case GL_DEPTH_ATTACHMENT:
1198 case GL_STENCIL_ATTACHMENT:
1199 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001200
He Yunchaoced53ae2016-11-29 15:00:51 +08001201 case GL_DEPTH_STENCIL_ATTACHMENT:
1202 if (!context->getExtensions().webglCompatibility &&
1203 context->getClientMajorVersion() < 3)
1204 {
Geoff Langfa125c92017-10-24 13:01:46 -04001205 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001206 return false;
1207 }
1208 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001209
He Yunchaoced53ae2016-11-29 15:00:51 +08001210 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001211 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001212 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001213 }
1214 }
1215
1216 return true;
1217}
1218
Jamie Madille8fb6402017-02-14 17:56:40 -05001219bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001220 GLenum target,
1221 GLsizei samples,
1222 GLenum internalformat,
1223 GLsizei width,
1224 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001225{
1226 switch (target)
1227 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001228 case GL_RENDERBUFFER:
1229 break;
1230 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001231 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001232 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001233 }
1234
1235 if (width < 0 || height < 0 || samples < 0)
1236 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001237 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001238 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001239 }
1240
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001241 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1242 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1243
1244 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001245 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001246 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001247 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001248 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001249 }
1250
1251 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1252 // 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 -08001253 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001254 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1255 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001256 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001257 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001258 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001259 }
1260
Geoff Langaae65a42014-05-26 12:43:44 -04001261 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001262 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001263 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001264 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001265 }
1266
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001267 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001268 if (handle == 0)
1269 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001270 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001271 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001272 }
1273
1274 return true;
1275}
1276
He Yunchaoced53ae2016-11-29 15:00:51 +08001277bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1278 GLenum target,
1279 GLenum attachment,
1280 GLenum renderbuffertarget,
1281 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001282{
Shannon Woods1da3cf62014-06-27 15:32:23 -04001283 if (!ValidFramebufferTarget(target))
1284 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001285 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001286 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001287 }
1288
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001289 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001290
Jamie Madill84115c92015-04-23 15:00:07 -04001291 ASSERT(framebuffer);
1292 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001293 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001294 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001295 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001296 }
1297
Jamie Madillb4472272014-07-03 10:38:55 -04001298 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001299 {
Jamie Madillb4472272014-07-03 10:38:55 -04001300 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001301 }
1302
Jamie Madillab9d82c2014-01-21 16:38:14 -05001303 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1304 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1305 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1306 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1307 if (renderbuffer != 0)
1308 {
1309 if (!context->getRenderbuffer(renderbuffer))
1310 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001311 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001312 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001313 }
1314 }
1315
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001316 return true;
1317}
1318
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001319bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001320 GLint srcX0,
1321 GLint srcY0,
1322 GLint srcX1,
1323 GLint srcY1,
1324 GLint dstX0,
1325 GLint dstY0,
1326 GLint dstX1,
1327 GLint dstY1,
1328 GLbitfield mask,
1329 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001330{
1331 switch (filter)
1332 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001333 case GL_NEAREST:
1334 break;
1335 case GL_LINEAR:
1336 break;
1337 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001338 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001339 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001340 }
1341
1342 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1343 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001344 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001345 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001346 }
1347
1348 if (mask == 0)
1349 {
1350 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1351 // buffers are copied.
1352 return false;
1353 }
1354
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001355 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1356 // color buffer, leaving only nearest being unfiltered from above
1357 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1358 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001359 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001360 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001361 }
1362
Jamie Madill51f40ec2016-06-15 14:06:00 -04001363 const auto &glState = context->getGLState();
1364 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1365 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001366
1367 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001368 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001369 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001370 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001371 }
1372
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001373 if (readFramebuffer->id() == drawFramebuffer->id())
1374 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001375 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001376 return false;
1377 }
1378
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001379 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001380 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001381 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001382 return false;
1383 }
1384
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001385 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001386 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001387 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001388 return false;
1389 }
1390
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001391 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001392 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001393 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001394 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001395 }
1396
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001397 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1398
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001399 if (mask & GL_COLOR_BUFFER_BIT)
1400 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001401 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001402 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001403
He Yunchao66a41a22016-12-15 16:45:05 +08001404 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001405 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001406 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001407
Geoff Langa15472a2015-08-11 11:48:03 -04001408 for (size_t drawbufferIdx = 0;
1409 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001410 {
Geoff Langa15472a2015-08-11 11:48:03 -04001411 const FramebufferAttachment *attachment =
1412 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1413 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001414 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001415 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001416
Geoff Langb2f3d052013-08-13 12:49:27 -04001417 // The GL ES 3.0.2 spec (pg 193) states that:
1418 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001419 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1420 // as well
1421 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1422 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001423 // Changes with EXT_color_buffer_float:
1424 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001425 GLenum readComponentType = readFormat.info->componentType;
1426 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001427 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001428 readComponentType == GL_SIGNED_NORMALIZED);
1429 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1430 drawComponentType == GL_SIGNED_NORMALIZED);
1431
1432 if (extensions.colorBufferFloat)
1433 {
1434 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1435 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1436
1437 if (readFixedOrFloat != drawFixedOrFloat)
1438 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001439 context->handleError(InvalidOperation()
1440 << "If the read buffer contains fixed-point or "
1441 "floating-point values, the draw buffer must "
1442 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001443 return false;
1444 }
1445 }
1446 else if (readFixedPoint != drawFixedPoint)
1447 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001448 context->handleError(InvalidOperation()
1449 << "If the read buffer contains fixed-point values, "
1450 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001451 return false;
1452 }
1453
1454 if (readComponentType == GL_UNSIGNED_INT &&
1455 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001456 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001457 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001458 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001459 }
1460
Jamie Madill6163c752015-12-07 16:32:59 -05001461 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001463 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001464 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001465 }
1466
Jamie Madilla3944d42016-07-22 22:13:26 -04001467 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001468 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001469 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001470 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001471 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001472 }
Geoff Lange4915782017-04-12 15:19:07 -04001473
1474 if (context->getExtensions().webglCompatibility &&
1475 *readColorBuffer == *attachment)
1476 {
1477 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001478 InvalidOperation()
1479 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001480 return false;
1481 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001482 }
1483 }
1484
Jamie Madilla3944d42016-07-22 22:13:26 -04001485 if ((readFormat.info->componentType == GL_INT ||
1486 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1487 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001488 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001489 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001490 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001491 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001492 }
He Yunchao66a41a22016-12-15 16:45:05 +08001493 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1494 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1495 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1496 // situation is an application error that would lead to a crash in ANGLE.
1497 else if (drawFramebuffer->hasEnabledDrawBuffer())
1498 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001499 context->handleError(
1500 InvalidOperation()
1501 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001502 return false;
1503 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001504 }
1505
He Yunchaoced53ae2016-11-29 15:00:51 +08001506 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001507 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1508 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001509 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001510 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001511 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001512 const gl::FramebufferAttachment *readBuffer =
1513 readFramebuffer->getAttachment(attachments[i]);
1514 const gl::FramebufferAttachment *drawBuffer =
1515 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001516
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001517 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001518 {
Kenneth Russell69382852017-07-21 16:38:44 -04001519 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001521 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001522 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001523 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001524
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001525 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001526 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001527 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001528 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001529 }
Geoff Lange4915782017-04-12 15:19:07 -04001530
1531 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1532 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001533 context->handleError(
1534 InvalidOperation()
1535 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001536 return false;
1537 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001538 }
He Yunchao66a41a22016-12-15 16:45:05 +08001539 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1540 else if (drawBuffer)
1541 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001542 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1543 "depth/stencil attachment of a "
1544 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001545 return false;
1546 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001547 }
1548 }
1549
Martin Radeva3ed4572017-07-27 18:29:37 +03001550 // ANGLE_multiview, Revision 1:
1551 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1552 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1553 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1554 {
1555 context->handleError(InvalidFramebufferOperation()
1556 << "Attempt to read from a multi-view framebuffer.");
1557 return false;
1558 }
1559 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1560 {
1561 context->handleError(InvalidFramebufferOperation()
1562 << "Attempt to write to a multi-view framebuffer.");
1563 return false;
1564 }
1565
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001566 return true;
1567}
1568
Jamie Madill4928b7c2017-06-20 12:57:39 -04001569bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001570 GLint x,
1571 GLint y,
1572 GLsizei width,
1573 GLsizei height,
1574 GLenum format,
1575 GLenum type,
1576 GLsizei bufSize,
1577 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001578 GLsizei *columns,
1579 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001580 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001581{
1582 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001583 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001584 return false;
1585 }
1586
Geoff Lang62fce5b2016-09-30 10:46:35 -04001587 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001588 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001589 {
Geoff Langb1196682014-07-23 13:47:29 -04001590 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001591 }
1592
Geoff Lang62fce5b2016-09-30 10:46:35 -04001593 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001594 {
Geoff Langb1196682014-07-23 13:47:29 -04001595 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001596 }
1597
Jamie Madillc29968b2016-01-20 11:17:23 -05001598 return true;
1599}
1600
1601bool ValidateReadnPixelsEXT(Context *context,
1602 GLint x,
1603 GLint y,
1604 GLsizei width,
1605 GLsizei height,
1606 GLenum format,
1607 GLenum type,
1608 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001609 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001610{
1611 if (bufSize < 0)
1612 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001613 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001614 return false;
1615 }
1616
Geoff Lang62fce5b2016-09-30 10:46:35 -04001617 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001618 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001619}
Jamie Madill26e91952014-03-05 15:01:27 -05001620
Jamie Madill4928b7c2017-06-20 12:57:39 -04001621bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001622 GLint x,
1623 GLint y,
1624 GLsizei width,
1625 GLsizei height,
1626 GLenum format,
1627 GLenum type,
1628 GLsizei bufSize,
1629 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001630 GLsizei *columns,
1631 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001632 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001633{
1634 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001635 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001636 return false;
1637 }
1638
Geoff Lange93daba2017-03-30 13:54:40 -04001639 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1640 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001641 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001642 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001643 }
1644
Geoff Lang62fce5b2016-09-30 10:46:35 -04001645 if (!ValidateRobustBufferSize(context, bufSize, *length))
1646 {
1647 return false;
1648 }
1649
1650 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001651}
1652
Jamie Madillf0e04492017-08-26 15:28:42 -04001653bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, 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 ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001666{
1667 if (!context->getExtensions().occlusionQueryBoolean &&
1668 !context->getExtensions().disjointTimerQuery)
1669 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001670 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001671 return false;
1672 }
1673
Olli Etuaho41997e72016-03-10 13:38:39 +02001674 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001675}
1676
Jamie Madillf0e04492017-08-26 15:28:42 -04001677bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1678{
1679 if (!context->getExtensions().occlusionQueryBoolean &&
1680 !context->getExtensions().disjointTimerQuery)
1681 {
1682 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1683 return false;
1684 }
1685
1686 return true;
1687}
1688
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001689bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001690{
1691 if (!ValidQueryType(context, target))
1692 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001693 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001694 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001695 }
1696
1697 if (id == 0)
1698 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001699 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001700 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001701 }
1702
1703 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1704 // of zero, if the active query object name for <target> is non-zero (for the
1705 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1706 // the active query for either target is non-zero), if <id> is the name of an
1707 // existing query object whose type does not match <target>, or if <id> is the
1708 // active query object name for any query type, the error INVALID_OPERATION is
1709 // generated.
1710
1711 // Ensure no other queries are active
1712 // NOTE: If other queries than occlusion are supported, we will need to check
1713 // separately that:
1714 // a) The query ID passed is not the current active query for any target/type
1715 // b) There are no active queries for the requested target (and in the case
1716 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1717 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001718
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001719 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001720 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001721 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001722 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001723 }
1724
1725 Query *queryObject = context->getQuery(id, true, target);
1726
1727 // check that name was obtained with glGenQueries
1728 if (!queryObject)
1729 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001730 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001731 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001732 }
1733
1734 // check for type mismatch
1735 if (queryObject->getType() != target)
1736 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001737 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001738 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001739 }
1740
1741 return true;
1742}
1743
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001744bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1745{
1746 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001747 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001748 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001749 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001750 return false;
1751 }
1752
1753 return ValidateBeginQueryBase(context, target, id);
1754}
1755
1756bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001757{
1758 if (!ValidQueryType(context, target))
1759 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001760 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001761 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001762 }
1763
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001764 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001765
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001766 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001767 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001768 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001769 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001770 }
1771
Jamie Madill45c785d2014-05-13 14:09:34 -04001772 return true;
1773}
1774
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001775bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1776{
1777 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001778 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001779 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001780 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001781 return false;
1782 }
1783
1784 return ValidateEndQueryBase(context, target);
1785}
1786
1787bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1788{
1789 if (!context->getExtensions().disjointTimerQuery)
1790 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001791 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001792 return false;
1793 }
1794
1795 if (target != GL_TIMESTAMP_EXT)
1796 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001797 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001798 return false;
1799 }
1800
1801 Query *queryObject = context->getQuery(id, true, target);
1802 if (queryObject == nullptr)
1803 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001804 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001805 return false;
1806 }
1807
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001808 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001809 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001810 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001811 return false;
1812 }
1813
1814 return true;
1815}
1816
Geoff Lang2186c382016-10-14 10:54:54 -04001817bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001818{
Geoff Lang2186c382016-10-14 10:54:54 -04001819 if (numParams)
1820 {
1821 *numParams = 0;
1822 }
1823
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001824 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1825 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001826 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001827 return false;
1828 }
1829
1830 switch (pname)
1831 {
1832 case GL_CURRENT_QUERY_EXT:
1833 if (target == GL_TIMESTAMP_EXT)
1834 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001835 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001836 return false;
1837 }
1838 break;
1839 case GL_QUERY_COUNTER_BITS_EXT:
1840 if (!context->getExtensions().disjointTimerQuery ||
1841 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1842 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001843 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001844 return false;
1845 }
1846 break;
1847 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001848 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001849 return false;
1850 }
1851
Geoff Lang2186c382016-10-14 10:54:54 -04001852 if (numParams)
1853 {
1854 // All queries return only one value
1855 *numParams = 1;
1856 }
1857
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001858 return true;
1859}
1860
1861bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1862{
1863 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001864 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001865 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001866 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001867 return false;
1868 }
1869
Geoff Lang2186c382016-10-14 10:54:54 -04001870 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001871}
1872
Geoff Lang2186c382016-10-14 10:54:54 -04001873bool ValidateGetQueryivRobustANGLE(Context *context,
1874 GLenum target,
1875 GLenum pname,
1876 GLsizei bufSize,
1877 GLsizei *length,
1878 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001879{
Geoff Lang2186c382016-10-14 10:54:54 -04001880 if (!ValidateRobustEntryPoint(context, bufSize))
1881 {
1882 return false;
1883 }
1884
1885 if (!ValidateGetQueryivBase(context, target, pname, length))
1886 {
1887 return false;
1888 }
1889
1890 if (!ValidateRobustBufferSize(context, bufSize, *length))
1891 {
1892 return false;
1893 }
1894
1895 return true;
1896}
1897
1898bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1899{
1900 if (numParams)
1901 {
1902 *numParams = 0;
1903 }
1904
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001905 Query *queryObject = context->getQuery(id, false, GL_NONE);
1906
1907 if (!queryObject)
1908 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001909 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001910 return false;
1911 }
1912
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001913 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001914 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001915 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001916 return false;
1917 }
1918
1919 switch (pname)
1920 {
1921 case GL_QUERY_RESULT_EXT:
1922 case GL_QUERY_RESULT_AVAILABLE_EXT:
1923 break;
1924
1925 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001926 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001927 return false;
1928 }
1929
Geoff Lang2186c382016-10-14 10:54:54 -04001930 if (numParams)
1931 {
1932 *numParams = 1;
1933 }
1934
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001935 return true;
1936}
1937
1938bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1939{
1940 if (!context->getExtensions().disjointTimerQuery)
1941 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001942 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001943 return false;
1944 }
Geoff Lang2186c382016-10-14 10:54:54 -04001945 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1946}
1947
1948bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1949 GLuint id,
1950 GLenum pname,
1951 GLsizei bufSize,
1952 GLsizei *length,
1953 GLint *params)
1954{
1955 if (!context->getExtensions().disjointTimerQuery)
1956 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001957 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001958 return false;
1959 }
1960
1961 if (!ValidateRobustEntryPoint(context, bufSize))
1962 {
1963 return false;
1964 }
1965
1966 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1967 {
1968 return false;
1969 }
1970
1971 if (!ValidateRobustBufferSize(context, bufSize, *length))
1972 {
1973 return false;
1974 }
1975
1976 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001977}
1978
1979bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1980{
1981 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001982 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001983 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001984 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001985 return false;
1986 }
Geoff Lang2186c382016-10-14 10:54:54 -04001987 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1988}
1989
1990bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1991 GLuint id,
1992 GLenum pname,
1993 GLsizei bufSize,
1994 GLsizei *length,
1995 GLuint *params)
1996{
1997 if (!context->getExtensions().disjointTimerQuery &&
1998 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1999 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002000 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002001 return false;
2002 }
2003
2004 if (!ValidateRobustEntryPoint(context, bufSize))
2005 {
2006 return false;
2007 }
2008
2009 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2010 {
2011 return false;
2012 }
2013
2014 if (!ValidateRobustBufferSize(context, bufSize, *length))
2015 {
2016 return false;
2017 }
2018
2019 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002020}
2021
2022bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2023{
2024 if (!context->getExtensions().disjointTimerQuery)
2025 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002026 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002027 return false;
2028 }
Geoff Lang2186c382016-10-14 10:54:54 -04002029 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2030}
2031
2032bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2033 GLuint id,
2034 GLenum pname,
2035 GLsizei bufSize,
2036 GLsizei *length,
2037 GLint64 *params)
2038{
2039 if (!context->getExtensions().disjointTimerQuery)
2040 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002041 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002042 return false;
2043 }
2044
2045 if (!ValidateRobustEntryPoint(context, bufSize))
2046 {
2047 return false;
2048 }
2049
2050 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2051 {
2052 return false;
2053 }
2054
2055 if (!ValidateRobustBufferSize(context, bufSize, *length))
2056 {
2057 return false;
2058 }
2059
2060 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002061}
2062
2063bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2064{
2065 if (!context->getExtensions().disjointTimerQuery)
2066 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002067 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002068 return false;
2069 }
Geoff Lang2186c382016-10-14 10:54:54 -04002070 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2071}
2072
2073bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2074 GLuint id,
2075 GLenum pname,
2076 GLsizei bufSize,
2077 GLsizei *length,
2078 GLuint64 *params)
2079{
2080 if (!context->getExtensions().disjointTimerQuery)
2081 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002082 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002083 return false;
2084 }
2085
2086 if (!ValidateRobustEntryPoint(context, bufSize))
2087 {
2088 return false;
2089 }
2090
2091 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2092 {
2093 return false;
2094 }
2095
2096 if (!ValidateRobustBufferSize(context, bufSize, *length))
2097 {
2098 return false;
2099 }
2100
2101 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002102}
2103
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002104bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002105 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002106 GLuint program,
2107 GLint location,
2108 GLsizei count)
2109{
2110 // Check for ES31 program uniform entry points
2111 if (context->getClientVersion() < Version(3, 1))
2112 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002113 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002114 return false;
2115 }
2116
2117 const LinkedUniform *uniform = nullptr;
2118 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002119 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2120 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002121}
2122
Frank Henigmana98a6472017-02-02 21:38:32 -05002123bool ValidateProgramUniform1iv(gl::Context *context,
2124 GLuint program,
2125 GLint location,
2126 GLsizei count,
2127 const GLint *value)
2128{
2129 // Check for ES31 program uniform entry points
2130 if (context->getClientVersion() < Version(3, 1))
2131 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002132 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Frank Henigmana98a6472017-02-02 21:38:32 -05002133 return false;
2134 }
2135
2136 const LinkedUniform *uniform = nullptr;
2137 gl::Program *programObject = GetValidProgram(context, program);
2138 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2139 ValidateUniform1ivValue(context, uniform->type, count, value);
2140}
2141
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002142bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002143 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002144 GLuint program,
2145 GLint location,
2146 GLsizei count,
2147 GLboolean transpose)
2148{
2149 // Check for ES31 program uniform entry points
2150 if (context->getClientVersion() < Version(3, 1))
2151 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002152 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002153 return false;
2154 }
2155
2156 const LinkedUniform *uniform = nullptr;
2157 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002158 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2159 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002160}
2161
Jamie Madillc1d770e2017-04-13 17:31:24 -04002162bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002163{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002164 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002165 gl::Program *programObject = context->getGLState().getProgram();
2166 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2167 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002168}
2169
Jamie Madillbe849e42017-05-02 15:49:00 -04002170bool ValidateUniform1iv(ValidationContext *context,
2171 GLint location,
2172 GLsizei count,
2173 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002174{
2175 const LinkedUniform *uniform = nullptr;
2176 gl::Program *programObject = context->getGLState().getProgram();
2177 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2178 ValidateUniform1ivValue(context, uniform->type, count, value);
2179}
2180
Jamie Madillc1d770e2017-04-13 17:31:24 -04002181bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002182 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002183 GLint location,
2184 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002185 GLboolean transpose)
2186{
Martin Radev1be913c2016-07-11 17:59:16 +03002187 if (transpose != GL_FALSE && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002188 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002189 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002190 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002191 }
2192
Jamie Madill62d31cb2015-09-11 13:25:51 -04002193 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002194 gl::Program *programObject = context->getGLState().getProgram();
2195 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2196 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002197}
2198
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002199bool ValidateStateQuery(ValidationContext *context,
2200 GLenum pname,
2201 GLenum *nativeType,
2202 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002203{
2204 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2205 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002206 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002207 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002208 }
2209
Jamie Madill0af26e12015-03-05 19:54:33 -05002210 const Caps &caps = context->getCaps();
2211
Jamie Madill893ab082014-05-16 16:56:10 -04002212 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2213 {
2214 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2215
Jamie Madill0af26e12015-03-05 19:54:33 -05002216 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002217 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002218 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002219 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002220 }
2221 }
2222
2223 switch (pname)
2224 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002225 case GL_TEXTURE_BINDING_2D:
2226 case GL_TEXTURE_BINDING_CUBE_MAP:
2227 case GL_TEXTURE_BINDING_3D:
2228 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002229 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002230 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002231 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2232 if (!context->getExtensions().textureRectangle)
2233 {
2234 context->handleError(InvalidEnum()
2235 << "ANGLE_texture_rectangle extension not present");
2236 return false;
2237 }
2238 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002239 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2240 if (!context->getExtensions().eglStreamConsumerExternal &&
2241 !context->getExtensions().eglImageExternal)
2242 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002243 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2244 "nor GL_OES_EGL_image_external "
2245 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002246 return false;
2247 }
2248 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002249
He Yunchaoced53ae2016-11-29 15:00:51 +08002250 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2251 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002252 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002253 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2254 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002255 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002256 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002257 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002258 }
2259
Jamie Madill51f40ec2016-06-15 14:06:00 -04002260 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2261 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002262
2263 if (framebuffer->getReadBufferState() == GL_NONE)
2264 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002265 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002266 return false;
2267 }
2268
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002269 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002270 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002271 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002272 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002273 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002274 }
2275 }
2276 break;
2277
He Yunchaoced53ae2016-11-29 15:00:51 +08002278 default:
2279 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002280 }
2281
2282 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002283 if (*numParams == 0)
2284 {
2285 return false;
2286 }
2287
2288 return true;
2289}
2290
2291bool ValidateRobustStateQuery(ValidationContext *context,
2292 GLenum pname,
2293 GLsizei bufSize,
2294 GLenum *nativeType,
2295 unsigned int *numParams)
2296{
2297 if (!ValidateRobustEntryPoint(context, bufSize))
2298 {
2299 return false;
2300 }
2301
2302 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2303 {
2304 return false;
2305 }
2306
2307 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002308 {
2309 return false;
2310 }
2311
2312 return true;
2313}
2314
Jamie Madillc29968b2016-01-20 11:17:23 -05002315bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2316 GLenum target,
2317 GLint level,
2318 GLenum internalformat,
2319 bool isSubImage,
2320 GLint xoffset,
2321 GLint yoffset,
2322 GLint zoffset,
2323 GLint x,
2324 GLint y,
2325 GLsizei width,
2326 GLsizei height,
2327 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002328 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002329{
Brandon Jones6cad5662017-06-14 13:25:13 -07002330 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002331 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002332 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2333 return false;
2334 }
2335
2336 if (width < 0 || height < 0)
2337 {
2338 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002339 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002340 }
2341
He Yunchaoced53ae2016-11-29 15:00:51 +08002342 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2343 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002344 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002345 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002346 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002347 }
2348
2349 if (border != 0)
2350 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002351 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002352 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002353 }
2354
2355 if (!ValidMipLevel(context, target, level))
2356 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002357 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002358 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002359 }
2360
Jamie Madill51f40ec2016-06-15 14:06:00 -04002361 const auto &state = context->getGLState();
2362 auto readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002363 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002364 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002365 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002366 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002367 }
2368
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002369 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002371 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002372 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002373 }
2374
Martin Radev138064f2016-07-15 12:03:41 +03002375 if (readFramebuffer->getReadBufferState() == GL_NONE)
2376 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002377 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002378 return false;
2379 }
2380
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002381 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2382 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002383 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002384 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002385 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2386 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002387 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002388 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002389 return false;
2390 }
2391
Martin Radev04e2c3b2017-07-27 16:54:35 +03002392 // ANGLE_multiview spec, Revision 1:
2393 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2394 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2395 // is not NONE.
2396 if (source->getMultiviewLayout() != GL_NONE)
2397 {
2398 context->handleError(InvalidFramebufferOperation()
2399 << "The active read framebuffer object has multiview attachments.");
2400 return false;
2401 }
2402
Geoff Langaae65a42014-05-26 12:43:44 -04002403 const gl::Caps &caps = context->getCaps();
2404
Geoff Langaae65a42014-05-26 12:43:44 -04002405 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002406 switch (target)
2407 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002408 case GL_TEXTURE_2D:
2409 maxDimension = caps.max2DTextureSize;
2410 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002411
He Yunchaoced53ae2016-11-29 15:00:51 +08002412 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2413 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2414 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2415 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2416 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2417 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2418 maxDimension = caps.maxCubeMapTextureSize;
2419 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002420
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002421 case GL_TEXTURE_RECTANGLE_ANGLE:
2422 maxDimension = caps.maxRectangleTextureSize;
2423 break;
2424
He Yunchaoced53ae2016-11-29 15:00:51 +08002425 case GL_TEXTURE_2D_ARRAY:
2426 maxDimension = caps.max2DTextureSize;
2427 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002428
He Yunchaoced53ae2016-11-29 15:00:51 +08002429 case GL_TEXTURE_3D:
2430 maxDimension = caps.max3DTextureSize;
2431 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002432
He Yunchaoced53ae2016-11-29 15:00:51 +08002433 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002434 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002435 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002436 }
2437
Jamie Madillc29968b2016-01-20 11:17:23 -05002438 gl::Texture *texture =
2439 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002440 if (!texture)
2441 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002442 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002443 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002444 }
2445
Geoff Lang69cce582015-09-17 13:20:36 -04002446 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002447 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002448 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002449 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002450 }
2451
Geoff Langca271392017-04-05 12:30:00 -04002452 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002453 isSubImage ? *texture->getFormat(target, level).info
2454 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002455
Geoff Lang966c9402017-04-18 12:38:27 -04002456 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002457 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002458 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002459 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002460 }
2461
2462 if (isSubImage)
2463 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002464 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2465 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2466 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002467 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002468 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002469 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002470 }
2471 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002472 else
2473 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002474 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002475 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002476 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002477 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002478 }
2479
Geoff Langeb66a6e2016-10-31 13:06:12 -04002480 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002481 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002482 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002483 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002484 }
2485
2486 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002487 if (static_cast<int>(width) > maxLevelDimension ||
2488 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002489 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002490 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002491 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002492 }
2493 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002494
Jamie Madill0c8abca2016-07-22 20:21:26 -04002495 if (textureFormatOut)
2496 {
2497 *textureFormatOut = texture->getFormat(target, level);
2498 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002499
2500 // Detect texture copying feedback loops for WebGL.
2501 if (context->getExtensions().webglCompatibility)
2502 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002503 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002504 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002505 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002506 return false;
2507 }
2508 }
2509
Jamie Madill560a8d82014-05-21 13:06:20 -04002510 return true;
2511}
2512
Jiajia Qind9671222016-11-29 16:30:31 +08002513bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002514{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002515 switch (mode)
2516 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002517 case GL_POINTS:
2518 case GL_LINES:
2519 case GL_LINE_LOOP:
2520 case GL_LINE_STRIP:
2521 case GL_TRIANGLES:
2522 case GL_TRIANGLE_STRIP:
2523 case GL_TRIANGLE_FAN:
2524 break;
2525 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002526 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002527 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002528 }
2529
Jamie Madill250d33f2014-06-06 17:09:03 -04002530 if (count < 0)
2531 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002532 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002533 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002534 }
2535
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002536 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002537
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002538 const Extensions &extensions = context->getExtensions();
2539
2540 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2541 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2542 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2543 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002544 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002545 // Check for mapped buffers
2546 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002547 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002548 {
2549 context->handleError(InvalidOperation());
2550 return false;
2551 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002552 }
2553
Jamie Madillcbcde722017-01-06 14:50:00 -05002554 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2555 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002556 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002557 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002558 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002559 const FramebufferAttachment *dsAttachment =
2560 framebuffer->getStencilOrDepthStencilAttachment();
2561 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002562 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002563 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002564
2565 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2566 bool differentWritemasks =
2567 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2568 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2569 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2570 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2571
2572 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002573 {
Martin Radevffe754b2017-07-31 10:38:07 +03002574 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002575 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002576 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2577 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002578 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002579 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002580 return false;
2581 }
Jamie Madillac528012014-06-20 13:21:23 -04002582 }
2583
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002584 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002585 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002586 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002587 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002588 }
2589
Geoff Lang7dd2e102014-11-10 15:19:26 -05002590 gl::Program *program = state.getProgram();
2591 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002592 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002593 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002594 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002595 }
2596
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002597 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002598 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002599 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002600 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002601 }
2602
Martin Radevffe754b2017-07-31 10:38:07 +03002603 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002604 {
Martin Radevda8e2572017-09-12 17:21:16 +03002605 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002606 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002607 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002608 {
2609 context->handleError(InvalidOperation() << "The number of views in the active program "
2610 "and draw framebuffer does not match.");
2611 return false;
2612 }
Martin Radev7e69f762017-07-27 14:54:13 +03002613
2614 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2615 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2616 framebufferNumViews > 1)
2617 {
2618 context->handleError(InvalidOperation()
2619 << "There is an active transform feedback object "
2620 "when the number of views in the active draw "
2621 "framebuffer is greater than 1.");
2622 return false;
2623 }
Martin Radevffe754b2017-07-31 10:38:07 +03002624
2625 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2626 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2627 {
2628 context->handleError(InvalidOperation() << "There is an active query for target "
2629 "GL_TIME_ELAPSED_EXT when the number of "
2630 "views in the active draw framebuffer is "
2631 "greater than 1.");
2632 return false;
2633 }
Martin Radev7cf61662017-07-26 17:10:53 +03002634 }
2635
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002636 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002637 for (unsigned int uniformBlockIndex = 0;
2638 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002639 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002640 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002641 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002642 const OffsetBindingPointer<Buffer> &uniformBuffer =
2643 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002644
Geoff Lang5d124a62015-09-15 13:03:27 -04002645 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002646 {
2647 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002648 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002649 InvalidOperation()
2650 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002651 return false;
2652 }
2653
Geoff Lang5d124a62015-09-15 13:03:27 -04002654 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002655 if (uniformBufferSize == 0)
2656 {
2657 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002658 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002659 }
2660
Jamie Madill62d31cb2015-09-11 13:25:51 -04002661 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002662 {
2663 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002664 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002665 InvalidOperation()
2666 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002667 return false;
2668 }
2669 }
2670
Geoff Lange0cff192017-05-30 13:04:56 -04002671 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002672 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002673 {
Geoff Lange0cff192017-05-30 13:04:56 -04002674 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002675 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2676 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002677 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002678 return false;
2679 }
Geoff Lange0cff192017-05-30 13:04:56 -04002680
Geoff Lang9ab5b822017-05-30 16:19:23 -04002681 // Detect that the vertex shader input types match the attribute types
2682 if (!ValidateVertexShaderAttributeTypeMatch(context))
2683 {
2684 return false;
2685 }
2686
Geoff Lange0cff192017-05-30 13:04:56 -04002687 // Detect that the color buffer types match the fragment shader output types
2688 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2689 {
2690 return false;
2691 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002692 }
2693
Jamie Madill250d33f2014-06-06 17:09:03 -04002694 // No-op if zero count
2695 return (count > 0);
2696}
2697
Jamie Madillc1d770e2017-04-13 17:31:24 -04002698bool ValidateDrawArraysCommon(ValidationContext *context,
2699 GLenum mode,
2700 GLint first,
2701 GLsizei count,
2702 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002703{
Jamie Madillfd716582014-06-06 17:09:04 -04002704 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002705 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002706 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002707 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002708 }
2709
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002710 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002711 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002712 if (curTransformFeedback && curTransformFeedback->isActive() &&
2713 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002714 {
2715 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002716 // that does not match the current transform feedback object's draw mode (if transform
2717 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002718 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002719 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002720 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002721 }
2722
Jiajia Qind9671222016-11-29 16:30:31 +08002723 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002724 {
2725 return false;
2726 }
2727
Corentin Wallez71168a02016-12-19 15:11:18 -08002728 // Check the computation of maxVertex doesn't overflow.
2729 // - first < 0 or count < 0 have been checked as an error condition
2730 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2731 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2732 ASSERT(count > 0 && first >= 0);
2733 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2734 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002735 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002736 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002737 return false;
2738 }
2739
Corentin Wallez71168a02016-12-19 15:11:18 -08002740 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002741 {
2742 return false;
2743 }
2744
2745 return true;
2746}
2747
He Yunchaoced53ae2016-11-29 15:00:51 +08002748bool ValidateDrawArraysInstancedANGLE(Context *context,
2749 GLenum mode,
2750 GLint first,
2751 GLsizei count,
2752 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002753{
Geoff Lang63c5a592017-09-27 14:08:16 -04002754 if (!context->getExtensions().instancedArrays)
2755 {
2756 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2757 return false;
2758 }
2759
Corentin Wallez170efbf2017-05-02 13:45:01 -04002760 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002761 {
2762 return false;
2763 }
2764
Corentin Wallez0dc97812017-06-22 14:38:44 -04002765 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002766}
2767
Jiajia Qind9671222016-11-29 16:30:31 +08002768bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002769{
Jamie Madill250d33f2014-06-06 17:09:03 -04002770 switch (type)
2771 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002772 case GL_UNSIGNED_BYTE:
2773 case GL_UNSIGNED_SHORT:
2774 break;
2775 case GL_UNSIGNED_INT:
2776 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2777 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002778 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002779 return false;
2780 }
2781 break;
2782 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002783 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002784 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002785 }
2786
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002787 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002788
2789 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002790 if (curTransformFeedback && curTransformFeedback->isActive() &&
2791 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002792 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002793 // It is an invalid operation to call DrawElements, DrawRangeElements or
2794 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002795 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002796 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002797 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002798 }
2799
Jiajia Qind9671222016-11-29 16:30:31 +08002800 return true;
2801}
2802
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002803bool ValidateDrawElementsCommon(ValidationContext *context,
2804 GLenum mode,
2805 GLsizei count,
2806 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002807 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002808 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002809{
2810 if (!ValidateDrawElementsBase(context, type))
2811 return false;
2812
2813 const State &state = context->getGLState();
2814
Corentin Wallez170efbf2017-05-02 13:45:01 -04002815 if (!ValidateDrawBase(context, mode, count))
2816 {
2817 return false;
2818 }
2819
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002820 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2821 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2822 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2823 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002824 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002825 // Check for mapped buffers
2826 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002827 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002828 {
2829 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2830 return false;
2831 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002832 }
2833
He Yunchaoced53ae2016-11-29 15:00:51 +08002834 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002835 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002836
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002837 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2838
2839 if (context->getExtensions().webglCompatibility)
2840 {
2841 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2842 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2843 {
2844 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2845 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2846 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002847 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002848 return false;
2849 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002850
2851 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2852 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2853 // error is generated.
2854 if (reinterpret_cast<intptr_t>(indices) < 0)
2855 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002856 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002857 return false;
2858 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002859 }
2860
2861 if (context->getExtensions().webglCompatibility ||
2862 !context->getGLState().areClientArraysEnabled())
2863 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002864 if (!elementArrayBuffer && count > 0)
2865 {
2866 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2867 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2868 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002869 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002870 return false;
2871 }
2872 }
2873
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002874 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002875 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002876 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002877 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002878 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2879 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2880 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2881 constexpr uint64_t kMaxTypeSize = 8;
2882 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2883 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2884 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002885
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002886 uint64_t typeSize = typeBytes;
2887 uint64_t elementCount = static_cast<uint64_t>(count);
2888 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2889
2890 // Doing the multiplication here is overflow-safe
2891 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2892
2893 // The offset can be any value, check for overflows
2894 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2895 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002896 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002897 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002898 return false;
2899 }
2900
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002901 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2902 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002903 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002904 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002905 return false;
2906 }
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002907
Corentin Wallez487653b2017-09-01 17:17:55 -04002908 ASSERT(isPow2(typeSize) && typeSize > 0);
2909 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002910 {
2911 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
2912 return false;
2913 }
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002914 }
2915 else if (!indices)
2916 {
2917 // This is an application error that would normally result in a crash,
2918 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002919 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04002920 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002921 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002922 }
2923
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002924 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002925 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002926 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2927 // access is enabled.
2928 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2929 {
2930 return false;
2931 }
2932 }
2933 else
2934 {
2935 // Use the parameter buffer to retrieve and cache the index range.
2936 const auto &params = context->getParams<HasIndexRange>();
2937 const auto &indexRangeOpt = params.getIndexRange();
2938 if (!indexRangeOpt.valid())
2939 {
2940 // Unexpected error.
2941 return false;
2942 }
2943
2944 // If we use an index greater than our maximum supported index range, return an error.
2945 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2946 // return an error if possible here.
2947 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2948 {
2949 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2950 return false;
2951 }
2952
2953 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2954 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2955 {
2956 return false;
2957 }
2958
2959 // No op if there are no real indices in the index data (all are primitive restart).
2960 return (indexRangeOpt.value().vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002961 }
2962
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002963 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002964}
2965
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002966bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2967 GLenum mode,
2968 GLsizei count,
2969 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002970 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002971 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002972{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002973 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002974}
2975
Geoff Lang3edfe032015-09-04 16:38:24 -04002976bool ValidateDrawElementsInstancedANGLE(Context *context,
2977 GLenum mode,
2978 GLsizei count,
2979 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002980 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002981 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002982{
Geoff Lang63c5a592017-09-27 14:08:16 -04002983 if (!context->getExtensions().instancedArrays)
2984 {
2985 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2986 return false;
2987 }
2988
Corentin Wallez170efbf2017-05-02 13:45:01 -04002989 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002990 {
2991 return false;
2992 }
2993
Corentin Wallez0dc97812017-06-22 14:38:44 -04002994 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002995}
2996
He Yunchaoced53ae2016-11-29 15:00:51 +08002997bool ValidateFramebufferTextureBase(Context *context,
2998 GLenum target,
2999 GLenum attachment,
3000 GLuint texture,
3001 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003002{
Jamie Madill55ec3b12014-07-03 10:38:57 -04003003 if (!ValidFramebufferTarget(target))
3004 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003005 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003006 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003007 }
3008
3009 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003010 {
3011 return false;
3012 }
3013
Jamie Madill55ec3b12014-07-03 10:38:57 -04003014 if (texture != 0)
3015 {
3016 gl::Texture *tex = context->getTexture(texture);
3017
Jamie Madillbe849e42017-05-02 15:49:00 -04003018 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003019 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003020 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003021 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003022 }
3023
3024 if (level < 0)
3025 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003026 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003027 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003028 }
3029 }
3030
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003031 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003032 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003033
Jamie Madill84115c92015-04-23 15:00:07 -04003034 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003035 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003036 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003037 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003038 }
3039
3040 return true;
3041}
3042
Geoff Langb1196682014-07-23 13:47:29 -04003043bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003044{
3045 if (program == 0)
3046 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003047 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003048 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003049 }
3050
Dian Xiang769769a2015-09-09 15:20:08 -07003051 gl::Program *programObject = GetValidProgram(context, program);
3052 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003053 {
3054 return false;
3055 }
3056
Jamie Madill0063c512014-08-25 15:47:53 -04003057 if (!programObject || !programObject->isLinked())
3058 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003059 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003060 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003061 }
3062
Geoff Lang7dd2e102014-11-10 15:19:26 -05003063 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003064 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003065 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003066 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003067 }
3068
Jamie Madill0063c512014-08-25 15:47:53 -04003069 return true;
3070}
3071
Geoff Langf41d0ee2016-10-07 13:04:23 -04003072static bool ValidateSizedGetUniform(Context *context,
3073 GLuint program,
3074 GLint location,
3075 GLsizei bufSize,
3076 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003077{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003078 if (length)
3079 {
3080 *length = 0;
3081 }
3082
Jamie Madill78f41802014-08-25 15:47:55 -04003083 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003084 {
Jamie Madill78f41802014-08-25 15:47:55 -04003085 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003086 }
3087
Geoff Langf41d0ee2016-10-07 13:04:23 -04003088 if (bufSize < 0)
3089 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003090 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003091 return false;
3092 }
3093
Jamie Madilla502c742014-08-28 17:19:13 -04003094 gl::Program *programObject = context->getProgram(program);
3095 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003096
Jamie Madill78f41802014-08-25 15:47:55 -04003097 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003098 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003099 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003100 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003101 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003102 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003103 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003104 }
3105
Geoff Langf41d0ee2016-10-07 13:04:23 -04003106 if (length)
3107 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003108 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003109 }
3110
Jamie Madill0063c512014-08-25 15:47:53 -04003111 return true;
3112}
3113
He Yunchaoced53ae2016-11-29 15:00:51 +08003114bool ValidateGetnUniformfvEXT(Context *context,
3115 GLuint program,
3116 GLint location,
3117 GLsizei bufSize,
3118 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003119{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003120 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003121}
3122
He Yunchaoced53ae2016-11-29 15:00:51 +08003123bool ValidateGetnUniformivEXT(Context *context,
3124 GLuint program,
3125 GLint location,
3126 GLsizei bufSize,
3127 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003128{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003129 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3130}
3131
3132bool ValidateGetUniformfvRobustANGLE(Context *context,
3133 GLuint program,
3134 GLint location,
3135 GLsizei bufSize,
3136 GLsizei *length,
3137 GLfloat *params)
3138{
3139 if (!ValidateRobustEntryPoint(context, bufSize))
3140 {
3141 return false;
3142 }
3143
3144 // bufSize is validated in ValidateSizedGetUniform
3145 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3146}
3147
3148bool ValidateGetUniformivRobustANGLE(Context *context,
3149 GLuint program,
3150 GLint location,
3151 GLsizei bufSize,
3152 GLsizei *length,
3153 GLint *params)
3154{
3155 if (!ValidateRobustEntryPoint(context, bufSize))
3156 {
3157 return false;
3158 }
3159
3160 // bufSize is validated in ValidateSizedGetUniform
3161 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3162}
3163
3164bool ValidateGetUniformuivRobustANGLE(Context *context,
3165 GLuint program,
3166 GLint location,
3167 GLsizei bufSize,
3168 GLsizei *length,
3169 GLuint *params)
3170{
3171 if (!ValidateRobustEntryPoint(context, bufSize))
3172 {
3173 return false;
3174 }
3175
3176 if (context->getClientMajorVersion() < 3)
3177 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003178 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003179 return false;
3180 }
3181
3182 // bufSize is validated in ValidateSizedGetUniform
3183 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003184}
3185
He Yunchaoced53ae2016-11-29 15:00:51 +08003186bool ValidateDiscardFramebufferBase(Context *context,
3187 GLenum target,
3188 GLsizei numAttachments,
3189 const GLenum *attachments,
3190 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003191{
3192 if (numAttachments < 0)
3193 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003194 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003195 return false;
3196 }
3197
3198 for (GLsizei i = 0; i < numAttachments; ++i)
3199 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003200 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003201 {
3202 if (defaultFramebuffer)
3203 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003204 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003205 return false;
3206 }
3207
3208 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3209 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003210 context->handleError(InvalidOperation() << "Requested color attachment is "
3211 "greater than the maximum supported "
3212 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003213 return false;
3214 }
3215 }
3216 else
3217 {
3218 switch (attachments[i])
3219 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003220 case GL_DEPTH_ATTACHMENT:
3221 case GL_STENCIL_ATTACHMENT:
3222 case GL_DEPTH_STENCIL_ATTACHMENT:
3223 if (defaultFramebuffer)
3224 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003225 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3226 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003227 return false;
3228 }
3229 break;
3230 case GL_COLOR:
3231 case GL_DEPTH:
3232 case GL_STENCIL:
3233 if (!defaultFramebuffer)
3234 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003235 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3236 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003237 return false;
3238 }
3239 break;
3240 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003241 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003242 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003243 }
3244 }
3245 }
3246
3247 return true;
3248}
3249
Austin Kinross6ee1e782015-05-29 17:05:37 -07003250bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3251{
3252 // Note that debug marker calls must not set error state
3253
3254 if (length < 0)
3255 {
3256 return false;
3257 }
3258
3259 if (marker == nullptr)
3260 {
3261 return false;
3262 }
3263
3264 return true;
3265}
3266
3267bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3268{
3269 // Note that debug marker calls must not set error state
3270
3271 if (length < 0)
3272 {
3273 return false;
3274 }
3275
3276 if (length > 0 && marker == nullptr)
3277 {
3278 return false;
3279 }
3280
3281 return true;
3282}
3283
Geoff Langdcab33b2015-07-21 13:03:16 -04003284bool ValidateEGLImageTargetTexture2DOES(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 && !context->getExtensions().eglImageExternal)
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_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003297 if (!context->getExtensions().eglImage)
3298 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003299 context->handleError(InvalidEnum()
3300 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003301 }
3302 break;
3303
3304 case GL_TEXTURE_EXTERNAL_OES:
3305 if (!context->getExtensions().eglImageExternal)
3306 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003307 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3308 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003309 }
Geoff Langa8406172015-07-21 16:53:39 -04003310 break;
3311
3312 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003313 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003314 return false;
3315 }
3316
Jamie Madill61e16b42017-06-19 11:13:23 -04003317 ASSERT(context->getCurrentDisplay());
3318 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003319 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003320 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003321 return false;
3322 }
3323
3324 if (image->getSamples() > 0)
3325 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003326 context->handleError(InvalidOperation()
3327 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003328 return false;
3329 }
3330
Geoff Langca271392017-04-05 12:30:00 -04003331 const TextureCaps &textureCaps =
3332 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003333 if (!textureCaps.texturable)
3334 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003335 context->handleError(InvalidOperation()
3336 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003337 return false;
3338 }
3339
Geoff Langdcab33b2015-07-21 13:03:16 -04003340 return true;
3341}
3342
3343bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003344 GLenum target,
3345 egl::Image *image)
3346{
Geoff Langa8406172015-07-21 16:53:39 -04003347 if (!context->getExtensions().eglImage)
3348 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003349 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003350 return false;
3351 }
3352
3353 switch (target)
3354 {
3355 case GL_RENDERBUFFER:
3356 break;
3357
3358 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003359 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003360 return false;
3361 }
3362
Jamie Madill61e16b42017-06-19 11:13:23 -04003363 ASSERT(context->getCurrentDisplay());
3364 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003365 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003366 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003367 return false;
3368 }
3369
Geoff Langca271392017-04-05 12:30:00 -04003370 const TextureCaps &textureCaps =
3371 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003372 if (!textureCaps.renderable)
3373 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003374 context->handleError(InvalidOperation()
3375 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003376 return false;
3377 }
3378
Geoff Langdcab33b2015-07-21 13:03:16 -04003379 return true;
3380}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003381
3382bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3383{
Geoff Lang36167ab2015-12-07 10:27:14 -05003384 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003385 {
3386 // The default VAO should always exist
3387 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003388 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003389 return false;
3390 }
3391
3392 return true;
3393}
3394
Geoff Langc5629752015-12-07 16:29:04 -05003395bool ValidateProgramBinaryBase(Context *context,
3396 GLuint program,
3397 GLenum binaryFormat,
3398 const void *binary,
3399 GLint length)
3400{
3401 Program *programObject = GetValidProgram(context, program);
3402 if (programObject == nullptr)
3403 {
3404 return false;
3405 }
3406
3407 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3408 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3409 programBinaryFormats.end())
3410 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003411 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003412 return false;
3413 }
3414
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003415 if (context->hasActiveTransformFeedback(program))
3416 {
3417 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003418 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3419 "is associated with an active transform "
3420 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003421 return false;
3422 }
3423
Geoff Langc5629752015-12-07 16:29:04 -05003424 return true;
3425}
3426
3427bool ValidateGetProgramBinaryBase(Context *context,
3428 GLuint program,
3429 GLsizei bufSize,
3430 GLsizei *length,
3431 GLenum *binaryFormat,
3432 void *binary)
3433{
3434 Program *programObject = GetValidProgram(context, program);
3435 if (programObject == nullptr)
3436 {
3437 return false;
3438 }
3439
3440 if (!programObject->isLinked())
3441 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003442 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003443 return false;
3444 }
3445
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003446 if (context->getCaps().programBinaryFormats.empty())
3447 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003448 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003449 return false;
3450 }
3451
Geoff Langc5629752015-12-07 16:29:04 -05003452 return true;
3453}
Jamie Madillc29968b2016-01-20 11:17:23 -05003454
Jamie Madillc29968b2016-01-20 11:17:23 -05003455bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3456{
3457 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003458 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003459 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003460 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3461 return false;
3462 }
3463 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3464 {
3465 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003466 return false;
3467 }
3468
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003469 ASSERT(context->getGLState().getDrawFramebuffer());
3470 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003471 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3472
3473 // This should come first before the check for the default frame buffer
3474 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3475 // rather than INVALID_OPERATION
3476 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3477 {
3478 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3479
3480 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003481 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3482 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003483 {
3484 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003485 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3486 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3487 // 3.1 is still a bit ambiguous about the error, but future specs are
3488 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003489 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003490 return false;
3491 }
3492 else if (bufs[colorAttachment] >= maxColorAttachment)
3493 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003494 context->handleError(InvalidOperation()
3495 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003496 return false;
3497 }
3498 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3499 frameBufferId != 0)
3500 {
3501 // INVALID_OPERATION-GL is bound to buffer and ith argument
3502 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003503 context->handleError(InvalidOperation()
3504 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003505 return false;
3506 }
3507 }
3508
3509 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3510 // and n is not 1 or bufs is bound to value other than BACK and NONE
3511 if (frameBufferId == 0)
3512 {
3513 if (n != 1)
3514 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003515 context->handleError(InvalidOperation()
3516 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003517 return false;
3518 }
3519
3520 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3521 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003522 context->handleError(
3523 InvalidOperation()
3524 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003525 return false;
3526 }
3527 }
3528
3529 return true;
3530}
3531
Geoff Lang496c02d2016-10-20 11:38:11 -07003532bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003533 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003534 GLenum pname,
3535 GLsizei *length,
3536 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003537{
Geoff Lang496c02d2016-10-20 11:38:11 -07003538 if (length)
3539 {
3540 *length = 0;
3541 }
3542
3543 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3544 {
3545 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003546 InvalidOperation()
3547 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003548 return false;
3549 }
3550
Corentin Wallez336129f2017-10-17 15:55:40 -04003551 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003552 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003553 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003554 return false;
3555 }
3556
Geoff Lang496c02d2016-10-20 11:38:11 -07003557 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003558 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003559 case GL_BUFFER_MAP_POINTER:
3560 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003561
Geoff Lang496c02d2016-10-20 11:38:11 -07003562 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003563 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003564 return false;
3565 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003566
3567 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3568 // target bound to zero generate an INVALID_OPERATION error."
3569 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003570 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003571 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003572 context->handleError(InvalidOperation()
3573 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003574 return false;
3575 }
3576
Geoff Lang496c02d2016-10-20 11:38:11 -07003577 if (length)
3578 {
3579 *length = 1;
3580 }
3581
Olli Etuaho4f667482016-03-30 15:56:35 +03003582 return true;
3583}
3584
Corentin Wallez336129f2017-10-17 15:55:40 -04003585bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003586{
Corentin Wallez336129f2017-10-17 15:55:40 -04003587 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003588 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003589 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003590 return false;
3591 }
3592
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003593 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003594
3595 if (buffer == nullptr || !buffer->isMapped())
3596 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003597 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003598 return false;
3599 }
3600
3601 return true;
3602}
3603
3604bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003605 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003606 GLintptr offset,
3607 GLsizeiptr length,
3608 GLbitfield access)
3609{
Corentin Wallez336129f2017-10-17 15:55:40 -04003610 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003611 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003612 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003613 return false;
3614 }
3615
Brandon Jones6cad5662017-06-14 13:25:13 -07003616 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003617 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003618 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3619 return false;
3620 }
3621
3622 if (length < 0)
3623 {
3624 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003625 return false;
3626 }
3627
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003628 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003629
3630 if (!buffer)
3631 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003632 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003633 return false;
3634 }
3635
3636 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003637 CheckedNumeric<size_t> checkedOffset(offset);
3638 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003639
Jamie Madille2e406c2016-06-02 13:04:10 -04003640 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003641 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003642 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003643 return false;
3644 }
3645
3646 // Check for invalid bits in the mask
3647 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3648 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3649 GL_MAP_UNSYNCHRONIZED_BIT;
3650
3651 if (access & ~(allAccessBits))
3652 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003653 context->handleError(InvalidValue()
3654 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003655 return false;
3656 }
3657
3658 if (length == 0)
3659 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003660 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003661 return false;
3662 }
3663
3664 if (buffer->isMapped())
3665 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003666 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003667 return false;
3668 }
3669
3670 // Check for invalid bit combinations
3671 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3672 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003673 context->handleError(InvalidOperation()
3674 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003675 return false;
3676 }
3677
3678 GLbitfield writeOnlyBits =
3679 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3680
3681 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3682 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003683 context->handleError(InvalidOperation()
3684 << "Invalid access bits when mapping buffer for reading: 0x"
3685 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003686 return false;
3687 }
3688
3689 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3690 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003691 context->handleError(
3692 InvalidOperation()
3693 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003694 return false;
3695 }
Geoff Lang79f71042017-08-14 16:43:43 -04003696
3697 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003698}
3699
3700bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003701 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003702 GLintptr offset,
3703 GLsizeiptr length)
3704{
Brandon Jones6cad5662017-06-14 13:25:13 -07003705 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003706 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003707 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3708 return false;
3709 }
3710
3711 if (length < 0)
3712 {
3713 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003714 return false;
3715 }
3716
Corentin Wallez336129f2017-10-17 15:55:40 -04003717 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003718 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003719 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003720 return false;
3721 }
3722
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003723 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003724
3725 if (buffer == nullptr)
3726 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003727 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003728 return false;
3729 }
3730
3731 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3732 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003733 context->handleError(InvalidOperation()
3734 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003735 return false;
3736 }
3737
3738 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003739 CheckedNumeric<size_t> checkedOffset(offset);
3740 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003741
Jamie Madille2e406c2016-06-02 13:04:10 -04003742 if (!checkedSize.IsValid() ||
3743 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003744 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003745 context->handleError(InvalidValue()
3746 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003747 return false;
3748 }
3749
3750 return true;
3751}
3752
Olli Etuaho41997e72016-03-10 13:38:39 +02003753bool ValidateGenOrDelete(Context *context, GLint n)
3754{
3755 if (n < 0)
3756 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003757 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003758 return false;
3759 }
3760 return true;
3761}
3762
Geoff Langff5b2d52016-09-07 11:32:23 -04003763bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3764{
3765 if (!context->getExtensions().robustClientMemory)
3766 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003767 context->handleError(InvalidOperation()
3768 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003769 return false;
3770 }
3771
3772 if (bufSize < 0)
3773 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003774 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003775 return false;
3776 }
3777
3778 return true;
3779}
3780
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003781bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3782{
3783 if (bufSize < numParams)
3784 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003785 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3786 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003787 return false;
3788 }
3789
3790 return true;
3791}
3792
Jamie Madillbe849e42017-05-02 15:49:00 -04003793bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3794 GLenum target,
3795 GLenum attachment,
3796 GLenum pname,
3797 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003798{
Geoff Langff5b2d52016-09-07 11:32:23 -04003799 if (!ValidFramebufferTarget(target))
3800 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003801 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003802 return false;
3803 }
3804
3805 int clientVersion = context->getClientMajorVersion();
3806
3807 switch (pname)
3808 {
3809 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3810 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3811 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3812 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3813 break;
3814
Martin Radeve5285d22017-07-14 16:23:53 +03003815 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3816 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3817 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3818 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3819 if (clientVersion < 3 || !context->getExtensions().multiview)
3820 {
3821 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3822 return false;
3823 }
3824 break;
3825
Geoff Langff5b2d52016-09-07 11:32:23 -04003826 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3827 if (clientVersion < 3 && !context->getExtensions().sRGB)
3828 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003829 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003830 return false;
3831 }
3832 break;
3833
3834 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3835 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3836 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3837 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3838 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3839 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3840 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3841 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3842 if (clientVersion < 3)
3843 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003844 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003845 return false;
3846 }
3847 break;
3848
3849 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003850 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003851 return false;
3852 }
3853
3854 // Determine if the attachment is a valid enum
3855 switch (attachment)
3856 {
3857 case GL_BACK:
3858 case GL_FRONT:
3859 case GL_DEPTH:
3860 case GL_STENCIL:
3861 case GL_DEPTH_STENCIL_ATTACHMENT:
3862 if (clientVersion < 3)
3863 {
Geoff Langfa125c92017-10-24 13:01:46 -04003864 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003865 return false;
3866 }
3867 break;
3868
Geoff Langfa125c92017-10-24 13:01:46 -04003869 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003870 case GL_DEPTH_ATTACHMENT:
3871 case GL_STENCIL_ATTACHMENT:
3872 break;
3873
3874 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003875 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3876 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003877 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3878 {
Geoff Langfa125c92017-10-24 13:01:46 -04003879 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003880 return false;
3881 }
3882 break;
3883 }
3884
3885 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3886 ASSERT(framebuffer);
3887
3888 if (framebuffer->id() == 0)
3889 {
3890 if (clientVersion < 3)
3891 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003892 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003893 return false;
3894 }
3895
3896 switch (attachment)
3897 {
3898 case GL_BACK:
3899 case GL_DEPTH:
3900 case GL_STENCIL:
3901 break;
3902
3903 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003904 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003905 return false;
3906 }
3907 }
3908 else
3909 {
3910 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3911 {
3912 // Valid attachment query
3913 }
3914 else
3915 {
3916 switch (attachment)
3917 {
3918 case GL_DEPTH_ATTACHMENT:
3919 case GL_STENCIL_ATTACHMENT:
3920 break;
3921
3922 case GL_DEPTH_STENCIL_ATTACHMENT:
3923 if (!framebuffer->hasValidDepthStencil())
3924 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003925 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003926 return false;
3927 }
3928 break;
3929
3930 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003931 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003932 return false;
3933 }
3934 }
3935 }
3936
3937 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3938 if (attachmentObject)
3939 {
3940 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3941 attachmentObject->type() == GL_TEXTURE ||
3942 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3943
3944 switch (pname)
3945 {
3946 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3947 if (attachmentObject->type() != GL_RENDERBUFFER &&
3948 attachmentObject->type() != GL_TEXTURE)
3949 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003950 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003951 return false;
3952 }
3953 break;
3954
3955 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3956 if (attachmentObject->type() != GL_TEXTURE)
3957 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003958 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003959 return false;
3960 }
3961 break;
3962
3963 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3964 if (attachmentObject->type() != GL_TEXTURE)
3965 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003966 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003967 return false;
3968 }
3969 break;
3970
3971 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3972 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3973 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003974 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003975 return false;
3976 }
3977 break;
3978
3979 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3980 if (attachmentObject->type() != GL_TEXTURE)
3981 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003982 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003983 return false;
3984 }
3985 break;
3986
3987 default:
3988 break;
3989 }
3990 }
3991 else
3992 {
3993 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3994 // is NONE, then querying any other pname will generate INVALID_ENUM.
3995
3996 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3997 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3998 // INVALID_OPERATION for all other pnames
3999
4000 switch (pname)
4001 {
4002 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4003 break;
4004
4005 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4006 if (clientVersion < 3)
4007 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004008 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004009 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004010 return false;
4011 }
4012 break;
4013
4014 default:
4015 if (clientVersion < 3)
4016 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004017 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004018 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004019 return false;
4020 }
4021 else
4022 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004023 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004024 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004025 return false;
4026 }
4027 }
4028 }
4029
Martin Radeve5285d22017-07-14 16:23:53 +03004030 if (numParams)
4031 {
4032 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4033 {
4034 // Only when the viewport offsets are queried we can have a varying number of output
4035 // parameters.
4036 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4037 *numParams = numViews * 2;
4038 }
4039 else
4040 {
4041 // For all other queries we can have only one output parameter.
4042 *numParams = 1;
4043 }
4044 }
4045
Geoff Langff5b2d52016-09-07 11:32:23 -04004046 return true;
4047}
4048
4049bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4050 GLenum target,
4051 GLenum attachment,
4052 GLenum pname,
4053 GLsizei bufSize,
4054 GLsizei *numParams)
4055{
4056 if (!ValidateRobustEntryPoint(context, bufSize))
4057 {
4058 return false;
4059 }
4060
Jamie Madillbe849e42017-05-02 15:49:00 -04004061 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4062 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004063 {
4064 return false;
4065 }
4066
4067 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4068 {
4069 return false;
4070 }
4071
4072 return true;
4073}
4074
Geoff Langff5b2d52016-09-07 11:32:23 -04004075bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004076 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004077 GLenum pname,
4078 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004079 GLsizei *length,
4080 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004081{
4082 if (!ValidateRobustEntryPoint(context, bufSize))
4083 {
4084 return false;
4085 }
4086
Geoff Langebebe1c2016-10-14 12:01:31 -04004087 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004088 {
4089 return false;
4090 }
4091
Geoff Langebebe1c2016-10-14 12:01:31 -04004092 if (!ValidateRobustBufferSize(context, bufSize, *length))
4093 {
4094 return false;
4095 }
4096
4097 return true;
4098}
4099
Geoff Langebebe1c2016-10-14 12:01:31 -04004100bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004101 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004102 GLenum pname,
4103 GLsizei bufSize,
4104 GLsizei *length,
4105 GLint64 *params)
4106{
4107 if (!ValidateRobustEntryPoint(context, bufSize))
4108 {
4109 return false;
4110 }
4111
4112 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4113 {
4114 return false;
4115 }
4116
4117 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004118 {
4119 return false;
4120 }
4121
4122 return true;
4123}
4124
Jamie Madillbe849e42017-05-02 15:49:00 -04004125bool ValidateGetProgramivBase(ValidationContext *context,
4126 GLuint program,
4127 GLenum pname,
4128 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004129{
4130 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004131 if (numParams)
4132 {
4133 *numParams = 1;
4134 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004135
4136 Program *programObject = GetValidProgram(context, program);
4137 if (!programObject)
4138 {
4139 return false;
4140 }
4141
4142 switch (pname)
4143 {
4144 case GL_DELETE_STATUS:
4145 case GL_LINK_STATUS:
4146 case GL_VALIDATE_STATUS:
4147 case GL_INFO_LOG_LENGTH:
4148 case GL_ATTACHED_SHADERS:
4149 case GL_ACTIVE_ATTRIBUTES:
4150 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4151 case GL_ACTIVE_UNIFORMS:
4152 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4153 break;
4154
4155 case GL_PROGRAM_BINARY_LENGTH:
4156 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4157 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004158 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4159 "requires GL_OES_get_program_binary or "
4160 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004161 return false;
4162 }
4163 break;
4164
4165 case GL_ACTIVE_UNIFORM_BLOCKS:
4166 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4167 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4168 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4169 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4170 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4171 if (context->getClientMajorVersion() < 3)
4172 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004173 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004174 return false;
4175 }
4176 break;
4177
Yunchao He61afff12017-03-14 15:34:03 +08004178 case GL_PROGRAM_SEPARABLE:
Xinghua Cao971f8502017-10-17 13:01:24 +08004179 case GL_COMPUTE_WORK_GROUP_SIZE:
jchen1058f67be2017-10-27 08:59:27 +08004180 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004181 if (context->getClientVersion() < Version(3, 1))
4182 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004183 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004184 return false;
4185 }
4186 break;
4187
Geoff Langff5b2d52016-09-07 11:32:23 -04004188 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004189 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004190 return false;
4191 }
4192
4193 return true;
4194}
4195
4196bool ValidateGetProgramivRobustANGLE(Context *context,
4197 GLuint program,
4198 GLenum pname,
4199 GLsizei bufSize,
4200 GLsizei *numParams)
4201{
4202 if (!ValidateRobustEntryPoint(context, bufSize))
4203 {
4204 return false;
4205 }
4206
Jamie Madillbe849e42017-05-02 15:49:00 -04004207 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004208 {
4209 return false;
4210 }
4211
4212 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4213 {
4214 return false;
4215 }
4216
4217 return true;
4218}
4219
Geoff Lang740d9022016-10-07 11:20:52 -04004220bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4221 GLenum target,
4222 GLenum pname,
4223 GLsizei bufSize,
4224 GLsizei *length,
4225 GLint *params)
4226{
4227 if (!ValidateRobustEntryPoint(context, bufSize))
4228 {
4229 return false;
4230 }
4231
4232 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4233 {
4234 return false;
4235 }
4236
4237 if (!ValidateRobustBufferSize(context, bufSize, *length))
4238 {
4239 return false;
4240 }
4241
4242 return true;
4243}
4244
Geoff Langd7d0ed32016-10-07 11:33:51 -04004245bool ValidateGetShaderivRobustANGLE(Context *context,
4246 GLuint shader,
4247 GLenum pname,
4248 GLsizei bufSize,
4249 GLsizei *length,
4250 GLint *params)
4251{
4252 if (!ValidateRobustEntryPoint(context, bufSize))
4253 {
4254 return false;
4255 }
4256
4257 if (!ValidateGetShaderivBase(context, shader, pname, length))
4258 {
4259 return false;
4260 }
4261
4262 if (!ValidateRobustBufferSize(context, bufSize, *length))
4263 {
4264 return false;
4265 }
4266
4267 return true;
4268}
4269
Geoff Langc1984ed2016-10-07 12:41:00 -04004270bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4271 GLenum target,
4272 GLenum pname,
4273 GLsizei bufSize,
4274 GLsizei *length,
4275 GLfloat *params)
4276{
4277 if (!ValidateRobustEntryPoint(context, bufSize))
4278 {
4279 return false;
4280 }
4281
4282 if (!ValidateGetTexParameterBase(context, target, pname, length))
4283 {
4284 return false;
4285 }
4286
4287 if (!ValidateRobustBufferSize(context, bufSize, *length))
4288 {
4289 return false;
4290 }
4291
4292 return true;
4293}
4294
Geoff Langc1984ed2016-10-07 12:41:00 -04004295bool ValidateGetTexParameterivRobustANGLE(Context *context,
4296 GLenum target,
4297 GLenum pname,
4298 GLsizei bufSize,
4299 GLsizei *length,
4300 GLint *params)
4301{
4302 if (!ValidateRobustEntryPoint(context, bufSize))
4303 {
4304 return false;
4305 }
4306
4307 if (!ValidateGetTexParameterBase(context, target, pname, length))
4308 {
4309 return false;
4310 }
4311
4312 if (!ValidateRobustBufferSize(context, bufSize, *length))
4313 {
4314 return false;
4315 }
4316
4317 return true;
4318}
4319
Geoff Langc1984ed2016-10-07 12:41:00 -04004320bool ValidateTexParameterfvRobustANGLE(Context *context,
4321 GLenum target,
4322 GLenum pname,
4323 GLsizei bufSize,
4324 const GLfloat *params)
4325{
4326 if (!ValidateRobustEntryPoint(context, bufSize))
4327 {
4328 return false;
4329 }
4330
4331 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4332}
4333
Geoff Langc1984ed2016-10-07 12:41:00 -04004334bool ValidateTexParameterivRobustANGLE(Context *context,
4335 GLenum target,
4336 GLenum pname,
4337 GLsizei bufSize,
4338 const GLint *params)
4339{
4340 if (!ValidateRobustEntryPoint(context, bufSize))
4341 {
4342 return false;
4343 }
4344
4345 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4346}
4347
Geoff Langc1984ed2016-10-07 12:41:00 -04004348bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4349 GLuint sampler,
4350 GLenum pname,
4351 GLuint bufSize,
4352 GLsizei *length,
4353 GLfloat *params)
4354{
4355 if (!ValidateRobustEntryPoint(context, bufSize))
4356 {
4357 return false;
4358 }
4359
4360 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4361 {
4362 return false;
4363 }
4364
4365 if (!ValidateRobustBufferSize(context, bufSize, *length))
4366 {
4367 return false;
4368 }
4369
4370 return true;
4371}
4372
Geoff Langc1984ed2016-10-07 12:41:00 -04004373bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4374 GLuint sampler,
4375 GLenum pname,
4376 GLuint bufSize,
4377 GLsizei *length,
4378 GLint *params)
4379{
4380 if (!ValidateRobustEntryPoint(context, bufSize))
4381 {
4382 return false;
4383 }
4384
4385 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4386 {
4387 return false;
4388 }
4389
4390 if (!ValidateRobustBufferSize(context, bufSize, *length))
4391 {
4392 return false;
4393 }
4394
4395 return true;
4396}
4397
Geoff Langc1984ed2016-10-07 12:41:00 -04004398bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4399 GLuint sampler,
4400 GLenum pname,
4401 GLsizei bufSize,
4402 const GLfloat *params)
4403{
4404 if (!ValidateRobustEntryPoint(context, bufSize))
4405 {
4406 return false;
4407 }
4408
4409 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4410}
4411
Geoff Langc1984ed2016-10-07 12:41:00 -04004412bool ValidateSamplerParameterivRobustANGLE(Context *context,
4413 GLuint sampler,
4414 GLenum pname,
4415 GLsizei bufSize,
4416 const GLint *params)
4417{
4418 if (!ValidateRobustEntryPoint(context, bufSize))
4419 {
4420 return false;
4421 }
4422
4423 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4424}
4425
Geoff Lang0b031062016-10-13 14:30:04 -04004426bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4427 GLuint index,
4428 GLenum pname,
4429 GLsizei bufSize,
4430 GLsizei *length,
4431 GLfloat *params)
4432{
4433 if (!ValidateRobustEntryPoint(context, bufSize))
4434 {
4435 return false;
4436 }
4437
4438 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4439 {
4440 return false;
4441 }
4442
4443 if (!ValidateRobustBufferSize(context, bufSize, *length))
4444 {
4445 return false;
4446 }
4447
4448 return true;
4449}
4450
Geoff Lang0b031062016-10-13 14:30:04 -04004451bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4452 GLuint index,
4453 GLenum pname,
4454 GLsizei bufSize,
4455 GLsizei *length,
4456 GLint *params)
4457{
4458 if (!ValidateRobustEntryPoint(context, bufSize))
4459 {
4460 return false;
4461 }
4462
4463 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4464 {
4465 return false;
4466 }
4467
4468 if (!ValidateRobustBufferSize(context, bufSize, *length))
4469 {
4470 return false;
4471 }
4472
4473 return true;
4474}
4475
Geoff Lang0b031062016-10-13 14:30:04 -04004476bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4477 GLuint index,
4478 GLenum pname,
4479 GLsizei bufSize,
4480 GLsizei *length,
4481 void **pointer)
4482{
4483 if (!ValidateRobustEntryPoint(context, bufSize))
4484 {
4485 return false;
4486 }
4487
4488 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4489 {
4490 return false;
4491 }
4492
4493 if (!ValidateRobustBufferSize(context, bufSize, *length))
4494 {
4495 return false;
4496 }
4497
4498 return true;
4499}
4500
Geoff Lang0b031062016-10-13 14:30:04 -04004501bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4502 GLuint index,
4503 GLenum pname,
4504 GLsizei bufSize,
4505 GLsizei *length,
4506 GLint *params)
4507{
4508 if (!ValidateRobustEntryPoint(context, bufSize))
4509 {
4510 return false;
4511 }
4512
4513 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4514 {
4515 return false;
4516 }
4517
4518 if (!ValidateRobustBufferSize(context, bufSize, *length))
4519 {
4520 return false;
4521 }
4522
4523 return true;
4524}
4525
Geoff Lang0b031062016-10-13 14:30:04 -04004526bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4527 GLuint index,
4528 GLenum pname,
4529 GLsizei bufSize,
4530 GLsizei *length,
4531 GLuint *params)
4532{
4533 if (!ValidateRobustEntryPoint(context, bufSize))
4534 {
4535 return false;
4536 }
4537
4538 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4539 {
4540 return false;
4541 }
4542
4543 if (!ValidateRobustBufferSize(context, bufSize, *length))
4544 {
4545 return false;
4546 }
4547
4548 return true;
4549}
4550
Geoff Lang6899b872016-10-14 11:30:13 -04004551bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4552 GLuint program,
4553 GLuint uniformBlockIndex,
4554 GLenum pname,
4555 GLsizei bufSize,
4556 GLsizei *length,
4557 GLint *params)
4558{
4559 if (!ValidateRobustEntryPoint(context, bufSize))
4560 {
4561 return false;
4562 }
4563
4564 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4565 {
4566 return false;
4567 }
4568
4569 if (!ValidateRobustBufferSize(context, bufSize, *length))
4570 {
4571 return false;
4572 }
4573
4574 return true;
4575}
4576
Geoff Lang0a9661f2016-10-20 10:59:20 -07004577bool ValidateGetInternalFormativRobustANGLE(Context *context,
4578 GLenum target,
4579 GLenum internalformat,
4580 GLenum pname,
4581 GLsizei bufSize,
4582 GLsizei *length,
4583 GLint *params)
4584{
4585 if (!ValidateRobustEntryPoint(context, bufSize))
4586 {
4587 return false;
4588 }
4589
4590 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4591 {
4592 return false;
4593 }
4594
4595 if (!ValidateRobustBufferSize(context, bufSize, *length))
4596 {
4597 return false;
4598 }
4599
4600 return true;
4601}
4602
Shao80957d92017-02-20 21:25:59 +08004603bool ValidateVertexFormatBase(ValidationContext *context,
4604 GLuint attribIndex,
4605 GLint size,
4606 GLenum type,
4607 GLboolean pureInteger)
4608{
4609 const Caps &caps = context->getCaps();
4610 if (attribIndex >= caps.maxVertexAttributes)
4611 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004612 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004613 return false;
4614 }
4615
4616 if (size < 1 || size > 4)
4617 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004618 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004619 return false;
Shao80957d92017-02-20 21:25:59 +08004620 }
4621
4622 switch (type)
4623 {
4624 case GL_BYTE:
4625 case GL_UNSIGNED_BYTE:
4626 case GL_SHORT:
4627 case GL_UNSIGNED_SHORT:
4628 break;
4629
4630 case GL_INT:
4631 case GL_UNSIGNED_INT:
4632 if (context->getClientMajorVersion() < 3)
4633 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004634 context->handleError(InvalidEnum()
4635 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004636 return false;
4637 }
4638 break;
4639
4640 case GL_FIXED:
4641 case GL_FLOAT:
4642 if (pureInteger)
4643 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004644 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004645 return false;
4646 }
4647 break;
4648
4649 case GL_HALF_FLOAT:
4650 if (context->getClientMajorVersion() < 3)
4651 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004652 context->handleError(InvalidEnum()
4653 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004654 return false;
4655 }
4656 if (pureInteger)
4657 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004658 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004659 return false;
4660 }
4661 break;
4662
4663 case GL_INT_2_10_10_10_REV:
4664 case GL_UNSIGNED_INT_2_10_10_10_REV:
4665 if (context->getClientMajorVersion() < 3)
4666 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004667 context->handleError(InvalidEnum()
4668 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004669 return false;
4670 }
4671 if (pureInteger)
4672 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004673 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004674 return false;
4675 }
4676 if (size != 4)
4677 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004678 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4679 "UNSIGNED_INT_2_10_10_10_REV and "
4680 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004681 return false;
4682 }
4683 break;
4684
4685 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004686 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004687 return false;
4688 }
4689
4690 return true;
4691}
4692
Geoff Lang76e65652017-03-27 14:58:02 -04004693// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4694// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4695// specified clear value and the type of a buffer that is being cleared generates an
4696// INVALID_OPERATION error instead of producing undefined results
4697bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4698 GLint drawbuffer,
4699 const GLenum *validComponentTypes,
4700 size_t validComponentTypeCount)
4701{
4702 const FramebufferAttachment *attachment =
4703 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4704 if (attachment)
4705 {
4706 GLenum componentType = attachment->getFormat().info->componentType;
4707 const GLenum *end = validComponentTypes + validComponentTypeCount;
4708 if (std::find(validComponentTypes, end, componentType) == end)
4709 {
4710 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004711 InvalidOperation()
4712 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004713 return false;
4714 }
4715 }
4716
4717 return true;
4718}
4719
Corentin Wallezb2931602017-04-11 15:58:57 -04004720bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4721 GLsizei imageSize,
4722 GLsizei dataSize)
4723{
4724 if (!ValidateRobustEntryPoint(context, dataSize))
4725 {
4726 return false;
4727 }
4728
Corentin Wallez336129f2017-10-17 15:55:40 -04004729 gl::Buffer *pixelUnpackBuffer =
4730 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004731 if (pixelUnpackBuffer == nullptr)
4732 {
4733 if (dataSize < imageSize)
4734 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004735 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004736 }
4737 }
4738 return true;
4739}
4740
Jamie Madillbe849e42017-05-02 15:49:00 -04004741bool ValidateGetBufferParameterBase(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004742 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004743 GLenum pname,
4744 bool pointerVersion,
4745 GLsizei *numParams)
4746{
4747 if (numParams)
4748 {
4749 *numParams = 0;
4750 }
4751
Corentin Wallez336129f2017-10-17 15:55:40 -04004752 if (!ValidBufferType(context, target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004753 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004754 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004755 return false;
4756 }
4757
4758 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4759 if (!buffer)
4760 {
4761 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004762 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004763 return false;
4764 }
4765
4766 const Extensions &extensions = context->getExtensions();
4767
4768 switch (pname)
4769 {
4770 case GL_BUFFER_USAGE:
4771 case GL_BUFFER_SIZE:
4772 break;
4773
4774 case GL_BUFFER_ACCESS_OES:
4775 if (!extensions.mapBuffer)
4776 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004777 context->handleError(InvalidEnum()
4778 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004779 return false;
4780 }
4781 break;
4782
4783 case GL_BUFFER_MAPPED:
4784 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4785 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4786 !extensions.mapBufferRange)
4787 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004788 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4789 "GL_OES_mapbuffer or "
4790 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004791 return false;
4792 }
4793 break;
4794
4795 case GL_BUFFER_MAP_POINTER:
4796 if (!pointerVersion)
4797 {
4798 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004799 InvalidEnum()
4800 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004801 return false;
4802 }
4803 break;
4804
4805 case GL_BUFFER_ACCESS_FLAGS:
4806 case GL_BUFFER_MAP_OFFSET:
4807 case GL_BUFFER_MAP_LENGTH:
4808 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4809 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004810 context->handleError(InvalidEnum()
4811 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004812 return false;
4813 }
4814 break;
4815
4816 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004817 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004818 return false;
4819 }
4820
4821 // All buffer parameter queries return one value.
4822 if (numParams)
4823 {
4824 *numParams = 1;
4825 }
4826
4827 return true;
4828}
4829
4830bool ValidateGetRenderbufferParameterivBase(Context *context,
4831 GLenum target,
4832 GLenum pname,
4833 GLsizei *length)
4834{
4835 if (length)
4836 {
4837 *length = 0;
4838 }
4839
4840 if (target != GL_RENDERBUFFER)
4841 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004842 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004843 return false;
4844 }
4845
4846 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4847 if (renderbuffer == nullptr)
4848 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004849 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004850 return false;
4851 }
4852
4853 switch (pname)
4854 {
4855 case GL_RENDERBUFFER_WIDTH:
4856 case GL_RENDERBUFFER_HEIGHT:
4857 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4858 case GL_RENDERBUFFER_RED_SIZE:
4859 case GL_RENDERBUFFER_GREEN_SIZE:
4860 case GL_RENDERBUFFER_BLUE_SIZE:
4861 case GL_RENDERBUFFER_ALPHA_SIZE:
4862 case GL_RENDERBUFFER_DEPTH_SIZE:
4863 case GL_RENDERBUFFER_STENCIL_SIZE:
4864 break;
4865
4866 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4867 if (!context->getExtensions().framebufferMultisample)
4868 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004869 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004870 return false;
4871 }
4872 break;
4873
4874 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004875 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004876 return false;
4877 }
4878
4879 if (length)
4880 {
4881 *length = 1;
4882 }
4883 return true;
4884}
4885
4886bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4887{
4888 if (length)
4889 {
4890 *length = 0;
4891 }
4892
4893 if (GetValidShader(context, shader) == nullptr)
4894 {
4895 return false;
4896 }
4897
4898 switch (pname)
4899 {
4900 case GL_SHADER_TYPE:
4901 case GL_DELETE_STATUS:
4902 case GL_COMPILE_STATUS:
4903 case GL_INFO_LOG_LENGTH:
4904 case GL_SHADER_SOURCE_LENGTH:
4905 break;
4906
4907 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4908 if (!context->getExtensions().translatedShaderSource)
4909 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004910 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004911 return false;
4912 }
4913 break;
4914
4915 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004916 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004917 return false;
4918 }
4919
4920 if (length)
4921 {
4922 *length = 1;
4923 }
4924 return true;
4925}
4926
4927bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4928{
4929 if (length)
4930 {
4931 *length = 0;
4932 }
4933
4934 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4935 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004936 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004937 return false;
4938 }
4939
4940 if (context->getTargetTexture(target) == nullptr)
4941 {
4942 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004943 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004944 return false;
4945 }
4946
4947 switch (pname)
4948 {
4949 case GL_TEXTURE_MAG_FILTER:
4950 case GL_TEXTURE_MIN_FILTER:
4951 case GL_TEXTURE_WRAP_S:
4952 case GL_TEXTURE_WRAP_T:
4953 break;
4954
4955 case GL_TEXTURE_USAGE_ANGLE:
4956 if (!context->getExtensions().textureUsage)
4957 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004958 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004959 return false;
4960 }
4961 break;
4962
4963 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4964 if (!context->getExtensions().textureFilterAnisotropic)
4965 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004966 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004967 return false;
4968 }
4969 break;
4970
4971 case GL_TEXTURE_IMMUTABLE_FORMAT:
4972 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4973 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004974 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004975 return false;
4976 }
4977 break;
4978
4979 case GL_TEXTURE_WRAP_R:
4980 case GL_TEXTURE_IMMUTABLE_LEVELS:
4981 case GL_TEXTURE_SWIZZLE_R:
4982 case GL_TEXTURE_SWIZZLE_G:
4983 case GL_TEXTURE_SWIZZLE_B:
4984 case GL_TEXTURE_SWIZZLE_A:
4985 case GL_TEXTURE_BASE_LEVEL:
4986 case GL_TEXTURE_MAX_LEVEL:
4987 case GL_TEXTURE_MIN_LOD:
4988 case GL_TEXTURE_MAX_LOD:
4989 case GL_TEXTURE_COMPARE_MODE:
4990 case GL_TEXTURE_COMPARE_FUNC:
4991 if (context->getClientMajorVersion() < 3)
4992 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004993 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004994 return false;
4995 }
4996 break;
4997
4998 case GL_TEXTURE_SRGB_DECODE_EXT:
4999 if (!context->getExtensions().textureSRGBDecode)
5000 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005001 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005002 return false;
5003 }
5004 break;
5005
5006 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005007 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005008 return false;
5009 }
5010
5011 if (length)
5012 {
5013 *length = 1;
5014 }
5015 return true;
5016}
5017
5018bool ValidateGetVertexAttribBase(Context *context,
5019 GLuint index,
5020 GLenum pname,
5021 GLsizei *length,
5022 bool pointer,
5023 bool pureIntegerEntryPoint)
5024{
5025 if (length)
5026 {
5027 *length = 0;
5028 }
5029
5030 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5031 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005032 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005033 return false;
5034 }
5035
5036 if (index >= context->getCaps().maxVertexAttributes)
5037 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005038 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005039 return false;
5040 }
5041
5042 if (pointer)
5043 {
5044 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5045 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005046 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005047 return false;
5048 }
5049 }
5050 else
5051 {
5052 switch (pname)
5053 {
5054 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5055 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5056 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5057 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5058 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5059 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5060 case GL_CURRENT_VERTEX_ATTRIB:
5061 break;
5062
5063 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5064 static_assert(
5065 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5066 "ANGLE extension enums not equal to GL enums.");
5067 if (context->getClientMajorVersion() < 3 &&
5068 !context->getExtensions().instancedArrays)
5069 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005070 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5071 "requires OpenGL ES 3.0 or "
5072 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005073 return false;
5074 }
5075 break;
5076
5077 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5078 if (context->getClientMajorVersion() < 3)
5079 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005080 context->handleError(
5081 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005082 return false;
5083 }
5084 break;
5085
5086 case GL_VERTEX_ATTRIB_BINDING:
5087 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5088 if (context->getClientVersion() < ES_3_1)
5089 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005090 context->handleError(InvalidEnum()
5091 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005092 return false;
5093 }
5094 break;
5095
5096 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005097 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005098 return false;
5099 }
5100 }
5101
5102 if (length)
5103 {
5104 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5105 {
5106 *length = 4;
5107 }
5108 else
5109 {
5110 *length = 1;
5111 }
5112 }
5113
5114 return true;
5115}
5116
Jamie Madill4928b7c2017-06-20 12:57:39 -04005117bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005118 GLint x,
5119 GLint y,
5120 GLsizei width,
5121 GLsizei height,
5122 GLenum format,
5123 GLenum type,
5124 GLsizei bufSize,
5125 GLsizei *length,
5126 GLsizei *columns,
5127 GLsizei *rows,
5128 void *pixels)
5129{
5130 if (length != nullptr)
5131 {
5132 *length = 0;
5133 }
5134 if (rows != nullptr)
5135 {
5136 *rows = 0;
5137 }
5138 if (columns != nullptr)
5139 {
5140 *columns = 0;
5141 }
5142
5143 if (width < 0 || height < 0)
5144 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005145 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005146 return false;
5147 }
5148
5149 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5150
5151 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5152 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005153 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005154 return false;
5155 }
5156
5157 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5158 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005159 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005160 return false;
5161 }
5162
5163 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5164 ASSERT(framebuffer);
5165
5166 if (framebuffer->getReadBufferState() == GL_NONE)
5167 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005168 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005169 return false;
5170 }
5171
5172 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5173 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5174 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5175 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5176 // situation is an application error that would lead to a crash in ANGLE.
5177 if (readBuffer == nullptr)
5178 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005179 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005180 return false;
5181 }
5182
Martin Radev28031682017-07-28 14:47:56 +03005183 // ANGLE_multiview, Revision 1:
5184 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5185 // current read framebuffer is not NONE.
5186 if (readBuffer->getMultiviewLayout() != GL_NONE)
5187 {
5188 context->handleError(InvalidFramebufferOperation()
5189 << "Attempting to read from a multi-view framebuffer.");
5190 return false;
5191 }
5192
Geoff Lang280ba992017-04-18 16:30:58 -04005193 if (context->getExtensions().webglCompatibility)
5194 {
5195 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5196 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5197 // and type before validating the combination of format and type. However, the
5198 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5199 // verifies that GL_INVALID_OPERATION is generated.
5200 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5201 // dEQP/WebGL.
5202 if (!ValidReadPixelsFormatEnum(context, format))
5203 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005204 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005205 return false;
5206 }
5207
5208 if (!ValidReadPixelsTypeEnum(context, type))
5209 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005210 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005211 return false;
5212 }
5213 }
5214
Jamie Madill4928b7c2017-06-20 12:57:39 -04005215 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5216 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005217 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5218
5219 bool validFormatTypeCombination =
5220 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5221
5222 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5223 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005224 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005225 return false;
5226 }
5227
5228 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005229 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005230 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5231 {
5232 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005233 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005234 return false;
5235 }
5236
5237 // .. the data would be packed to the buffer object such that the memory writes required
5238 // would exceed the data store size.
5239 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5240 const gl::Extents size(width, height, 1);
5241 const auto &pack = context->getGLState().getPackState();
5242
5243 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5244 if (endByteOrErr.isError())
5245 {
5246 context->handleError(endByteOrErr.getError());
5247 return false;
5248 }
5249
5250 size_t endByte = endByteOrErr.getResult();
5251 if (bufSize >= 0)
5252 {
5253 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5254 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005255 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005256 return false;
5257 }
5258 }
5259
5260 if (pixelPackBuffer != nullptr)
5261 {
5262 CheckedNumeric<size_t> checkedEndByte(endByte);
5263 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5264 checkedEndByte += checkedOffset;
5265
5266 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5267 {
5268 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005269 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005270 return false;
5271 }
5272 }
5273
5274 if (pixelPackBuffer == nullptr && length != nullptr)
5275 {
5276 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5277 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005278 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005279 return false;
5280 }
5281
5282 *length = static_cast<GLsizei>(endByte);
5283 }
5284
5285 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5286 angle::CheckedNumeric<int> clippedExtent(length);
5287 if (start < 0)
5288 {
5289 // "subtract" the area that is less than 0
5290 clippedExtent += start;
5291 }
5292
5293 const int readExtent = start + length;
5294 if (readExtent > bufferSize)
5295 {
5296 // Subtract the region to the right of the read buffer
5297 clippedExtent -= (readExtent - bufferSize);
5298 }
5299
5300 if (!clippedExtent.IsValid())
5301 {
5302 return 0;
5303 }
5304
5305 return std::max(clippedExtent.ValueOrDie(), 0);
5306 };
5307
5308 if (columns != nullptr)
5309 {
5310 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5311 }
5312
5313 if (rows != nullptr)
5314 {
5315 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5316 }
5317
5318 return true;
5319}
5320
5321template <typename ParamType>
5322bool ValidateTexParameterBase(Context *context,
5323 GLenum target,
5324 GLenum pname,
5325 GLsizei bufSize,
5326 const ParamType *params)
5327{
5328 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5329 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005330 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005331 return false;
5332 }
5333
5334 if (context->getTargetTexture(target) == nullptr)
5335 {
5336 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005337 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005338 return false;
5339 }
5340
5341 const GLsizei minBufSize = 1;
5342 if (bufSize >= 0 && bufSize < minBufSize)
5343 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005344 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005345 return false;
5346 }
5347
5348 switch (pname)
5349 {
5350 case GL_TEXTURE_WRAP_R:
5351 case GL_TEXTURE_SWIZZLE_R:
5352 case GL_TEXTURE_SWIZZLE_G:
5353 case GL_TEXTURE_SWIZZLE_B:
5354 case GL_TEXTURE_SWIZZLE_A:
5355 case GL_TEXTURE_BASE_LEVEL:
5356 case GL_TEXTURE_MAX_LEVEL:
5357 case GL_TEXTURE_COMPARE_MODE:
5358 case GL_TEXTURE_COMPARE_FUNC:
5359 case GL_TEXTURE_MIN_LOD:
5360 case GL_TEXTURE_MAX_LOD:
5361 if (context->getClientMajorVersion() < 3)
5362 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005363 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005364 return false;
5365 }
5366 if (target == GL_TEXTURE_EXTERNAL_OES &&
5367 !context->getExtensions().eglImageExternalEssl3)
5368 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005369 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5370 "available without "
5371 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005372 return false;
5373 }
5374 break;
5375
5376 default:
5377 break;
5378 }
5379
JiangYizhou4cff8d62017-07-06 14:54:09 +08005380 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5381 {
5382 switch (pname)
5383 {
5384 case GL_TEXTURE_MIN_FILTER:
5385 case GL_TEXTURE_MAG_FILTER:
5386 case GL_TEXTURE_WRAP_S:
5387 case GL_TEXTURE_WRAP_T:
5388 case GL_TEXTURE_WRAP_R:
5389 case GL_TEXTURE_MIN_LOD:
5390 case GL_TEXTURE_MAX_LOD:
5391 case GL_TEXTURE_COMPARE_MODE:
5392 case GL_TEXTURE_COMPARE_FUNC:
5393 context->handleError(InvalidEnum()
5394 << "Invalid parameter for 2D multisampled textures.");
5395 return false;
5396 }
5397 }
5398
Jamie Madillbe849e42017-05-02 15:49:00 -04005399 switch (pname)
5400 {
5401 case GL_TEXTURE_WRAP_S:
5402 case GL_TEXTURE_WRAP_T:
5403 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005404 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005405 bool restrictedWrapModes =
5406 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5407 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5408 {
5409 return false;
5410 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005411 }
5412 break;
5413
5414 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005415 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005416 bool restrictedMinFilter =
5417 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5418 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5419 {
5420 return false;
5421 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005422 }
5423 break;
5424
5425 case GL_TEXTURE_MAG_FILTER:
5426 if (!ValidateTextureMagFilterValue(context, params))
5427 {
5428 return false;
5429 }
5430 break;
5431
5432 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005433 if (!context->getExtensions().textureUsage)
5434 {
5435 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5436 return false;
5437 }
5438
Jamie Madillbe849e42017-05-02 15:49:00 -04005439 switch (ConvertToGLenum(params[0]))
5440 {
5441 case GL_NONE:
5442 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5443 break;
5444
5445 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005446 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005447 return false;
5448 }
5449 break;
5450
5451 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5452 if (!context->getExtensions().textureFilterAnisotropic)
5453 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005454 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005455 return false;
5456 }
5457
5458 // we assume the parameter passed to this validation method is truncated, not rounded
5459 if (params[0] < 1)
5460 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005461 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005462 return false;
5463 }
5464 break;
5465
5466 case GL_TEXTURE_MIN_LOD:
5467 case GL_TEXTURE_MAX_LOD:
5468 // any value is permissible
5469 break;
5470
5471 case GL_TEXTURE_COMPARE_MODE:
5472 if (!ValidateTextureCompareModeValue(context, params))
5473 {
5474 return false;
5475 }
5476 break;
5477
5478 case GL_TEXTURE_COMPARE_FUNC:
5479 if (!ValidateTextureCompareFuncValue(context, params))
5480 {
5481 return false;
5482 }
5483 break;
5484
5485 case GL_TEXTURE_SWIZZLE_R:
5486 case GL_TEXTURE_SWIZZLE_G:
5487 case GL_TEXTURE_SWIZZLE_B:
5488 case GL_TEXTURE_SWIZZLE_A:
5489 switch (ConvertToGLenum(params[0]))
5490 {
5491 case GL_RED:
5492 case GL_GREEN:
5493 case GL_BLUE:
5494 case GL_ALPHA:
5495 case GL_ZERO:
5496 case GL_ONE:
5497 break;
5498
5499 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005500 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005501 return false;
5502 }
5503 break;
5504
5505 case GL_TEXTURE_BASE_LEVEL:
5506 if (params[0] < 0)
5507 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005508 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005509 return false;
5510 }
5511 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5512 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005513 context->handleError(InvalidOperation()
5514 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005515 return false;
5516 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005517 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5518 {
5519 context->handleError(InvalidOperation()
5520 << "Base level must be 0 for multisampled textures.");
5521 return false;
5522 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005523 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5524 {
5525 context->handleError(InvalidOperation()
5526 << "Base level must be 0 for rectangle textures.");
5527 return false;
5528 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005529 break;
5530
5531 case GL_TEXTURE_MAX_LEVEL:
5532 if (params[0] < 0)
5533 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005534 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005535 return false;
5536 }
5537 break;
5538
5539 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5540 if (context->getClientVersion() < Version(3, 1))
5541 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005542 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005543 return false;
5544 }
5545 switch (ConvertToGLenum(params[0]))
5546 {
5547 case GL_DEPTH_COMPONENT:
5548 case GL_STENCIL_INDEX:
5549 break;
5550
5551 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005552 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005553 return false;
5554 }
5555 break;
5556
5557 case GL_TEXTURE_SRGB_DECODE_EXT:
5558 if (!ValidateTextureSRGBDecodeValue(context, params))
5559 {
5560 return false;
5561 }
5562 break;
5563
5564 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005565 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005566 return false;
5567 }
5568
5569 return true;
5570}
5571
5572template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5573template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5574
Jamie Madill12e957f2017-08-26 21:42:26 -04005575bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5576{
5577 if (index >= MAX_VERTEX_ATTRIBS)
5578 {
5579 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5580 return false;
5581 }
5582
5583 return true;
5584}
5585
5586bool ValidateGetActiveUniformBlockivBase(Context *context,
5587 GLuint program,
5588 GLuint uniformBlockIndex,
5589 GLenum pname,
5590 GLsizei *length)
5591{
5592 if (length)
5593 {
5594 *length = 0;
5595 }
5596
5597 if (context->getClientMajorVersion() < 3)
5598 {
5599 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5600 return false;
5601 }
5602
5603 Program *programObject = GetValidProgram(context, program);
5604 if (!programObject)
5605 {
5606 return false;
5607 }
5608
5609 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5610 {
5611 context->handleError(InvalidValue()
5612 << "uniformBlockIndex exceeds active uniform block count.");
5613 return false;
5614 }
5615
5616 switch (pname)
5617 {
5618 case GL_UNIFORM_BLOCK_BINDING:
5619 case GL_UNIFORM_BLOCK_DATA_SIZE:
5620 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5621 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5622 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5623 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5624 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5625 break;
5626
5627 default:
5628 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5629 return false;
5630 }
5631
5632 if (length)
5633 {
5634 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5635 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005636 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005637 programObject->getUniformBlockByIndex(uniformBlockIndex);
5638 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5639 }
5640 else
5641 {
5642 *length = 1;
5643 }
5644 }
5645
5646 return true;
5647}
5648
Jamie Madill9696d072017-08-26 23:19:57 -04005649template <typename ParamType>
5650bool ValidateSamplerParameterBase(Context *context,
5651 GLuint sampler,
5652 GLenum pname,
5653 GLsizei bufSize,
5654 ParamType *params)
5655{
5656 if (context->getClientMajorVersion() < 3)
5657 {
5658 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5659 return false;
5660 }
5661
5662 if (!context->isSampler(sampler))
5663 {
5664 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5665 return false;
5666 }
5667
5668 const GLsizei minBufSize = 1;
5669 if (bufSize >= 0 && bufSize < minBufSize)
5670 {
5671 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5672 return false;
5673 }
5674
5675 switch (pname)
5676 {
5677 case GL_TEXTURE_WRAP_S:
5678 case GL_TEXTURE_WRAP_T:
5679 case GL_TEXTURE_WRAP_R:
5680 if (!ValidateTextureWrapModeValue(context, params, false))
5681 {
5682 return false;
5683 }
5684 break;
5685
5686 case GL_TEXTURE_MIN_FILTER:
5687 if (!ValidateTextureMinFilterValue(context, params, false))
5688 {
5689 return false;
5690 }
5691 break;
5692
5693 case GL_TEXTURE_MAG_FILTER:
5694 if (!ValidateTextureMagFilterValue(context, params))
5695 {
5696 return false;
5697 }
5698 break;
5699
5700 case GL_TEXTURE_MIN_LOD:
5701 case GL_TEXTURE_MAX_LOD:
5702 // any value is permissible
5703 break;
5704
5705 case GL_TEXTURE_COMPARE_MODE:
5706 if (!ValidateTextureCompareModeValue(context, params))
5707 {
5708 return false;
5709 }
5710 break;
5711
5712 case GL_TEXTURE_COMPARE_FUNC:
5713 if (!ValidateTextureCompareFuncValue(context, params))
5714 {
5715 return false;
5716 }
5717 break;
5718
5719 case GL_TEXTURE_SRGB_DECODE_EXT:
5720 if (!ValidateTextureSRGBDecodeValue(context, params))
5721 {
5722 return false;
5723 }
5724 break;
5725
5726 default:
5727 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5728 return false;
5729 }
5730
5731 return true;
5732}
5733
5734template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5735template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5736
5737bool ValidateGetSamplerParameterBase(Context *context,
5738 GLuint sampler,
5739 GLenum pname,
5740 GLsizei *length)
5741{
5742 if (length)
5743 {
5744 *length = 0;
5745 }
5746
5747 if (context->getClientMajorVersion() < 3)
5748 {
5749 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5750 return false;
5751 }
5752
5753 if (!context->isSampler(sampler))
5754 {
5755 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5756 return false;
5757 }
5758
5759 switch (pname)
5760 {
5761 case GL_TEXTURE_WRAP_S:
5762 case GL_TEXTURE_WRAP_T:
5763 case GL_TEXTURE_WRAP_R:
5764 case GL_TEXTURE_MIN_FILTER:
5765 case GL_TEXTURE_MAG_FILTER:
5766 case GL_TEXTURE_MIN_LOD:
5767 case GL_TEXTURE_MAX_LOD:
5768 case GL_TEXTURE_COMPARE_MODE:
5769 case GL_TEXTURE_COMPARE_FUNC:
5770 break;
5771
5772 case GL_TEXTURE_SRGB_DECODE_EXT:
5773 if (!context->getExtensions().textureSRGBDecode)
5774 {
5775 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5776 return false;
5777 }
5778 break;
5779
5780 default:
5781 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5782 return false;
5783 }
5784
5785 if (length)
5786 {
5787 *length = 1;
5788 }
5789 return true;
5790}
5791
5792bool ValidateGetInternalFormativBase(Context *context,
5793 GLenum target,
5794 GLenum internalformat,
5795 GLenum pname,
5796 GLsizei bufSize,
5797 GLsizei *numParams)
5798{
5799 if (numParams)
5800 {
5801 *numParams = 0;
5802 }
5803
5804 if (context->getClientMajorVersion() < 3)
5805 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005806 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005807 return false;
5808 }
5809
5810 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5811 if (!formatCaps.renderable)
5812 {
5813 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5814 return false;
5815 }
5816
5817 switch (target)
5818 {
5819 case GL_RENDERBUFFER:
5820 break;
5821
5822 case GL_TEXTURE_2D_MULTISAMPLE:
5823 if (context->getClientVersion() < ES_3_1)
5824 {
5825 context->handleError(InvalidOperation()
5826 << "Texture target requires at least OpenGL ES 3.1.");
5827 return false;
5828 }
5829 break;
5830
5831 default:
5832 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5833 return false;
5834 }
5835
5836 if (bufSize < 0)
5837 {
5838 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5839 return false;
5840 }
5841
5842 GLsizei maxWriteParams = 0;
5843 switch (pname)
5844 {
5845 case GL_NUM_SAMPLE_COUNTS:
5846 maxWriteParams = 1;
5847 break;
5848
5849 case GL_SAMPLES:
5850 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5851 break;
5852
5853 default:
5854 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5855 return false;
5856 }
5857
5858 if (numParams)
5859 {
5860 // glGetInternalFormativ will not overflow bufSize
5861 *numParams = std::min(bufSize, maxWriteParams);
5862 }
5863
5864 return true;
5865}
5866
Jamie Madillc29968b2016-01-20 11:17:23 -05005867} // namespace gl