blob: dda80276841b362cc6eaef21d49a5f31de9e6c42 [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
Geoff Lange8afa902017-09-27 15:00:43 -0400760bool ValidFramebufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500761{
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;
Geoff Lange8afa902017-09-27 15:00:43 -0400770
He Yunchaoced53ae2016-11-29 15:00:51 +0800771 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800772 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400773 return (context->getExtensions().framebufferBlit ||
774 context->getClientMajorVersion() >= 3);
775
He Yunchaoced53ae2016-11-29 15:00:51 +0800776 default:
777 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500778 }
779}
780
Corentin Wallez336129f2017-10-17 15:55:40 -0400781bool ValidBufferType(const ValidationContext *context, BufferBinding target)
Jamie Madill8c96d582014-03-05 15:01:23 -0500782{
783 switch (target)
784 {
Corentin Wallez336129f2017-10-17 15:55:40 -0400785 case BufferBinding::ElementArray:
786 case BufferBinding::Array:
He Yunchaoced53ae2016-11-29 15:00:51 +0800787 return true;
Jamie Madill8c96d582014-03-05 15:01:23 -0500788
Corentin Wallez336129f2017-10-17 15:55:40 -0400789 case BufferBinding::PixelPack:
790 case BufferBinding::PixelUnpack:
He Yunchaoced53ae2016-11-29 15:00:51 +0800791 return (context->getExtensions().pixelBufferObject ||
792 context->getClientMajorVersion() >= 3);
Shannon Woods158c4382014-05-06 13:00:07 -0400793
Corentin Wallez336129f2017-10-17 15:55:40 -0400794 case BufferBinding::CopyRead:
795 case BufferBinding::CopyWrite:
796 case BufferBinding::TransformFeedback:
797 case BufferBinding::Uniform:
He Yunchaoced53ae2016-11-29 15:00:51 +0800798 return (context->getClientMajorVersion() >= 3);
Jamie Madill8c96d582014-03-05 15:01:23 -0500799
Corentin Wallez336129f2017-10-17 15:55:40 -0400800 case BufferBinding::AtomicCounter:
801 case BufferBinding::ShaderStorage:
802 case BufferBinding::DrawIndirect:
803 case BufferBinding::DispatchIndirect:
He Yunchaoced53ae2016-11-29 15:00:51 +0800804 return context->getClientVersion() >= Version(3, 1);
Geoff Lang3b573612016-10-31 14:08:10 -0400805
He Yunchaoced53ae2016-11-29 15:00:51 +0800806 default:
807 return false;
Jamie Madill8c96d582014-03-05 15:01:23 -0500808 }
809}
810
Jamie Madillc29968b2016-01-20 11:17:23 -0500811bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400812{
Jamie Madillc29968b2016-01-20 11:17:23 -0500813 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400814 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -0400815 switch (target)
816 {
Jamie Madillc29968b2016-01-20 11:17:23 -0500817 case GL_TEXTURE_2D:
818 maxDimension = caps.max2DTextureSize;
819 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800820 case GL_TEXTURE_CUBE_MAP:
821 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
822 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
823 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
824 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
825 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
826 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
827 maxDimension = caps.maxCubeMapTextureSize;
828 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400829 case GL_TEXTURE_RECTANGLE_ANGLE:
830 return level == 0;
He Yunchaoced53ae2016-11-29 15:00:51 +0800831 case GL_TEXTURE_3D:
832 maxDimension = caps.max3DTextureSize;
833 break;
834 case GL_TEXTURE_2D_ARRAY:
835 maxDimension = caps.max2DTextureSize;
836 break;
He Yunchao11b038b2016-11-22 21:24:04 +0800837 case GL_TEXTURE_2D_MULTISAMPLE:
838 maxDimension = caps.max2DTextureSize;
839 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800840 default:
841 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400842 }
843
Brandon Jones6cad5662017-06-14 13:25:13 -0700844 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400845}
846
Brandon Jones6cad5662017-06-14 13:25:13 -0700847bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -0700848 GLenum target,
849 GLint level,
850 GLsizei width,
851 GLsizei height,
852 GLsizei depth,
853 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400854{
Brandon Jones6cad5662017-06-14 13:25:13 -0700855 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400856 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700857 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400858 return false;
859 }
Austin Kinross08528e12015-10-07 16:24:40 -0700860 // TexSubImage parameters can be NPOT without textureNPOT extension,
861 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500862 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500863 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500864 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400865 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400866 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700867 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400868 return false;
869 }
870
871 if (!ValidMipLevel(context, target, level))
872 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700873 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400874 return false;
875 }
876
877 return true;
878}
879
Geoff Lang0d8b7242015-09-09 14:56:53 -0400880bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
881{
882 // List of compressed format that require that the texture size is smaller than or a multiple of
883 // the compressed block size.
884 switch (internalFormat)
885 {
886 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
887 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
888 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
889 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langfff7a7d2017-06-02 10:39:17 -0400890 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
891 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
892 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
893 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
Minmin Gonge3939b92015-12-01 15:36:51 -0800894 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800895 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
896 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
897 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
898 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
899 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
900 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -0400901 return true;
902
903 default:
904 return false;
905 }
906}
907
Geoff Lang966c9402017-04-18 12:38:27 -0400908bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
909{
910 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
911 (size % blockSize == 0);
912}
913
Jamie Madillc29968b2016-01-20 11:17:23 -0500914bool ValidCompressedImageSize(const ValidationContext *context,
915 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400916 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500917 GLsizei width,
918 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400919{
Geoff Langca271392017-04-05 12:30:00 -0400920 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400921 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400922 {
923 return false;
924 }
925
Geoff Lang966c9402017-04-18 12:38:27 -0400926 if (width < 0 || height < 0)
927 {
928 return false;
929 }
930
931 if (CompressedTextureFormatRequiresExactSize(internalFormat))
932 {
933 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
934 // block size for level 0 but WebGL disallows this.
935 bool smallerThanBlockSizeAllowed =
936 level > 0 || !context->getExtensions().webglCompatibility;
937
938 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
939 smallerThanBlockSizeAllowed) ||
940 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
941 smallerThanBlockSizeAllowed))
942 {
943 return false;
944 }
945 }
946
947 return true;
948}
949
950bool ValidCompressedSubImageSize(const ValidationContext *context,
951 GLenum internalFormat,
952 GLint xoffset,
953 GLint yoffset,
954 GLsizei width,
955 GLsizei height,
956 size_t textureWidth,
957 size_t textureHeight)
958{
959 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
960 if (!formatInfo.compressed)
961 {
962 return false;
963 }
964
Geoff Lang44ff5a72017-02-03 15:15:43 -0500965 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400966 {
967 return false;
968 }
969
Geoff Lang0d8b7242015-09-09 14:56:53 -0400970 if (CompressedTextureFormatRequiresExactSize(internalFormat))
971 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500972 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400973 yoffset % formatInfo.compressedBlockHeight != 0)
974 {
975 return false;
976 }
977
978 // Allowed to either have data that is a multiple of block size or is smaller than the block
979 // size but fills the entire mip
980 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
981 static_cast<size_t>(width) == textureWidth &&
982 static_cast<size_t>(height) == textureHeight;
983 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
984 (height % formatInfo.compressedBlockHeight) == 0;
985 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400986 {
987 return false;
988 }
989 }
990
Geoff Langd4f180b2013-09-24 13:57:44 -0400991 return true;
992}
993
Geoff Langff5b2d52016-09-07 11:32:23 -0400994bool ValidImageDataSize(ValidationContext *context,
995 GLenum textureTarget,
996 GLsizei width,
997 GLsizei height,
998 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400999 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -04001000 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001001 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -04001002 GLsizei imageSize)
1003{
Corentin Wallez336129f2017-10-17 15:55:40 -04001004 gl::Buffer *pixelUnpackBuffer =
1005 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -04001006 if (pixelUnpackBuffer == nullptr && imageSize < 0)
1007 {
1008 // Checks are not required
1009 return true;
1010 }
1011
1012 // ...the data would be unpacked from the buffer object such that the memory reads required
1013 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -04001014 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
1015 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -04001016 const gl::Extents size(width, height, depth);
1017 const auto &unpack = context->getGLState().getUnpackState();
1018
1019 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
1020 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
1021 if (endByteOrErr.isError())
1022 {
1023 context->handleError(endByteOrErr.getError());
1024 return false;
1025 }
1026
1027 GLuint endByte = endByteOrErr.getResult();
1028
1029 if (pixelUnpackBuffer)
1030 {
1031 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
1032 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
1033 checkedEndByte += checkedOffset;
1034
1035 if (!checkedEndByte.IsValid() ||
1036 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
1037 {
1038 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001039 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04001040 return false;
1041 }
1042 }
1043 else
1044 {
1045 ASSERT(imageSize >= 0);
1046 if (pixels == nullptr && imageSize != 0)
1047 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001048 context->handleError(InvalidOperation()
1049 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001050 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -04001051 }
1052
Geoff Lang3feb3ff2016-10-26 10:57:45 -04001053 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -04001054 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001055 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -04001056 return false;
1057 }
1058 }
1059
1060 return true;
1061}
1062
Geoff Lang37dde692014-01-31 16:34:54 -05001063bool ValidQueryType(const Context *context, GLenum queryType)
1064{
He Yunchaoced53ae2016-11-29 15:00:51 +08001065 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
1066 "GL extension enums not equal.");
1067 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1068 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -05001069
1070 switch (queryType)
1071 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001072 case GL_ANY_SAMPLES_PASSED:
1073 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -04001074 return context->getClientMajorVersion() >= 3 ||
1075 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +08001076 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
1077 return (context->getClientMajorVersion() >= 3);
1078 case GL_TIME_ELAPSED_EXT:
1079 return context->getExtensions().disjointTimerQuery;
1080 case GL_COMMANDS_COMPLETED_CHROMIUM:
1081 return context->getExtensions().syncQuery;
1082 default:
1083 return false;
Geoff Lang37dde692014-01-31 16:34:54 -05001084 }
1085}
1086
Geoff Lang2d62ab72017-03-23 16:54:40 -04001087bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
1088 GLenum type,
1089 GLboolean normalized,
1090 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04001091 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -04001092 bool pureInteger)
1093{
1094 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001095 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
1096 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
1097 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
1098 // parameter exceeds 255.
1099 constexpr GLsizei kMaxWebGLStride = 255;
1100 if (stride > kMaxWebGLStride)
1101 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001102 context->handleError(InvalidValue()
1103 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -04001104 return false;
1105 }
1106
1107 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
1108 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
1109 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
1110 // or an INVALID_OPERATION error is generated.
1111 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
1112 size_t typeSize = GetVertexFormatTypeSize(internalType);
1113
1114 ASSERT(isPow2(typeSize) && typeSize > 0);
1115 size_t sizeMask = (typeSize - 1);
1116 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
1117 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001118 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001119 return false;
1120 }
1121
1122 if ((stride & sizeMask) != 0)
1123 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001124 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -04001125 return false;
1126 }
1127
1128 return true;
1129}
1130
Jamie Madillef300b12016-10-07 15:12:09 -04001131Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -05001132{
He Yunchaoced53ae2016-11-29 15:00:51 +08001133 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
1134 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
1135 // or program object and INVALID_OPERATION if the provided name identifies an object
1136 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -05001137
Dian Xiang769769a2015-09-09 15:20:08 -07001138 Program *validProgram = context->getProgram(id);
1139
1140 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001141 {
Dian Xiang769769a2015-09-09 15:20:08 -07001142 if (context->getShader(id))
1143 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001144 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001145 }
1146 else
1147 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001148 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001149 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001150 }
Dian Xiang769769a2015-09-09 15:20:08 -07001151
1152 return validProgram;
1153}
1154
Jamie Madillef300b12016-10-07 15:12:09 -04001155Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001156{
1157 // See ValidProgram for spec details.
1158
1159 Shader *validShader = context->getShader(id);
1160
1161 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001162 {
Dian Xiang769769a2015-09-09 15:20:08 -07001163 if (context->getProgram(id))
1164 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001165 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001166 }
1167 else
1168 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001169 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001170 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001171 }
Dian Xiang769769a2015-09-09 15:20:08 -07001172
1173 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001174}
1175
Geoff Langb1196682014-07-23 13:47:29 -04001176bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001177{
Geoff Langfa125c92017-10-24 13:01:46 -04001178 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001179 {
Geoff Langfa125c92017-10-24 13:01:46 -04001180 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1181 {
1182 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1183 return false;
1184 }
Jamie Madillb4472272014-07-03 10:38:55 -04001185
Geoff Langfa125c92017-10-24 13:01:46 -04001186 // Color attachment 0 is validated below because it is always valid
1187 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001188 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001189 {
Geoff Langfa125c92017-10-24 13:01:46 -04001190 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001191 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001192 }
1193 }
1194 else
1195 {
1196 switch (attachment)
1197 {
Geoff Langfa125c92017-10-24 13:01:46 -04001198 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001199 case GL_DEPTH_ATTACHMENT:
1200 case GL_STENCIL_ATTACHMENT:
1201 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001202
He Yunchaoced53ae2016-11-29 15:00:51 +08001203 case GL_DEPTH_STENCIL_ATTACHMENT:
1204 if (!context->getExtensions().webglCompatibility &&
1205 context->getClientMajorVersion() < 3)
1206 {
Geoff Langfa125c92017-10-24 13:01:46 -04001207 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001208 return false;
1209 }
1210 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001211
He Yunchaoced53ae2016-11-29 15:00:51 +08001212 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001213 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001214 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001215 }
1216 }
1217
1218 return true;
1219}
1220
Jamie Madille8fb6402017-02-14 17:56:40 -05001221bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001222 GLenum target,
1223 GLsizei samples,
1224 GLenum internalformat,
1225 GLsizei width,
1226 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001227{
1228 switch (target)
1229 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001230 case GL_RENDERBUFFER:
1231 break;
1232 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001233 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001234 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001235 }
1236
1237 if (width < 0 || height < 0 || samples < 0)
1238 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001239 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001240 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001241 }
1242
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001243 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1244 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1245
1246 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001247 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001248 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001249 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001250 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001251 }
1252
1253 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1254 // 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 -08001255 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001256 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1257 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001258 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001259 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001260 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001261 }
1262
Geoff Langaae65a42014-05-26 12:43:44 -04001263 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001264 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001265 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001266 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001267 }
1268
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001269 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001270 if (handle == 0)
1271 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001272 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001273 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001274 }
1275
1276 return true;
1277}
1278
He Yunchaoced53ae2016-11-29 15:00:51 +08001279bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1280 GLenum target,
1281 GLenum attachment,
1282 GLenum renderbuffertarget,
1283 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001284{
Geoff Lange8afa902017-09-27 15:00:43 -04001285 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001286 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001287 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001288 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001289 }
1290
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001291 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001292
Jamie Madill84115c92015-04-23 15:00:07 -04001293 ASSERT(framebuffer);
1294 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001295 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001296 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001297 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001298 }
1299
Jamie Madillb4472272014-07-03 10:38:55 -04001300 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001301 {
Jamie Madillb4472272014-07-03 10:38:55 -04001302 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001303 }
1304
Jamie Madillab9d82c2014-01-21 16:38:14 -05001305 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1306 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1307 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1308 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1309 if (renderbuffer != 0)
1310 {
1311 if (!context->getRenderbuffer(renderbuffer))
1312 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001313 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001314 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001315 }
1316 }
1317
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001318 return true;
1319}
1320
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001321bool ValidateBlitFramebufferParameters(ValidationContext *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001322 GLint srcX0,
1323 GLint srcY0,
1324 GLint srcX1,
1325 GLint srcY1,
1326 GLint dstX0,
1327 GLint dstY0,
1328 GLint dstX1,
1329 GLint dstY1,
1330 GLbitfield mask,
1331 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001332{
1333 switch (filter)
1334 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001335 case GL_NEAREST:
1336 break;
1337 case GL_LINEAR:
1338 break;
1339 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001340 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001341 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001342 }
1343
1344 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1345 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001346 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001347 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001348 }
1349
1350 if (mask == 0)
1351 {
1352 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1353 // buffers are copied.
1354 return false;
1355 }
1356
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001357 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1358 // color buffer, leaving only nearest being unfiltered from above
1359 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1360 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001361 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001362 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001363 }
1364
Jamie Madill51f40ec2016-06-15 14:06:00 -04001365 const auto &glState = context->getGLState();
1366 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1367 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001368
1369 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001371 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001372 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001373 }
1374
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001375 if (readFramebuffer->id() == drawFramebuffer->id())
1376 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001377 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001378 return false;
1379 }
1380
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001381 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001382 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001383 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001384 return false;
1385 }
1386
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001387 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001388 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001389 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001390 return false;
1391 }
1392
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001393 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001394 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001395 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001396 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001397 }
1398
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001399 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1400
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001401 if (mask & GL_COLOR_BUFFER_BIT)
1402 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001403 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001404 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001405
He Yunchao66a41a22016-12-15 16:45:05 +08001406 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001407 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001408 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001409
Geoff Langa15472a2015-08-11 11:48:03 -04001410 for (size_t drawbufferIdx = 0;
1411 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001412 {
Geoff Langa15472a2015-08-11 11:48:03 -04001413 const FramebufferAttachment *attachment =
1414 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1415 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001416 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001417 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001418
Geoff Langb2f3d052013-08-13 12:49:27 -04001419 // The GL ES 3.0.2 spec (pg 193) states that:
1420 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001421 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1422 // as well
1423 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1424 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001425 // Changes with EXT_color_buffer_float:
1426 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001427 GLenum readComponentType = readFormat.info->componentType;
1428 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001429 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001430 readComponentType == GL_SIGNED_NORMALIZED);
1431 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1432 drawComponentType == GL_SIGNED_NORMALIZED);
1433
1434 if (extensions.colorBufferFloat)
1435 {
1436 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1437 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1438
1439 if (readFixedOrFloat != drawFixedOrFloat)
1440 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001441 context->handleError(InvalidOperation()
1442 << "If the read buffer contains fixed-point or "
1443 "floating-point values, the draw buffer must "
1444 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001445 return false;
1446 }
1447 }
1448 else if (readFixedPoint != drawFixedPoint)
1449 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001450 context->handleError(InvalidOperation()
1451 << "If the read buffer contains fixed-point values, "
1452 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001453 return false;
1454 }
1455
1456 if (readComponentType == GL_UNSIGNED_INT &&
1457 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001458 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001459 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001460 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001461 }
1462
Jamie Madill6163c752015-12-07 16:32:59 -05001463 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001464 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001465 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001466 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001467 }
1468
Jamie Madilla3944d42016-07-22 22:13:26 -04001469 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001470 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001471 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001472 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001473 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001474 }
Geoff Lange4915782017-04-12 15:19:07 -04001475
1476 if (context->getExtensions().webglCompatibility &&
1477 *readColorBuffer == *attachment)
1478 {
1479 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001480 InvalidOperation()
1481 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001482 return false;
1483 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001484 }
1485 }
1486
Jamie Madilla3944d42016-07-22 22:13:26 -04001487 if ((readFormat.info->componentType == GL_INT ||
1488 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1489 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001490 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001491 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001492 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001493 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001494 }
He Yunchao66a41a22016-12-15 16:45:05 +08001495 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1496 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1497 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1498 // situation is an application error that would lead to a crash in ANGLE.
1499 else if (drawFramebuffer->hasEnabledDrawBuffer())
1500 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001501 context->handleError(
1502 InvalidOperation()
1503 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001504 return false;
1505 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001506 }
1507
He Yunchaoced53ae2016-11-29 15:00:51 +08001508 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001509 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1510 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001511 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001512 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001513 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001514 const gl::FramebufferAttachment *readBuffer =
1515 readFramebuffer->getAttachment(attachments[i]);
1516 const gl::FramebufferAttachment *drawBuffer =
1517 drawFramebuffer->getAttachment(attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001518
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001519 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001520 {
Kenneth Russell69382852017-07-21 16:38:44 -04001521 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001522 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001523 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001524 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001525 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001526
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001527 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001528 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001529 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001530 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001531 }
Geoff Lange4915782017-04-12 15:19:07 -04001532
1533 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1534 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001535 context->handleError(
1536 InvalidOperation()
1537 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001538 return false;
1539 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001540 }
He Yunchao66a41a22016-12-15 16:45:05 +08001541 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1542 else if (drawBuffer)
1543 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001544 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1545 "depth/stencil attachment of a "
1546 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001547 return false;
1548 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001549 }
1550 }
1551
Martin Radeva3ed4572017-07-27 18:29:37 +03001552 // ANGLE_multiview, Revision 1:
1553 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1554 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1555 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1556 {
1557 context->handleError(InvalidFramebufferOperation()
1558 << "Attempt to read from a multi-view framebuffer.");
1559 return false;
1560 }
1561 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1562 {
1563 context->handleError(InvalidFramebufferOperation()
1564 << "Attempt to write to a multi-view framebuffer.");
1565 return false;
1566 }
1567
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001568 return true;
1569}
1570
Jamie Madill4928b7c2017-06-20 12:57:39 -04001571bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001572 GLint x,
1573 GLint y,
1574 GLsizei width,
1575 GLsizei height,
1576 GLenum format,
1577 GLenum type,
1578 GLsizei bufSize,
1579 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001580 GLsizei *columns,
1581 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001582 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001583{
1584 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001585 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001586 return false;
1587 }
1588
Geoff Lang62fce5b2016-09-30 10:46:35 -04001589 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001590 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001591 {
Geoff Langb1196682014-07-23 13:47:29 -04001592 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001593 }
1594
Geoff Lang62fce5b2016-09-30 10:46:35 -04001595 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001596 {
Geoff Langb1196682014-07-23 13:47:29 -04001597 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001598 }
1599
Jamie Madillc29968b2016-01-20 11:17:23 -05001600 return true;
1601}
1602
1603bool ValidateReadnPixelsEXT(Context *context,
1604 GLint x,
1605 GLint y,
1606 GLsizei width,
1607 GLsizei height,
1608 GLenum format,
1609 GLenum type,
1610 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001611 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001612{
1613 if (bufSize < 0)
1614 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001615 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001616 return false;
1617 }
1618
Geoff Lang62fce5b2016-09-30 10:46:35 -04001619 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001620 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001621}
Jamie Madill26e91952014-03-05 15:01:27 -05001622
Jamie Madill4928b7c2017-06-20 12:57:39 -04001623bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001624 GLint x,
1625 GLint y,
1626 GLsizei width,
1627 GLsizei height,
1628 GLenum format,
1629 GLenum type,
1630 GLsizei bufSize,
1631 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001632 GLsizei *columns,
1633 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001634 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001635{
1636 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001637 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001638 return false;
1639 }
1640
Geoff Lange93daba2017-03-30 13:54:40 -04001641 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1642 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001643 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001644 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001645 }
1646
Geoff Lang62fce5b2016-09-30 10:46:35 -04001647 if (!ValidateRobustBufferSize(context, bufSize, *length))
1648 {
1649 return false;
1650 }
1651
1652 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001653}
1654
Jamie Madillf0e04492017-08-26 15:28:42 -04001655bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001656{
1657 if (!context->getExtensions().occlusionQueryBoolean &&
1658 !context->getExtensions().disjointTimerQuery)
1659 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001660 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001661 return false;
1662 }
1663
Olli Etuaho41997e72016-03-10 13:38:39 +02001664 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001665}
1666
Jamie Madillf0e04492017-08-26 15:28:42 -04001667bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001668{
1669 if (!context->getExtensions().occlusionQueryBoolean &&
1670 !context->getExtensions().disjointTimerQuery)
1671 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001672 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001673 return false;
1674 }
1675
Olli Etuaho41997e72016-03-10 13:38:39 +02001676 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001677}
1678
Jamie Madillf0e04492017-08-26 15:28:42 -04001679bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1680{
1681 if (!context->getExtensions().occlusionQueryBoolean &&
1682 !context->getExtensions().disjointTimerQuery)
1683 {
1684 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1685 return false;
1686 }
1687
1688 return true;
1689}
1690
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001691bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001692{
1693 if (!ValidQueryType(context, target))
1694 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001695 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001696 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001697 }
1698
1699 if (id == 0)
1700 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001701 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001702 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001703 }
1704
1705 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1706 // of zero, if the active query object name for <target> is non-zero (for the
1707 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1708 // the active query for either target is non-zero), if <id> is the name of an
1709 // existing query object whose type does not match <target>, or if <id> is the
1710 // active query object name for any query type, the error INVALID_OPERATION is
1711 // generated.
1712
1713 // Ensure no other queries are active
1714 // NOTE: If other queries than occlusion are supported, we will need to check
1715 // separately that:
1716 // a) The query ID passed is not the current active query for any target/type
1717 // b) There are no active queries for the requested target (and in the case
1718 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1719 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001720
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001721 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001722 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001723 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001724 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001725 }
1726
1727 Query *queryObject = context->getQuery(id, true, target);
1728
1729 // check that name was obtained with glGenQueries
1730 if (!queryObject)
1731 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001732 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001733 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001734 }
1735
1736 // check for type mismatch
1737 if (queryObject->getType() != target)
1738 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001739 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001740 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001741 }
1742
1743 return true;
1744}
1745
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001746bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1747{
1748 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001749 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001750 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001751 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001752 return false;
1753 }
1754
1755 return ValidateBeginQueryBase(context, target, id);
1756}
1757
1758bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001759{
1760 if (!ValidQueryType(context, target))
1761 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001762 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001763 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001764 }
1765
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001766 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001767
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001768 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001769 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001770 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001771 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001772 }
1773
Jamie Madill45c785d2014-05-13 14:09:34 -04001774 return true;
1775}
1776
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001777bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1778{
1779 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001780 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001781 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001782 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001783 return false;
1784 }
1785
1786 return ValidateEndQueryBase(context, target);
1787}
1788
1789bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1790{
1791 if (!context->getExtensions().disjointTimerQuery)
1792 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001793 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001794 return false;
1795 }
1796
1797 if (target != GL_TIMESTAMP_EXT)
1798 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001799 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001800 return false;
1801 }
1802
1803 Query *queryObject = context->getQuery(id, true, target);
1804 if (queryObject == nullptr)
1805 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001806 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001807 return false;
1808 }
1809
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001810 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001811 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001812 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001813 return false;
1814 }
1815
1816 return true;
1817}
1818
Geoff Lang2186c382016-10-14 10:54:54 -04001819bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001820{
Geoff Lang2186c382016-10-14 10:54:54 -04001821 if (numParams)
1822 {
1823 *numParams = 0;
1824 }
1825
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001826 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1827 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001828 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001829 return false;
1830 }
1831
1832 switch (pname)
1833 {
1834 case GL_CURRENT_QUERY_EXT:
1835 if (target == GL_TIMESTAMP_EXT)
1836 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001837 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001838 return false;
1839 }
1840 break;
1841 case GL_QUERY_COUNTER_BITS_EXT:
1842 if (!context->getExtensions().disjointTimerQuery ||
1843 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1844 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001845 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001846 return false;
1847 }
1848 break;
1849 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001850 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001851 return false;
1852 }
1853
Geoff Lang2186c382016-10-14 10:54:54 -04001854 if (numParams)
1855 {
1856 // All queries return only one value
1857 *numParams = 1;
1858 }
1859
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001860 return true;
1861}
1862
1863bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1864{
1865 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001866 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001867 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001868 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001869 return false;
1870 }
1871
Geoff Lang2186c382016-10-14 10:54:54 -04001872 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001873}
1874
Geoff Lang2186c382016-10-14 10:54:54 -04001875bool ValidateGetQueryivRobustANGLE(Context *context,
1876 GLenum target,
1877 GLenum pname,
1878 GLsizei bufSize,
1879 GLsizei *length,
1880 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001881{
Geoff Lang2186c382016-10-14 10:54:54 -04001882 if (!ValidateRobustEntryPoint(context, bufSize))
1883 {
1884 return false;
1885 }
1886
1887 if (!ValidateGetQueryivBase(context, target, pname, length))
1888 {
1889 return false;
1890 }
1891
1892 if (!ValidateRobustBufferSize(context, bufSize, *length))
1893 {
1894 return false;
1895 }
1896
1897 return true;
1898}
1899
1900bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1901{
1902 if (numParams)
1903 {
1904 *numParams = 0;
1905 }
1906
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001907 Query *queryObject = context->getQuery(id, false, GL_NONE);
1908
1909 if (!queryObject)
1910 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001911 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001912 return false;
1913 }
1914
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001915 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001916 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001917 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001918 return false;
1919 }
1920
1921 switch (pname)
1922 {
1923 case GL_QUERY_RESULT_EXT:
1924 case GL_QUERY_RESULT_AVAILABLE_EXT:
1925 break;
1926
1927 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001928 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001929 return false;
1930 }
1931
Geoff Lang2186c382016-10-14 10:54:54 -04001932 if (numParams)
1933 {
1934 *numParams = 1;
1935 }
1936
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001937 return true;
1938}
1939
1940bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1941{
1942 if (!context->getExtensions().disjointTimerQuery)
1943 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001944 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001945 return false;
1946 }
Geoff Lang2186c382016-10-14 10:54:54 -04001947 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1948}
1949
1950bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1951 GLuint id,
1952 GLenum pname,
1953 GLsizei bufSize,
1954 GLsizei *length,
1955 GLint *params)
1956{
1957 if (!context->getExtensions().disjointTimerQuery)
1958 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001959 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001960 return false;
1961 }
1962
1963 if (!ValidateRobustEntryPoint(context, bufSize))
1964 {
1965 return false;
1966 }
1967
1968 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1969 {
1970 return false;
1971 }
1972
1973 if (!ValidateRobustBufferSize(context, bufSize, *length))
1974 {
1975 return false;
1976 }
1977
1978 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001979}
1980
1981bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1982{
1983 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001984 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001985 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001986 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001987 return false;
1988 }
Geoff Lang2186c382016-10-14 10:54:54 -04001989 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1990}
1991
1992bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1993 GLuint id,
1994 GLenum pname,
1995 GLsizei bufSize,
1996 GLsizei *length,
1997 GLuint *params)
1998{
1999 if (!context->getExtensions().disjointTimerQuery &&
2000 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
2001 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002002 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002003 return false;
2004 }
2005
2006 if (!ValidateRobustEntryPoint(context, bufSize))
2007 {
2008 return false;
2009 }
2010
2011 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2012 {
2013 return false;
2014 }
2015
2016 if (!ValidateRobustBufferSize(context, bufSize, *length))
2017 {
2018 return false;
2019 }
2020
2021 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002022}
2023
2024bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
2025{
2026 if (!context->getExtensions().disjointTimerQuery)
2027 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002028 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002029 return false;
2030 }
Geoff Lang2186c382016-10-14 10:54:54 -04002031 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2032}
2033
2034bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
2035 GLuint id,
2036 GLenum pname,
2037 GLsizei bufSize,
2038 GLsizei *length,
2039 GLint64 *params)
2040{
2041 if (!context->getExtensions().disjointTimerQuery)
2042 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002043 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002044 return false;
2045 }
2046
2047 if (!ValidateRobustEntryPoint(context, bufSize))
2048 {
2049 return false;
2050 }
2051
2052 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2053 {
2054 return false;
2055 }
2056
2057 if (!ValidateRobustBufferSize(context, bufSize, *length))
2058 {
2059 return false;
2060 }
2061
2062 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002063}
2064
2065bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
2066{
2067 if (!context->getExtensions().disjointTimerQuery)
2068 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002069 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002070 return false;
2071 }
Geoff Lang2186c382016-10-14 10:54:54 -04002072 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
2073}
2074
2075bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
2076 GLuint id,
2077 GLenum pname,
2078 GLsizei bufSize,
2079 GLsizei *length,
2080 GLuint64 *params)
2081{
2082 if (!context->getExtensions().disjointTimerQuery)
2083 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002084 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04002085 return false;
2086 }
2087
2088 if (!ValidateRobustEntryPoint(context, bufSize))
2089 {
2090 return false;
2091 }
2092
2093 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
2094 {
2095 return false;
2096 }
2097
2098 if (!ValidateRobustBufferSize(context, bufSize, *length))
2099 {
2100 return false;
2101 }
2102
2103 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05002104}
2105
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002106bool ValidateProgramUniform(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002107 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002108 GLuint program,
2109 GLint location,
2110 GLsizei count)
2111{
2112 // Check for ES31 program uniform entry points
2113 if (context->getClientVersion() < Version(3, 1))
2114 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002115 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002116 return false;
2117 }
2118
2119 const LinkedUniform *uniform = nullptr;
2120 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002121 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2122 ValidateUniformValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002123}
2124
Frank Henigmana98a6472017-02-02 21:38:32 -05002125bool ValidateProgramUniform1iv(gl::Context *context,
2126 GLuint program,
2127 GLint location,
2128 GLsizei count,
2129 const GLint *value)
2130{
2131 // Check for ES31 program uniform entry points
2132 if (context->getClientVersion() < Version(3, 1))
2133 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002134 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Frank Henigmana98a6472017-02-02 21:38:32 -05002135 return false;
2136 }
2137
2138 const LinkedUniform *uniform = nullptr;
2139 gl::Program *programObject = GetValidProgram(context, program);
2140 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2141 ValidateUniform1ivValue(context, uniform->type, count, value);
2142}
2143
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002144bool ValidateProgramUniformMatrix(gl::Context *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002145 GLenum valueType,
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002146 GLuint program,
2147 GLint location,
2148 GLsizei count,
2149 GLboolean transpose)
2150{
2151 // Check for ES31 program uniform entry points
2152 if (context->getClientVersion() < Version(3, 1))
2153 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002154 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002155 return false;
2156 }
2157
2158 const LinkedUniform *uniform = nullptr;
2159 gl::Program *programObject = GetValidProgram(context, program);
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002160 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2161 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002162}
2163
Jamie Madillc1d770e2017-04-13 17:31:24 -04002164bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002165{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002166 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002167 gl::Program *programObject = context->getGLState().getProgram();
2168 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2169 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002170}
2171
Jamie Madillbe849e42017-05-02 15:49:00 -04002172bool ValidateUniform1iv(ValidationContext *context,
2173 GLint location,
2174 GLsizei count,
2175 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002176{
2177 const LinkedUniform *uniform = nullptr;
2178 gl::Program *programObject = context->getGLState().getProgram();
2179 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2180 ValidateUniform1ivValue(context, uniform->type, count, value);
2181}
2182
Jamie Madillc1d770e2017-04-13 17:31:24 -04002183bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002184 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002185 GLint location,
2186 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002187 GLboolean transpose)
2188{
Geoff Lang92019432017-11-20 13:09:34 -05002189 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002190 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002191 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002192 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002193 }
2194
Jamie Madill62d31cb2015-09-11 13:25:51 -04002195 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002196 gl::Program *programObject = context->getGLState().getProgram();
2197 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2198 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002199}
2200
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002201bool ValidateStateQuery(ValidationContext *context,
2202 GLenum pname,
2203 GLenum *nativeType,
2204 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002205{
2206 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2207 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002208 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002209 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002210 }
2211
Jamie Madill0af26e12015-03-05 19:54:33 -05002212 const Caps &caps = context->getCaps();
2213
Jamie Madill893ab082014-05-16 16:56:10 -04002214 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2215 {
2216 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2217
Jamie Madill0af26e12015-03-05 19:54:33 -05002218 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002219 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002220 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002221 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002222 }
2223 }
2224
2225 switch (pname)
2226 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002227 case GL_TEXTURE_BINDING_2D:
2228 case GL_TEXTURE_BINDING_CUBE_MAP:
2229 case GL_TEXTURE_BINDING_3D:
2230 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002231 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002232 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002233 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2234 if (!context->getExtensions().textureRectangle)
2235 {
2236 context->handleError(InvalidEnum()
2237 << "ANGLE_texture_rectangle extension not present");
2238 return false;
2239 }
2240 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002241 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2242 if (!context->getExtensions().eglStreamConsumerExternal &&
2243 !context->getExtensions().eglImageExternal)
2244 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002245 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2246 "nor GL_OES_EGL_image_external "
2247 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002248 return false;
2249 }
2250 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002251
He Yunchaoced53ae2016-11-29 15:00:51 +08002252 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2253 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002254 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002255 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2256 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002257 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002258 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002259 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002260 }
2261
Jamie Madill51f40ec2016-06-15 14:06:00 -04002262 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2263 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002264
2265 if (framebuffer->getReadBufferState() == GL_NONE)
2266 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002267 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002268 return false;
2269 }
2270
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002271 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002272 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002273 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002274 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002275 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002276 }
2277 }
2278 break;
2279
He Yunchaoced53ae2016-11-29 15:00:51 +08002280 default:
2281 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002282 }
2283
2284 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002285 if (*numParams == 0)
2286 {
2287 return false;
2288 }
2289
2290 return true;
2291}
2292
2293bool ValidateRobustStateQuery(ValidationContext *context,
2294 GLenum pname,
2295 GLsizei bufSize,
2296 GLenum *nativeType,
2297 unsigned int *numParams)
2298{
2299 if (!ValidateRobustEntryPoint(context, bufSize))
2300 {
2301 return false;
2302 }
2303
2304 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2305 {
2306 return false;
2307 }
2308
2309 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002310 {
2311 return false;
2312 }
2313
2314 return true;
2315}
2316
Jamie Madillc29968b2016-01-20 11:17:23 -05002317bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2318 GLenum target,
2319 GLint level,
2320 GLenum internalformat,
2321 bool isSubImage,
2322 GLint xoffset,
2323 GLint yoffset,
2324 GLint zoffset,
2325 GLint x,
2326 GLint y,
2327 GLsizei width,
2328 GLsizei height,
2329 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002330 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002331{
Brandon Jones6cad5662017-06-14 13:25:13 -07002332 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002333 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002334 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2335 return false;
2336 }
2337
2338 if (width < 0 || height < 0)
2339 {
2340 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002341 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002342 }
2343
He Yunchaoced53ae2016-11-29 15:00:51 +08002344 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2345 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002346 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002347 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002348 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002349 }
2350
2351 if (border != 0)
2352 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002353 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002354 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002355 }
2356
2357 if (!ValidMipLevel(context, target, level))
2358 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002359 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002360 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002361 }
2362
Jamie Madill51f40ec2016-06-15 14:06:00 -04002363 const auto &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002364 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002365 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002366 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002367 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002368 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002369 }
2370
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002371 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002372 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002373 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002374 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002375 }
2376
Martin Radev138064f2016-07-15 12:03:41 +03002377 if (readFramebuffer->getReadBufferState() == GL_NONE)
2378 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002379 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002380 return false;
2381 }
2382
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002383 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2384 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002385 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002386 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002387 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2388 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002389 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002390 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002391 return false;
2392 }
2393
Martin Radev04e2c3b2017-07-27 16:54:35 +03002394 // ANGLE_multiview spec, Revision 1:
2395 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2396 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2397 // is not NONE.
2398 if (source->getMultiviewLayout() != GL_NONE)
2399 {
2400 context->handleError(InvalidFramebufferOperation()
2401 << "The active read framebuffer object has multiview attachments.");
2402 return false;
2403 }
2404
Geoff Langaae65a42014-05-26 12:43:44 -04002405 const gl::Caps &caps = context->getCaps();
2406
Geoff Langaae65a42014-05-26 12:43:44 -04002407 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002408 switch (target)
2409 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002410 case GL_TEXTURE_2D:
2411 maxDimension = caps.max2DTextureSize;
2412 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002413
He Yunchaoced53ae2016-11-29 15:00:51 +08002414 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2415 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2416 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2417 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2418 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2419 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2420 maxDimension = caps.maxCubeMapTextureSize;
2421 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002422
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002423 case GL_TEXTURE_RECTANGLE_ANGLE:
2424 maxDimension = caps.maxRectangleTextureSize;
2425 break;
2426
He Yunchaoced53ae2016-11-29 15:00:51 +08002427 case GL_TEXTURE_2D_ARRAY:
2428 maxDimension = caps.max2DTextureSize;
2429 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002430
He Yunchaoced53ae2016-11-29 15:00:51 +08002431 case GL_TEXTURE_3D:
2432 maxDimension = caps.max3DTextureSize;
2433 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002434
He Yunchaoced53ae2016-11-29 15:00:51 +08002435 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002436 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002437 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002438 }
2439
Jamie Madillc29968b2016-01-20 11:17:23 -05002440 gl::Texture *texture =
2441 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002442 if (!texture)
2443 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002444 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002445 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002446 }
2447
Geoff Lang69cce582015-09-17 13:20:36 -04002448 if (texture->getImmutableFormat() && !isSubImage)
Jamie Madill560a8d82014-05-21 13:06:20 -04002449 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002450 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002451 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002452 }
2453
Geoff Langca271392017-04-05 12:30:00 -04002454 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002455 isSubImage ? *texture->getFormat(target, level).info
2456 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002457
Geoff Lang966c9402017-04-18 12:38:27 -04002458 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002459 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002460 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002461 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002462 }
2463
2464 if (isSubImage)
2465 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002466 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2467 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2468 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002469 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002470 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002471 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002472 }
2473 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002474 else
2475 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002476 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002477 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002478 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002479 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002480 }
2481
Geoff Langeb66a6e2016-10-31 13:06:12 -04002482 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002483 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002484 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002485 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002486 }
2487
2488 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002489 if (static_cast<int>(width) > maxLevelDimension ||
2490 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002491 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002492 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002493 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002494 }
2495 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002496
Jamie Madill0c8abca2016-07-22 20:21:26 -04002497 if (textureFormatOut)
2498 {
2499 *textureFormatOut = texture->getFormat(target, level);
2500 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002501
2502 // Detect texture copying feedback loops for WebGL.
2503 if (context->getExtensions().webglCompatibility)
2504 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002505 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002506 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002507 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002508 return false;
2509 }
2510 }
2511
Jamie Madill560a8d82014-05-21 13:06:20 -04002512 return true;
2513}
2514
Jiajia Qind9671222016-11-29 16:30:31 +08002515bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002516{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002517 switch (mode)
2518 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002519 case GL_POINTS:
2520 case GL_LINES:
2521 case GL_LINE_LOOP:
2522 case GL_LINE_STRIP:
2523 case GL_TRIANGLES:
2524 case GL_TRIANGLE_STRIP:
2525 case GL_TRIANGLE_FAN:
2526 break;
2527 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002528 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002529 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002530 }
2531
Jamie Madill250d33f2014-06-06 17:09:03 -04002532 if (count < 0)
2533 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002534 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002535 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002536 }
2537
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002538 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002539
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002540 const Extensions &extensions = context->getExtensions();
2541
2542 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2543 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2544 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2545 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002546 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002547 // Check for mapped buffers
2548 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002549 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002550 {
2551 context->handleError(InvalidOperation());
2552 return false;
2553 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002554 }
2555
Jamie Madillcbcde722017-01-06 14:50:00 -05002556 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2557 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002558 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002559 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002560 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002561 const FramebufferAttachment *dsAttachment =
2562 framebuffer->getStencilOrDepthStencilAttachment();
2563 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002564 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002565 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002566
2567 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2568 bool differentWritemasks =
2569 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2570 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2571 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2572 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2573
2574 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002575 {
Martin Radevffe754b2017-07-31 10:38:07 +03002576 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002577 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002578 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2579 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002580 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002581 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002582 return false;
2583 }
Jamie Madillac528012014-06-20 13:21:23 -04002584 }
2585
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002586 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002587 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002588 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002589 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002590 }
2591
Geoff Lang7dd2e102014-11-10 15:19:26 -05002592 gl::Program *program = state.getProgram();
2593 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002594 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002595 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002596 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002597 }
2598
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002599 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002600 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002601 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002602 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002603 }
2604
Martin Radevffe754b2017-07-31 10:38:07 +03002605 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002606 {
Martin Radevda8e2572017-09-12 17:21:16 +03002607 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002608 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002609 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002610 {
2611 context->handleError(InvalidOperation() << "The number of views in the active program "
2612 "and draw framebuffer does not match.");
2613 return false;
2614 }
Martin Radev7e69f762017-07-27 14:54:13 +03002615
2616 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2617 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2618 framebufferNumViews > 1)
2619 {
2620 context->handleError(InvalidOperation()
2621 << "There is an active transform feedback object "
2622 "when the number of views in the active draw "
2623 "framebuffer is greater than 1.");
2624 return false;
2625 }
Martin Radevffe754b2017-07-31 10:38:07 +03002626
2627 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2628 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2629 {
2630 context->handleError(InvalidOperation() << "There is an active query for target "
2631 "GL_TIME_ELAPSED_EXT when the number of "
2632 "views in the active draw framebuffer is "
2633 "greater than 1.");
2634 return false;
2635 }
Martin Radev7cf61662017-07-26 17:10:53 +03002636 }
2637
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002638 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002639 for (unsigned int uniformBlockIndex = 0;
2640 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002641 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002642 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002643 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002644 const OffsetBindingPointer<Buffer> &uniformBuffer =
2645 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002646
Geoff Lang5d124a62015-09-15 13:03:27 -04002647 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002648 {
2649 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002650 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002651 InvalidOperation()
2652 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002653 return false;
2654 }
2655
Geoff Lang5d124a62015-09-15 13:03:27 -04002656 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002657 if (uniformBufferSize == 0)
2658 {
2659 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002660 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002661 }
2662
Jamie Madill62d31cb2015-09-11 13:25:51 -04002663 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002664 {
2665 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002666 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002667 InvalidOperation()
2668 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002669 return false;
2670 }
2671 }
2672
Geoff Lange0cff192017-05-30 13:04:56 -04002673 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002674 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002675 {
Geoff Lange0cff192017-05-30 13:04:56 -04002676 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002677 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2678 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002679 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002680 return false;
2681 }
Geoff Lange0cff192017-05-30 13:04:56 -04002682
Geoff Lang9ab5b822017-05-30 16:19:23 -04002683 // Detect that the vertex shader input types match the attribute types
2684 if (!ValidateVertexShaderAttributeTypeMatch(context))
2685 {
2686 return false;
2687 }
2688
Geoff Lange0cff192017-05-30 13:04:56 -04002689 // Detect that the color buffer types match the fragment shader output types
2690 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2691 {
2692 return false;
2693 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002694 }
2695
Jamie Madill250d33f2014-06-06 17:09:03 -04002696 // No-op if zero count
2697 return (count > 0);
2698}
2699
Jamie Madillc1d770e2017-04-13 17:31:24 -04002700bool ValidateDrawArraysCommon(ValidationContext *context,
2701 GLenum mode,
2702 GLint first,
2703 GLsizei count,
2704 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002705{
Jamie Madillfd716582014-06-06 17:09:04 -04002706 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002707 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002708 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002709 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002710 }
2711
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002712 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002713 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002714 if (curTransformFeedback && curTransformFeedback->isActive() &&
2715 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002716 {
2717 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002718 // that does not match the current transform feedback object's draw mode (if transform
2719 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002720 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002721 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002722 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002723 }
2724
Jiajia Qind9671222016-11-29 16:30:31 +08002725 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002726 {
2727 return false;
2728 }
2729
Corentin Wallez71168a02016-12-19 15:11:18 -08002730 // Check the computation of maxVertex doesn't overflow.
2731 // - first < 0 or count < 0 have been checked as an error condition
2732 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2733 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2734 ASSERT(count > 0 && first >= 0);
2735 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2736 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002737 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002738 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002739 return false;
2740 }
2741
Corentin Wallez71168a02016-12-19 15:11:18 -08002742 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002743 {
2744 return false;
2745 }
2746
2747 return true;
2748}
2749
He Yunchaoced53ae2016-11-29 15:00:51 +08002750bool ValidateDrawArraysInstancedANGLE(Context *context,
2751 GLenum mode,
2752 GLint first,
2753 GLsizei count,
2754 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002755{
Geoff Lang63c5a592017-09-27 14:08:16 -04002756 if (!context->getExtensions().instancedArrays)
2757 {
2758 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2759 return false;
2760 }
2761
Corentin Wallez170efbf2017-05-02 13:45:01 -04002762 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002763 {
2764 return false;
2765 }
2766
Corentin Wallez0dc97812017-06-22 14:38:44 -04002767 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002768}
2769
Jiajia Qind9671222016-11-29 16:30:31 +08002770bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002771{
Jamie Madill250d33f2014-06-06 17:09:03 -04002772 switch (type)
2773 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002774 case GL_UNSIGNED_BYTE:
2775 case GL_UNSIGNED_SHORT:
2776 break;
2777 case GL_UNSIGNED_INT:
2778 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2779 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002780 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002781 return false;
2782 }
2783 break;
2784 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002785 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002786 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002787 }
2788
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002789 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002790
2791 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002792 if (curTransformFeedback && curTransformFeedback->isActive() &&
2793 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002794 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002795 // It is an invalid operation to call DrawElements, DrawRangeElements or
2796 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002797 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002798 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002799 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002800 }
2801
Jiajia Qind9671222016-11-29 16:30:31 +08002802 return true;
2803}
2804
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002805bool ValidateDrawElementsCommon(ValidationContext *context,
2806 GLenum mode,
2807 GLsizei count,
2808 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002809 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002810 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002811{
2812 if (!ValidateDrawElementsBase(context, type))
2813 return false;
2814
2815 const State &state = context->getGLState();
2816
Corentin Wallez170efbf2017-05-02 13:45:01 -04002817 if (!ValidateDrawBase(context, mode, count))
2818 {
2819 return false;
2820 }
2821
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002822 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2823 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2824 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2825 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002826 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002827 // Check for mapped buffers
2828 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002829 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002830 {
2831 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2832 return false;
2833 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002834 }
2835
He Yunchaoced53ae2016-11-29 15:00:51 +08002836 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002837 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002838
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002839 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2840
2841 if (context->getExtensions().webglCompatibility)
2842 {
2843 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2844 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2845 {
2846 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2847 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2848 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002849 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002850 return false;
2851 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002852
2853 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2854 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2855 // error is generated.
2856 if (reinterpret_cast<intptr_t>(indices) < 0)
2857 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002858 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002859 return false;
2860 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002861 }
2862
2863 if (context->getExtensions().webglCompatibility ||
2864 !context->getGLState().areClientArraysEnabled())
2865 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002866 if (!elementArrayBuffer && count > 0)
2867 {
2868 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2869 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2870 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002871 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002872 return false;
2873 }
2874 }
2875
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002876 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002877 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002878 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002879 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002880 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2881 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2882 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2883 constexpr uint64_t kMaxTypeSize = 8;
2884 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2885 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2886 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002887
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002888 uint64_t typeSize = typeBytes;
2889 uint64_t elementCount = static_cast<uint64_t>(count);
2890 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2891
2892 // Doing the multiplication here is overflow-safe
2893 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2894
2895 // The offset can be any value, check for overflows
2896 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2897 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002898 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002899 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002900 return false;
2901 }
2902
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002903 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2904 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002905 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002906 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002907 return false;
2908 }
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002909
Corentin Wallez487653b2017-09-01 17:17:55 -04002910 ASSERT(isPow2(typeSize) && typeSize > 0);
2911 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002912 {
2913 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
2914 return false;
2915 }
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002916 }
2917 else if (!indices)
2918 {
2919 // This is an application error that would normally result in a crash,
2920 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002921 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04002922 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002923 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002924 }
2925
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002926 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002927 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002928 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2929 // access is enabled.
2930 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2931 {
2932 return false;
2933 }
2934 }
2935 else
2936 {
2937 // Use the parameter buffer to retrieve and cache the index range.
2938 const auto &params = context->getParams<HasIndexRange>();
2939 const auto &indexRangeOpt = params.getIndexRange();
2940 if (!indexRangeOpt.valid())
2941 {
2942 // Unexpected error.
2943 return false;
2944 }
2945
2946 // If we use an index greater than our maximum supported index range, return an error.
2947 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2948 // return an error if possible here.
2949 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2950 {
2951 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2952 return false;
2953 }
2954
2955 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2956 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2957 {
2958 return false;
2959 }
2960
2961 // No op if there are no real indices in the index data (all are primitive restart).
2962 return (indexRangeOpt.value().vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002963 }
2964
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002965 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002966}
2967
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002968bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2969 GLenum mode,
2970 GLsizei count,
2971 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002972 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002973 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002974{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002975 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002976}
2977
Geoff Lang3edfe032015-09-04 16:38:24 -04002978bool ValidateDrawElementsInstancedANGLE(Context *context,
2979 GLenum mode,
2980 GLsizei count,
2981 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002982 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002983 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002984{
Geoff Lang63c5a592017-09-27 14:08:16 -04002985 if (!context->getExtensions().instancedArrays)
2986 {
2987 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2988 return false;
2989 }
2990
Corentin Wallez170efbf2017-05-02 13:45:01 -04002991 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002992 {
2993 return false;
2994 }
2995
Corentin Wallez0dc97812017-06-22 14:38:44 -04002996 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002997}
2998
He Yunchaoced53ae2016-11-29 15:00:51 +08002999bool ValidateFramebufferTextureBase(Context *context,
3000 GLenum target,
3001 GLenum attachment,
3002 GLuint texture,
3003 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04003004{
Geoff Lange8afa902017-09-27 15:00:43 -04003005 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04003006 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003007 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003008 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003009 }
3010
3011 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04003012 {
3013 return false;
3014 }
3015
Jamie Madill55ec3b12014-07-03 10:38:57 -04003016 if (texture != 0)
3017 {
3018 gl::Texture *tex = context->getTexture(texture);
3019
Jamie Madillbe849e42017-05-02 15:49:00 -04003020 if (tex == NULL)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003021 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003022 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003023 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003024 }
3025
3026 if (level < 0)
3027 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003028 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003029 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003030 }
3031 }
3032
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003033 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04003034 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04003035
Jamie Madill84115c92015-04-23 15:00:07 -04003036 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04003037 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003038 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04003039 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04003040 }
3041
3042 return true;
3043}
3044
Geoff Langb1196682014-07-23 13:47:29 -04003045bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04003046{
3047 if (program == 0)
3048 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003049 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04003050 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003051 }
3052
Dian Xiang769769a2015-09-09 15:20:08 -07003053 gl::Program *programObject = GetValidProgram(context, program);
3054 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05003055 {
3056 return false;
3057 }
3058
Jamie Madill0063c512014-08-25 15:47:53 -04003059 if (!programObject || !programObject->isLinked())
3060 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003061 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04003062 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003063 }
3064
Geoff Lang7dd2e102014-11-10 15:19:26 -05003065 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003066 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003067 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003068 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003069 }
3070
Jamie Madill0063c512014-08-25 15:47:53 -04003071 return true;
3072}
3073
Geoff Langf41d0ee2016-10-07 13:04:23 -04003074static bool ValidateSizedGetUniform(Context *context,
3075 GLuint program,
3076 GLint location,
3077 GLsizei bufSize,
3078 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003079{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003080 if (length)
3081 {
3082 *length = 0;
3083 }
3084
Jamie Madill78f41802014-08-25 15:47:55 -04003085 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003086 {
Jamie Madill78f41802014-08-25 15:47:55 -04003087 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003088 }
3089
Geoff Langf41d0ee2016-10-07 13:04:23 -04003090 if (bufSize < 0)
3091 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003092 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003093 return false;
3094 }
3095
Jamie Madilla502c742014-08-28 17:19:13 -04003096 gl::Program *programObject = context->getProgram(program);
3097 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003098
Jamie Madill78f41802014-08-25 15:47:55 -04003099 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003100 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003101 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003102 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003103 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003104 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003105 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003106 }
3107
Geoff Langf41d0ee2016-10-07 13:04:23 -04003108 if (length)
3109 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003110 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003111 }
3112
Jamie Madill0063c512014-08-25 15:47:53 -04003113 return true;
3114}
3115
He Yunchaoced53ae2016-11-29 15:00:51 +08003116bool ValidateGetnUniformfvEXT(Context *context,
3117 GLuint program,
3118 GLint location,
3119 GLsizei bufSize,
3120 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003121{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003122 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003123}
3124
He Yunchaoced53ae2016-11-29 15:00:51 +08003125bool ValidateGetnUniformivEXT(Context *context,
3126 GLuint program,
3127 GLint location,
3128 GLsizei bufSize,
3129 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003130{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003131 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3132}
3133
3134bool ValidateGetUniformfvRobustANGLE(Context *context,
3135 GLuint program,
3136 GLint location,
3137 GLsizei bufSize,
3138 GLsizei *length,
3139 GLfloat *params)
3140{
3141 if (!ValidateRobustEntryPoint(context, bufSize))
3142 {
3143 return false;
3144 }
3145
3146 // bufSize is validated in ValidateSizedGetUniform
3147 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3148}
3149
3150bool ValidateGetUniformivRobustANGLE(Context *context,
3151 GLuint program,
3152 GLint location,
3153 GLsizei bufSize,
3154 GLsizei *length,
3155 GLint *params)
3156{
3157 if (!ValidateRobustEntryPoint(context, bufSize))
3158 {
3159 return false;
3160 }
3161
3162 // bufSize is validated in ValidateSizedGetUniform
3163 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3164}
3165
3166bool ValidateGetUniformuivRobustANGLE(Context *context,
3167 GLuint program,
3168 GLint location,
3169 GLsizei bufSize,
3170 GLsizei *length,
3171 GLuint *params)
3172{
3173 if (!ValidateRobustEntryPoint(context, bufSize))
3174 {
3175 return false;
3176 }
3177
3178 if (context->getClientMajorVersion() < 3)
3179 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003180 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003181 return false;
3182 }
3183
3184 // bufSize is validated in ValidateSizedGetUniform
3185 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003186}
3187
He Yunchaoced53ae2016-11-29 15:00:51 +08003188bool ValidateDiscardFramebufferBase(Context *context,
3189 GLenum target,
3190 GLsizei numAttachments,
3191 const GLenum *attachments,
3192 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003193{
3194 if (numAttachments < 0)
3195 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003196 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003197 return false;
3198 }
3199
3200 for (GLsizei i = 0; i < numAttachments; ++i)
3201 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003202 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003203 {
3204 if (defaultFramebuffer)
3205 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003206 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003207 return false;
3208 }
3209
3210 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3211 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003212 context->handleError(InvalidOperation() << "Requested color attachment is "
3213 "greater than the maximum supported "
3214 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003215 return false;
3216 }
3217 }
3218 else
3219 {
3220 switch (attachments[i])
3221 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003222 case GL_DEPTH_ATTACHMENT:
3223 case GL_STENCIL_ATTACHMENT:
3224 case GL_DEPTH_STENCIL_ATTACHMENT:
3225 if (defaultFramebuffer)
3226 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003227 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3228 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003229 return false;
3230 }
3231 break;
3232 case GL_COLOR:
3233 case GL_DEPTH:
3234 case GL_STENCIL:
3235 if (!defaultFramebuffer)
3236 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003237 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3238 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003239 return false;
3240 }
3241 break;
3242 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003243 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003244 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003245 }
3246 }
3247 }
3248
3249 return true;
3250}
3251
Austin Kinross6ee1e782015-05-29 17:05:37 -07003252bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3253{
3254 // Note that debug marker calls must not set error state
3255
3256 if (length < 0)
3257 {
3258 return false;
3259 }
3260
3261 if (marker == nullptr)
3262 {
3263 return false;
3264 }
3265
3266 return true;
3267}
3268
3269bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3270{
3271 // Note that debug marker calls must not set error state
3272
3273 if (length < 0)
3274 {
3275 return false;
3276 }
3277
3278 if (length > 0 && marker == nullptr)
3279 {
3280 return false;
3281 }
3282
3283 return true;
3284}
3285
Geoff Langdcab33b2015-07-21 13:03:16 -04003286bool ValidateEGLImageTargetTexture2DOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003287 GLenum target,
3288 egl::Image *image)
3289{
Geoff Langa8406172015-07-21 16:53:39 -04003290 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3291 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003292 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003293 return false;
3294 }
3295
3296 switch (target)
3297 {
3298 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003299 if (!context->getExtensions().eglImage)
3300 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003301 context->handleError(InvalidEnum()
3302 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003303 }
3304 break;
3305
3306 case GL_TEXTURE_EXTERNAL_OES:
3307 if (!context->getExtensions().eglImageExternal)
3308 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003309 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3310 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003311 }
Geoff Langa8406172015-07-21 16:53:39 -04003312 break;
3313
3314 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003315 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003316 return false;
3317 }
3318
Jamie Madill61e16b42017-06-19 11:13:23 -04003319 ASSERT(context->getCurrentDisplay());
3320 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003321 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003322 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003323 return false;
3324 }
3325
3326 if (image->getSamples() > 0)
3327 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003328 context->handleError(InvalidOperation()
3329 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003330 return false;
3331 }
3332
Geoff Langca271392017-04-05 12:30:00 -04003333 const TextureCaps &textureCaps =
3334 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003335 if (!textureCaps.texturable)
3336 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003337 context->handleError(InvalidOperation()
3338 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003339 return false;
3340 }
3341
Geoff Langdcab33b2015-07-21 13:03:16 -04003342 return true;
3343}
3344
3345bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003346 GLenum target,
3347 egl::Image *image)
3348{
Geoff Langa8406172015-07-21 16:53:39 -04003349 if (!context->getExtensions().eglImage)
3350 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003351 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003352 return false;
3353 }
3354
3355 switch (target)
3356 {
3357 case GL_RENDERBUFFER:
3358 break;
3359
3360 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003361 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003362 return false;
3363 }
3364
Jamie Madill61e16b42017-06-19 11:13:23 -04003365 ASSERT(context->getCurrentDisplay());
3366 if (!context->getCurrentDisplay()->isValidImage(image))
Geoff Langa8406172015-07-21 16:53:39 -04003367 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003368 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003369 return false;
3370 }
3371
Geoff Langca271392017-04-05 12:30:00 -04003372 const TextureCaps &textureCaps =
3373 context->getTextureCaps().get(image->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003374 if (!textureCaps.renderable)
3375 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003376 context->handleError(InvalidOperation()
3377 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003378 return false;
3379 }
3380
Geoff Langdcab33b2015-07-21 13:03:16 -04003381 return true;
3382}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003383
3384bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3385{
Geoff Lang36167ab2015-12-07 10:27:14 -05003386 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003387 {
3388 // The default VAO should always exist
3389 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003390 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003391 return false;
3392 }
3393
3394 return true;
3395}
3396
Geoff Langc5629752015-12-07 16:29:04 -05003397bool ValidateProgramBinaryBase(Context *context,
3398 GLuint program,
3399 GLenum binaryFormat,
3400 const void *binary,
3401 GLint length)
3402{
3403 Program *programObject = GetValidProgram(context, program);
3404 if (programObject == nullptr)
3405 {
3406 return false;
3407 }
3408
3409 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3410 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3411 programBinaryFormats.end())
3412 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003413 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003414 return false;
3415 }
3416
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003417 if (context->hasActiveTransformFeedback(program))
3418 {
3419 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003420 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3421 "is associated with an active transform "
3422 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003423 return false;
3424 }
3425
Geoff Langc5629752015-12-07 16:29:04 -05003426 return true;
3427}
3428
3429bool ValidateGetProgramBinaryBase(Context *context,
3430 GLuint program,
3431 GLsizei bufSize,
3432 GLsizei *length,
3433 GLenum *binaryFormat,
3434 void *binary)
3435{
3436 Program *programObject = GetValidProgram(context, program);
3437 if (programObject == nullptr)
3438 {
3439 return false;
3440 }
3441
3442 if (!programObject->isLinked())
3443 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003444 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003445 return false;
3446 }
3447
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003448 if (context->getCaps().programBinaryFormats.empty())
3449 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003450 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003451 return false;
3452 }
3453
Geoff Langc5629752015-12-07 16:29:04 -05003454 return true;
3455}
Jamie Madillc29968b2016-01-20 11:17:23 -05003456
Jamie Madillc29968b2016-01-20 11:17:23 -05003457bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3458{
3459 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003460 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003461 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003462 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3463 return false;
3464 }
3465 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3466 {
3467 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003468 return false;
3469 }
3470
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003471 ASSERT(context->getGLState().getDrawFramebuffer());
3472 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003473 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3474
3475 // This should come first before the check for the default frame buffer
3476 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3477 // rather than INVALID_OPERATION
3478 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3479 {
3480 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3481
3482 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003483 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3484 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003485 {
3486 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003487 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3488 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3489 // 3.1 is still a bit ambiguous about the error, but future specs are
3490 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003491 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003492 return false;
3493 }
3494 else if (bufs[colorAttachment] >= maxColorAttachment)
3495 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003496 context->handleError(InvalidOperation()
3497 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003498 return false;
3499 }
3500 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3501 frameBufferId != 0)
3502 {
3503 // INVALID_OPERATION-GL is bound to buffer and ith argument
3504 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003505 context->handleError(InvalidOperation()
3506 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003507 return false;
3508 }
3509 }
3510
3511 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3512 // and n is not 1 or bufs is bound to value other than BACK and NONE
3513 if (frameBufferId == 0)
3514 {
3515 if (n != 1)
3516 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003517 context->handleError(InvalidOperation()
3518 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003519 return false;
3520 }
3521
3522 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3523 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003524 context->handleError(
3525 InvalidOperation()
3526 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003527 return false;
3528 }
3529 }
3530
3531 return true;
3532}
3533
Geoff Lang496c02d2016-10-20 11:38:11 -07003534bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003535 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003536 GLenum pname,
3537 GLsizei *length,
3538 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003539{
Geoff Lang496c02d2016-10-20 11:38:11 -07003540 if (length)
3541 {
3542 *length = 0;
3543 }
3544
3545 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3546 {
3547 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003548 InvalidOperation()
3549 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003550 return false;
3551 }
3552
Corentin Wallez336129f2017-10-17 15:55:40 -04003553 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003554 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003555 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003556 return false;
3557 }
3558
Geoff Lang496c02d2016-10-20 11:38:11 -07003559 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003560 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003561 case GL_BUFFER_MAP_POINTER:
3562 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003563
Geoff Lang496c02d2016-10-20 11:38:11 -07003564 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003565 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003566 return false;
3567 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003568
3569 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3570 // target bound to zero generate an INVALID_OPERATION error."
3571 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003572 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003573 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003574 context->handleError(InvalidOperation()
3575 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003576 return false;
3577 }
3578
Geoff Lang496c02d2016-10-20 11:38:11 -07003579 if (length)
3580 {
3581 *length = 1;
3582 }
3583
Olli Etuaho4f667482016-03-30 15:56:35 +03003584 return true;
3585}
3586
Corentin Wallez336129f2017-10-17 15:55:40 -04003587bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003588{
Corentin Wallez336129f2017-10-17 15:55:40 -04003589 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003590 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003591 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003592 return false;
3593 }
3594
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003595 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003596
3597 if (buffer == nullptr || !buffer->isMapped())
3598 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003599 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003600 return false;
3601 }
3602
3603 return true;
3604}
3605
3606bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003607 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003608 GLintptr offset,
3609 GLsizeiptr length,
3610 GLbitfield access)
3611{
Corentin Wallez336129f2017-10-17 15:55:40 -04003612 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003613 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003614 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003615 return false;
3616 }
3617
Brandon Jones6cad5662017-06-14 13:25:13 -07003618 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003619 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003620 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3621 return false;
3622 }
3623
3624 if (length < 0)
3625 {
3626 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003627 return false;
3628 }
3629
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003630 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003631
3632 if (!buffer)
3633 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003634 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003635 return false;
3636 }
3637
3638 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003639 CheckedNumeric<size_t> checkedOffset(offset);
3640 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003641
Jamie Madille2e406c2016-06-02 13:04:10 -04003642 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003643 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003644 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003645 return false;
3646 }
3647
3648 // Check for invalid bits in the mask
3649 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3650 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3651 GL_MAP_UNSYNCHRONIZED_BIT;
3652
3653 if (access & ~(allAccessBits))
3654 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003655 context->handleError(InvalidValue()
3656 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003657 return false;
3658 }
3659
3660 if (length == 0)
3661 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003662 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003663 return false;
3664 }
3665
3666 if (buffer->isMapped())
3667 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003668 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003669 return false;
3670 }
3671
3672 // Check for invalid bit combinations
3673 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3674 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003675 context->handleError(InvalidOperation()
3676 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003677 return false;
3678 }
3679
3680 GLbitfield writeOnlyBits =
3681 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3682
3683 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3684 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003685 context->handleError(InvalidOperation()
3686 << "Invalid access bits when mapping buffer for reading: 0x"
3687 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003688 return false;
3689 }
3690
3691 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3692 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003693 context->handleError(
3694 InvalidOperation()
3695 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003696 return false;
3697 }
Geoff Lang79f71042017-08-14 16:43:43 -04003698
3699 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003700}
3701
3702bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003703 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003704 GLintptr offset,
3705 GLsizeiptr length)
3706{
Brandon Jones6cad5662017-06-14 13:25:13 -07003707 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003708 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003709 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3710 return false;
3711 }
3712
3713 if (length < 0)
3714 {
3715 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003716 return false;
3717 }
3718
Corentin Wallez336129f2017-10-17 15:55:40 -04003719 if (!ValidBufferType(context, target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003720 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003721 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003722 return false;
3723 }
3724
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003725 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003726
3727 if (buffer == nullptr)
3728 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003729 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003730 return false;
3731 }
3732
3733 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3734 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003735 context->handleError(InvalidOperation()
3736 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003737 return false;
3738 }
3739
3740 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003741 CheckedNumeric<size_t> checkedOffset(offset);
3742 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003743
Jamie Madille2e406c2016-06-02 13:04:10 -04003744 if (!checkedSize.IsValid() ||
3745 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003746 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003747 context->handleError(InvalidValue()
3748 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003749 return false;
3750 }
3751
3752 return true;
3753}
3754
Olli Etuaho41997e72016-03-10 13:38:39 +02003755bool ValidateGenOrDelete(Context *context, GLint n)
3756{
3757 if (n < 0)
3758 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003759 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003760 return false;
3761 }
3762 return true;
3763}
3764
Geoff Langff5b2d52016-09-07 11:32:23 -04003765bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3766{
3767 if (!context->getExtensions().robustClientMemory)
3768 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003769 context->handleError(InvalidOperation()
3770 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003771 return false;
3772 }
3773
3774 if (bufSize < 0)
3775 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003776 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003777 return false;
3778 }
3779
3780 return true;
3781}
3782
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003783bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3784{
3785 if (bufSize < numParams)
3786 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003787 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3788 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003789 return false;
3790 }
3791
3792 return true;
3793}
3794
Jamie Madillbe849e42017-05-02 15:49:00 -04003795bool ValidateGetFramebufferAttachmentParameterivBase(ValidationContext *context,
3796 GLenum target,
3797 GLenum attachment,
3798 GLenum pname,
3799 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003800{
Geoff Lange8afa902017-09-27 15:00:43 -04003801 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003802 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003803 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003804 return false;
3805 }
3806
3807 int clientVersion = context->getClientMajorVersion();
3808
3809 switch (pname)
3810 {
3811 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3812 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3813 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3814 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3815 break;
3816
Martin Radeve5285d22017-07-14 16:23:53 +03003817 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3818 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3819 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3820 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3821 if (clientVersion < 3 || !context->getExtensions().multiview)
3822 {
3823 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3824 return false;
3825 }
3826 break;
3827
Geoff Langff5b2d52016-09-07 11:32:23 -04003828 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3829 if (clientVersion < 3 && !context->getExtensions().sRGB)
3830 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003831 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003832 return false;
3833 }
3834 break;
3835
3836 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3837 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3838 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3839 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3840 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3841 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3842 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3843 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3844 if (clientVersion < 3)
3845 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003846 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003847 return false;
3848 }
3849 break;
3850
3851 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003852 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003853 return false;
3854 }
3855
3856 // Determine if the attachment is a valid enum
3857 switch (attachment)
3858 {
3859 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04003860 case GL_DEPTH:
3861 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04003862 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
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003869 case GL_DEPTH_STENCIL_ATTACHMENT:
3870 if (clientVersion < 3 && !context->isWebGL1())
3871 {
3872 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3873 return false;
3874 }
3875 break;
3876
Geoff Langfa125c92017-10-24 13:01:46 -04003877 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003878 case GL_DEPTH_ATTACHMENT:
3879 case GL_STENCIL_ATTACHMENT:
3880 break;
3881
3882 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003883 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3884 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003885 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3886 {
Geoff Langfa125c92017-10-24 13:01:46 -04003887 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003888 return false;
3889 }
3890 break;
3891 }
3892
3893 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3894 ASSERT(framebuffer);
3895
3896 if (framebuffer->id() == 0)
3897 {
3898 if (clientVersion < 3)
3899 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003900 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003901 return false;
3902 }
3903
3904 switch (attachment)
3905 {
3906 case GL_BACK:
3907 case GL_DEPTH:
3908 case GL_STENCIL:
3909 break;
3910
3911 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003912 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003913 return false;
3914 }
3915 }
3916 else
3917 {
3918 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3919 {
3920 // Valid attachment query
3921 }
3922 else
3923 {
3924 switch (attachment)
3925 {
3926 case GL_DEPTH_ATTACHMENT:
3927 case GL_STENCIL_ATTACHMENT:
3928 break;
3929
3930 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003931 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04003932 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003933 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003934 return false;
3935 }
3936 break;
3937
3938 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003939 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003940 return false;
3941 }
3942 }
3943 }
3944
3945 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3946 if (attachmentObject)
3947 {
3948 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3949 attachmentObject->type() == GL_TEXTURE ||
3950 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3951
3952 switch (pname)
3953 {
3954 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3955 if (attachmentObject->type() != GL_RENDERBUFFER &&
3956 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_LEVEL:
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_TEXTURE_CUBE_MAP_FACE:
3972 if (attachmentObject->type() != GL_TEXTURE)
3973 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003974 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003975 return false;
3976 }
3977 break;
3978
3979 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3980 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3981 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003982 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003983 return false;
3984 }
3985 break;
3986
3987 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3988 if (attachmentObject->type() != GL_TEXTURE)
3989 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003990 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003991 return false;
3992 }
3993 break;
3994
3995 default:
3996 break;
3997 }
3998 }
3999 else
4000 {
4001 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
4002 // is NONE, then querying any other pname will generate INVALID_ENUM.
4003
4004 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
4005 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4006 // INVALID_OPERATION for all other pnames
4007
4008 switch (pname)
4009 {
4010 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4011 break;
4012
4013 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4014 if (clientVersion < 3)
4015 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004016 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004017 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004018 return false;
4019 }
4020 break;
4021
4022 default:
4023 if (clientVersion < 3)
4024 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004025 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004026 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004027 return false;
4028 }
4029 else
4030 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004031 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08004032 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004033 return false;
4034 }
4035 }
4036 }
4037
Martin Radeve5285d22017-07-14 16:23:53 +03004038 if (numParams)
4039 {
4040 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4041 {
4042 // Only when the viewport offsets are queried we can have a varying number of output
4043 // parameters.
4044 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4045 *numParams = numViews * 2;
4046 }
4047 else
4048 {
4049 // For all other queries we can have only one output parameter.
4050 *numParams = 1;
4051 }
4052 }
4053
Geoff Langff5b2d52016-09-07 11:32:23 -04004054 return true;
4055}
4056
4057bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4058 GLenum target,
4059 GLenum attachment,
4060 GLenum pname,
4061 GLsizei bufSize,
4062 GLsizei *numParams)
4063{
4064 if (!ValidateRobustEntryPoint(context, bufSize))
4065 {
4066 return false;
4067 }
4068
Jamie Madillbe849e42017-05-02 15:49:00 -04004069 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4070 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004071 {
4072 return false;
4073 }
4074
4075 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4076 {
4077 return false;
4078 }
4079
4080 return true;
4081}
4082
Geoff Langff5b2d52016-09-07 11:32:23 -04004083bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004084 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004085 GLenum pname,
4086 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004087 GLsizei *length,
4088 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004089{
4090 if (!ValidateRobustEntryPoint(context, bufSize))
4091 {
4092 return false;
4093 }
4094
Geoff Langebebe1c2016-10-14 12:01:31 -04004095 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004096 {
4097 return false;
4098 }
4099
Geoff Langebebe1c2016-10-14 12:01:31 -04004100 if (!ValidateRobustBufferSize(context, bufSize, *length))
4101 {
4102 return false;
4103 }
4104
4105 return true;
4106}
4107
Geoff Langebebe1c2016-10-14 12:01:31 -04004108bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004109 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004110 GLenum pname,
4111 GLsizei bufSize,
4112 GLsizei *length,
4113 GLint64 *params)
4114{
4115 if (!ValidateRobustEntryPoint(context, bufSize))
4116 {
4117 return false;
4118 }
4119
4120 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4121 {
4122 return false;
4123 }
4124
4125 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004126 {
4127 return false;
4128 }
4129
4130 return true;
4131}
4132
Jamie Madillbe849e42017-05-02 15:49:00 -04004133bool ValidateGetProgramivBase(ValidationContext *context,
4134 GLuint program,
4135 GLenum pname,
4136 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004137{
4138 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004139 if (numParams)
4140 {
4141 *numParams = 1;
4142 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004143
4144 Program *programObject = GetValidProgram(context, program);
4145 if (!programObject)
4146 {
4147 return false;
4148 }
4149
4150 switch (pname)
4151 {
4152 case GL_DELETE_STATUS:
4153 case GL_LINK_STATUS:
4154 case GL_VALIDATE_STATUS:
4155 case GL_INFO_LOG_LENGTH:
4156 case GL_ATTACHED_SHADERS:
4157 case GL_ACTIVE_ATTRIBUTES:
4158 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4159 case GL_ACTIVE_UNIFORMS:
4160 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4161 break;
4162
4163 case GL_PROGRAM_BINARY_LENGTH:
4164 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4165 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004166 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4167 "requires GL_OES_get_program_binary or "
4168 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004169 return false;
4170 }
4171 break;
4172
4173 case GL_ACTIVE_UNIFORM_BLOCKS:
4174 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4175 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4176 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4177 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4178 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4179 if (context->getClientMajorVersion() < 3)
4180 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004181 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004182 return false;
4183 }
4184 break;
4185
Yunchao He61afff12017-03-14 15:34:03 +08004186 case GL_PROGRAM_SEPARABLE:
Xinghua Cao971f8502017-10-17 13:01:24 +08004187 case GL_COMPUTE_WORK_GROUP_SIZE:
jchen1058f67be2017-10-27 08:59:27 +08004188 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004189 if (context->getClientVersion() < Version(3, 1))
4190 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004191 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004192 return false;
4193 }
4194 break;
4195
Geoff Langff5b2d52016-09-07 11:32:23 -04004196 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004197 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004198 return false;
4199 }
4200
4201 return true;
4202}
4203
4204bool ValidateGetProgramivRobustANGLE(Context *context,
4205 GLuint program,
4206 GLenum pname,
4207 GLsizei bufSize,
4208 GLsizei *numParams)
4209{
4210 if (!ValidateRobustEntryPoint(context, bufSize))
4211 {
4212 return false;
4213 }
4214
Jamie Madillbe849e42017-05-02 15:49:00 -04004215 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004216 {
4217 return false;
4218 }
4219
4220 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4221 {
4222 return false;
4223 }
4224
4225 return true;
4226}
4227
Geoff Lang740d9022016-10-07 11:20:52 -04004228bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4229 GLenum target,
4230 GLenum pname,
4231 GLsizei bufSize,
4232 GLsizei *length,
4233 GLint *params)
4234{
4235 if (!ValidateRobustEntryPoint(context, bufSize))
4236 {
4237 return false;
4238 }
4239
4240 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4241 {
4242 return false;
4243 }
4244
4245 if (!ValidateRobustBufferSize(context, bufSize, *length))
4246 {
4247 return false;
4248 }
4249
4250 return true;
4251}
4252
Geoff Langd7d0ed32016-10-07 11:33:51 -04004253bool ValidateGetShaderivRobustANGLE(Context *context,
4254 GLuint shader,
4255 GLenum pname,
4256 GLsizei bufSize,
4257 GLsizei *length,
4258 GLint *params)
4259{
4260 if (!ValidateRobustEntryPoint(context, bufSize))
4261 {
4262 return false;
4263 }
4264
4265 if (!ValidateGetShaderivBase(context, shader, pname, length))
4266 {
4267 return false;
4268 }
4269
4270 if (!ValidateRobustBufferSize(context, bufSize, *length))
4271 {
4272 return false;
4273 }
4274
4275 return true;
4276}
4277
Geoff Langc1984ed2016-10-07 12:41:00 -04004278bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4279 GLenum target,
4280 GLenum pname,
4281 GLsizei bufSize,
4282 GLsizei *length,
4283 GLfloat *params)
4284{
4285 if (!ValidateRobustEntryPoint(context, bufSize))
4286 {
4287 return false;
4288 }
4289
4290 if (!ValidateGetTexParameterBase(context, target, pname, length))
4291 {
4292 return false;
4293 }
4294
4295 if (!ValidateRobustBufferSize(context, bufSize, *length))
4296 {
4297 return false;
4298 }
4299
4300 return true;
4301}
4302
Geoff Langc1984ed2016-10-07 12:41:00 -04004303bool ValidateGetTexParameterivRobustANGLE(Context *context,
4304 GLenum target,
4305 GLenum pname,
4306 GLsizei bufSize,
4307 GLsizei *length,
4308 GLint *params)
4309{
4310 if (!ValidateRobustEntryPoint(context, bufSize))
4311 {
4312 return false;
4313 }
4314
4315 if (!ValidateGetTexParameterBase(context, target, pname, length))
4316 {
4317 return false;
4318 }
4319
4320 if (!ValidateRobustBufferSize(context, bufSize, *length))
4321 {
4322 return false;
4323 }
4324
4325 return true;
4326}
4327
Geoff Langc1984ed2016-10-07 12:41:00 -04004328bool ValidateTexParameterfvRobustANGLE(Context *context,
4329 GLenum target,
4330 GLenum pname,
4331 GLsizei bufSize,
4332 const GLfloat *params)
4333{
4334 if (!ValidateRobustEntryPoint(context, bufSize))
4335 {
4336 return false;
4337 }
4338
4339 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4340}
4341
Geoff Langc1984ed2016-10-07 12:41:00 -04004342bool ValidateTexParameterivRobustANGLE(Context *context,
4343 GLenum target,
4344 GLenum pname,
4345 GLsizei bufSize,
4346 const GLint *params)
4347{
4348 if (!ValidateRobustEntryPoint(context, bufSize))
4349 {
4350 return false;
4351 }
4352
4353 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4354}
4355
Geoff Langc1984ed2016-10-07 12:41:00 -04004356bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4357 GLuint sampler,
4358 GLenum pname,
4359 GLuint bufSize,
4360 GLsizei *length,
4361 GLfloat *params)
4362{
4363 if (!ValidateRobustEntryPoint(context, bufSize))
4364 {
4365 return false;
4366 }
4367
4368 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4369 {
4370 return false;
4371 }
4372
4373 if (!ValidateRobustBufferSize(context, bufSize, *length))
4374 {
4375 return false;
4376 }
4377
4378 return true;
4379}
4380
Geoff Langc1984ed2016-10-07 12:41:00 -04004381bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4382 GLuint sampler,
4383 GLenum pname,
4384 GLuint bufSize,
4385 GLsizei *length,
4386 GLint *params)
4387{
4388 if (!ValidateRobustEntryPoint(context, bufSize))
4389 {
4390 return false;
4391 }
4392
4393 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4394 {
4395 return false;
4396 }
4397
4398 if (!ValidateRobustBufferSize(context, bufSize, *length))
4399 {
4400 return false;
4401 }
4402
4403 return true;
4404}
4405
Geoff Langc1984ed2016-10-07 12:41:00 -04004406bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4407 GLuint sampler,
4408 GLenum pname,
4409 GLsizei bufSize,
4410 const GLfloat *params)
4411{
4412 if (!ValidateRobustEntryPoint(context, bufSize))
4413 {
4414 return false;
4415 }
4416
4417 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4418}
4419
Geoff Langc1984ed2016-10-07 12:41:00 -04004420bool ValidateSamplerParameterivRobustANGLE(Context *context,
4421 GLuint sampler,
4422 GLenum pname,
4423 GLsizei bufSize,
4424 const GLint *params)
4425{
4426 if (!ValidateRobustEntryPoint(context, bufSize))
4427 {
4428 return false;
4429 }
4430
4431 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4432}
4433
Geoff Lang0b031062016-10-13 14:30:04 -04004434bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4435 GLuint index,
4436 GLenum pname,
4437 GLsizei bufSize,
4438 GLsizei *length,
4439 GLfloat *params)
4440{
4441 if (!ValidateRobustEntryPoint(context, bufSize))
4442 {
4443 return false;
4444 }
4445
4446 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4447 {
4448 return false;
4449 }
4450
4451 if (!ValidateRobustBufferSize(context, bufSize, *length))
4452 {
4453 return false;
4454 }
4455
4456 return true;
4457}
4458
Geoff Lang0b031062016-10-13 14:30:04 -04004459bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4460 GLuint index,
4461 GLenum pname,
4462 GLsizei bufSize,
4463 GLsizei *length,
4464 GLint *params)
4465{
4466 if (!ValidateRobustEntryPoint(context, bufSize))
4467 {
4468 return false;
4469 }
4470
4471 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4472 {
4473 return false;
4474 }
4475
4476 if (!ValidateRobustBufferSize(context, bufSize, *length))
4477 {
4478 return false;
4479 }
4480
4481 return true;
4482}
4483
Geoff Lang0b031062016-10-13 14:30:04 -04004484bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4485 GLuint index,
4486 GLenum pname,
4487 GLsizei bufSize,
4488 GLsizei *length,
4489 void **pointer)
4490{
4491 if (!ValidateRobustEntryPoint(context, bufSize))
4492 {
4493 return false;
4494 }
4495
4496 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4497 {
4498 return false;
4499 }
4500
4501 if (!ValidateRobustBufferSize(context, bufSize, *length))
4502 {
4503 return false;
4504 }
4505
4506 return true;
4507}
4508
Geoff Lang0b031062016-10-13 14:30:04 -04004509bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4510 GLuint index,
4511 GLenum pname,
4512 GLsizei bufSize,
4513 GLsizei *length,
4514 GLint *params)
4515{
4516 if (!ValidateRobustEntryPoint(context, bufSize))
4517 {
4518 return false;
4519 }
4520
4521 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4522 {
4523 return false;
4524 }
4525
4526 if (!ValidateRobustBufferSize(context, bufSize, *length))
4527 {
4528 return false;
4529 }
4530
4531 return true;
4532}
4533
Geoff Lang0b031062016-10-13 14:30:04 -04004534bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4535 GLuint index,
4536 GLenum pname,
4537 GLsizei bufSize,
4538 GLsizei *length,
4539 GLuint *params)
4540{
4541 if (!ValidateRobustEntryPoint(context, bufSize))
4542 {
4543 return false;
4544 }
4545
4546 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4547 {
4548 return false;
4549 }
4550
4551 if (!ValidateRobustBufferSize(context, bufSize, *length))
4552 {
4553 return false;
4554 }
4555
4556 return true;
4557}
4558
Geoff Lang6899b872016-10-14 11:30:13 -04004559bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4560 GLuint program,
4561 GLuint uniformBlockIndex,
4562 GLenum pname,
4563 GLsizei bufSize,
4564 GLsizei *length,
4565 GLint *params)
4566{
4567 if (!ValidateRobustEntryPoint(context, bufSize))
4568 {
4569 return false;
4570 }
4571
4572 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4573 {
4574 return false;
4575 }
4576
4577 if (!ValidateRobustBufferSize(context, bufSize, *length))
4578 {
4579 return false;
4580 }
4581
4582 return true;
4583}
4584
Geoff Lang0a9661f2016-10-20 10:59:20 -07004585bool ValidateGetInternalFormativRobustANGLE(Context *context,
4586 GLenum target,
4587 GLenum internalformat,
4588 GLenum pname,
4589 GLsizei bufSize,
4590 GLsizei *length,
4591 GLint *params)
4592{
4593 if (!ValidateRobustEntryPoint(context, bufSize))
4594 {
4595 return false;
4596 }
4597
4598 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4599 {
4600 return false;
4601 }
4602
4603 if (!ValidateRobustBufferSize(context, bufSize, *length))
4604 {
4605 return false;
4606 }
4607
4608 return true;
4609}
4610
Shao80957d92017-02-20 21:25:59 +08004611bool ValidateVertexFormatBase(ValidationContext *context,
4612 GLuint attribIndex,
4613 GLint size,
4614 GLenum type,
4615 GLboolean pureInteger)
4616{
4617 const Caps &caps = context->getCaps();
4618 if (attribIndex >= caps.maxVertexAttributes)
4619 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004620 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004621 return false;
4622 }
4623
4624 if (size < 1 || size > 4)
4625 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004626 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004627 return false;
Shao80957d92017-02-20 21:25:59 +08004628 }
4629
4630 switch (type)
4631 {
4632 case GL_BYTE:
4633 case GL_UNSIGNED_BYTE:
4634 case GL_SHORT:
4635 case GL_UNSIGNED_SHORT:
4636 break;
4637
4638 case GL_INT:
4639 case GL_UNSIGNED_INT:
4640 if (context->getClientMajorVersion() < 3)
4641 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004642 context->handleError(InvalidEnum()
4643 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004644 return false;
4645 }
4646 break;
4647
4648 case GL_FIXED:
4649 case GL_FLOAT:
4650 if (pureInteger)
4651 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004652 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004653 return false;
4654 }
4655 break;
4656
4657 case GL_HALF_FLOAT:
4658 if (context->getClientMajorVersion() < 3)
4659 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004660 context->handleError(InvalidEnum()
4661 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004662 return false;
4663 }
4664 if (pureInteger)
4665 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004666 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004667 return false;
4668 }
4669 break;
4670
4671 case GL_INT_2_10_10_10_REV:
4672 case GL_UNSIGNED_INT_2_10_10_10_REV:
4673 if (context->getClientMajorVersion() < 3)
4674 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004675 context->handleError(InvalidEnum()
4676 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004677 return false;
4678 }
4679 if (pureInteger)
4680 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004681 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004682 return false;
4683 }
4684 if (size != 4)
4685 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004686 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4687 "UNSIGNED_INT_2_10_10_10_REV and "
4688 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004689 return false;
4690 }
4691 break;
4692
4693 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004694 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004695 return false;
4696 }
4697
4698 return true;
4699}
4700
Geoff Lang76e65652017-03-27 14:58:02 -04004701// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4702// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4703// specified clear value and the type of a buffer that is being cleared generates an
4704// INVALID_OPERATION error instead of producing undefined results
4705bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4706 GLint drawbuffer,
4707 const GLenum *validComponentTypes,
4708 size_t validComponentTypeCount)
4709{
4710 const FramebufferAttachment *attachment =
4711 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4712 if (attachment)
4713 {
4714 GLenum componentType = attachment->getFormat().info->componentType;
4715 const GLenum *end = validComponentTypes + validComponentTypeCount;
4716 if (std::find(validComponentTypes, end, componentType) == end)
4717 {
4718 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004719 InvalidOperation()
4720 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004721 return false;
4722 }
4723 }
4724
4725 return true;
4726}
4727
Corentin Wallezb2931602017-04-11 15:58:57 -04004728bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4729 GLsizei imageSize,
4730 GLsizei dataSize)
4731{
4732 if (!ValidateRobustEntryPoint(context, dataSize))
4733 {
4734 return false;
4735 }
4736
Corentin Wallez336129f2017-10-17 15:55:40 -04004737 gl::Buffer *pixelUnpackBuffer =
4738 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004739 if (pixelUnpackBuffer == nullptr)
4740 {
4741 if (dataSize < imageSize)
4742 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004743 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004744 }
4745 }
4746 return true;
4747}
4748
Jamie Madillbe849e42017-05-02 15:49:00 -04004749bool ValidateGetBufferParameterBase(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004750 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004751 GLenum pname,
4752 bool pointerVersion,
4753 GLsizei *numParams)
4754{
4755 if (numParams)
4756 {
4757 *numParams = 0;
4758 }
4759
Corentin Wallez336129f2017-10-17 15:55:40 -04004760 if (!ValidBufferType(context, target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004761 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004762 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004763 return false;
4764 }
4765
4766 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4767 if (!buffer)
4768 {
4769 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004770 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004771 return false;
4772 }
4773
4774 const Extensions &extensions = context->getExtensions();
4775
4776 switch (pname)
4777 {
4778 case GL_BUFFER_USAGE:
4779 case GL_BUFFER_SIZE:
4780 break;
4781
4782 case GL_BUFFER_ACCESS_OES:
4783 if (!extensions.mapBuffer)
4784 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004785 context->handleError(InvalidEnum()
4786 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004787 return false;
4788 }
4789 break;
4790
4791 case GL_BUFFER_MAPPED:
4792 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4793 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4794 !extensions.mapBufferRange)
4795 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004796 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4797 "GL_OES_mapbuffer or "
4798 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004799 return false;
4800 }
4801 break;
4802
4803 case GL_BUFFER_MAP_POINTER:
4804 if (!pointerVersion)
4805 {
4806 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004807 InvalidEnum()
4808 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004809 return false;
4810 }
4811 break;
4812
4813 case GL_BUFFER_ACCESS_FLAGS:
4814 case GL_BUFFER_MAP_OFFSET:
4815 case GL_BUFFER_MAP_LENGTH:
4816 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4817 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004818 context->handleError(InvalidEnum()
4819 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004820 return false;
4821 }
4822 break;
4823
4824 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004825 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004826 return false;
4827 }
4828
4829 // All buffer parameter queries return one value.
4830 if (numParams)
4831 {
4832 *numParams = 1;
4833 }
4834
4835 return true;
4836}
4837
4838bool ValidateGetRenderbufferParameterivBase(Context *context,
4839 GLenum target,
4840 GLenum pname,
4841 GLsizei *length)
4842{
4843 if (length)
4844 {
4845 *length = 0;
4846 }
4847
4848 if (target != GL_RENDERBUFFER)
4849 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004850 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004851 return false;
4852 }
4853
4854 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4855 if (renderbuffer == nullptr)
4856 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004857 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004858 return false;
4859 }
4860
4861 switch (pname)
4862 {
4863 case GL_RENDERBUFFER_WIDTH:
4864 case GL_RENDERBUFFER_HEIGHT:
4865 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4866 case GL_RENDERBUFFER_RED_SIZE:
4867 case GL_RENDERBUFFER_GREEN_SIZE:
4868 case GL_RENDERBUFFER_BLUE_SIZE:
4869 case GL_RENDERBUFFER_ALPHA_SIZE:
4870 case GL_RENDERBUFFER_DEPTH_SIZE:
4871 case GL_RENDERBUFFER_STENCIL_SIZE:
4872 break;
4873
4874 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4875 if (!context->getExtensions().framebufferMultisample)
4876 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004877 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004878 return false;
4879 }
4880 break;
4881
4882 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004883 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004884 return false;
4885 }
4886
4887 if (length)
4888 {
4889 *length = 1;
4890 }
4891 return true;
4892}
4893
4894bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4895{
4896 if (length)
4897 {
4898 *length = 0;
4899 }
4900
4901 if (GetValidShader(context, shader) == nullptr)
4902 {
4903 return false;
4904 }
4905
4906 switch (pname)
4907 {
4908 case GL_SHADER_TYPE:
4909 case GL_DELETE_STATUS:
4910 case GL_COMPILE_STATUS:
4911 case GL_INFO_LOG_LENGTH:
4912 case GL_SHADER_SOURCE_LENGTH:
4913 break;
4914
4915 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4916 if (!context->getExtensions().translatedShaderSource)
4917 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004918 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004919 return false;
4920 }
4921 break;
4922
4923 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004924 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004925 return false;
4926 }
4927
4928 if (length)
4929 {
4930 *length = 1;
4931 }
4932 return true;
4933}
4934
4935bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4936{
4937 if (length)
4938 {
4939 *length = 0;
4940 }
4941
4942 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4943 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004944 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004945 return false;
4946 }
4947
4948 if (context->getTargetTexture(target) == nullptr)
4949 {
4950 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004951 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004952 return false;
4953 }
4954
4955 switch (pname)
4956 {
4957 case GL_TEXTURE_MAG_FILTER:
4958 case GL_TEXTURE_MIN_FILTER:
4959 case GL_TEXTURE_WRAP_S:
4960 case GL_TEXTURE_WRAP_T:
4961 break;
4962
4963 case GL_TEXTURE_USAGE_ANGLE:
4964 if (!context->getExtensions().textureUsage)
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_MAX_ANISOTROPY_EXT:
4972 if (!context->getExtensions().textureFilterAnisotropic)
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_IMMUTABLE_FORMAT:
4980 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4981 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004982 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004983 return false;
4984 }
4985 break;
4986
4987 case GL_TEXTURE_WRAP_R:
4988 case GL_TEXTURE_IMMUTABLE_LEVELS:
4989 case GL_TEXTURE_SWIZZLE_R:
4990 case GL_TEXTURE_SWIZZLE_G:
4991 case GL_TEXTURE_SWIZZLE_B:
4992 case GL_TEXTURE_SWIZZLE_A:
4993 case GL_TEXTURE_BASE_LEVEL:
4994 case GL_TEXTURE_MAX_LEVEL:
4995 case GL_TEXTURE_MIN_LOD:
4996 case GL_TEXTURE_MAX_LOD:
4997 case GL_TEXTURE_COMPARE_MODE:
4998 case GL_TEXTURE_COMPARE_FUNC:
4999 if (context->getClientMajorVersion() < 3)
5000 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005001 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005002 return false;
5003 }
5004 break;
5005
5006 case GL_TEXTURE_SRGB_DECODE_EXT:
5007 if (!context->getExtensions().textureSRGBDecode)
5008 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005009 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005010 return false;
5011 }
5012 break;
5013
5014 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005015 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005016 return false;
5017 }
5018
5019 if (length)
5020 {
5021 *length = 1;
5022 }
5023 return true;
5024}
5025
5026bool ValidateGetVertexAttribBase(Context *context,
5027 GLuint index,
5028 GLenum pname,
5029 GLsizei *length,
5030 bool pointer,
5031 bool pureIntegerEntryPoint)
5032{
5033 if (length)
5034 {
5035 *length = 0;
5036 }
5037
5038 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5039 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005040 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005041 return false;
5042 }
5043
5044 if (index >= context->getCaps().maxVertexAttributes)
5045 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005046 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005047 return false;
5048 }
5049
5050 if (pointer)
5051 {
5052 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5053 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005054 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005055 return false;
5056 }
5057 }
5058 else
5059 {
5060 switch (pname)
5061 {
5062 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5063 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5064 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5065 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5066 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5067 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5068 case GL_CURRENT_VERTEX_ATTRIB:
5069 break;
5070
5071 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5072 static_assert(
5073 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5074 "ANGLE extension enums not equal to GL enums.");
5075 if (context->getClientMajorVersion() < 3 &&
5076 !context->getExtensions().instancedArrays)
5077 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005078 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5079 "requires OpenGL ES 3.0 or "
5080 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005081 return false;
5082 }
5083 break;
5084
5085 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5086 if (context->getClientMajorVersion() < 3)
5087 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005088 context->handleError(
5089 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005090 return false;
5091 }
5092 break;
5093
5094 case GL_VERTEX_ATTRIB_BINDING:
5095 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5096 if (context->getClientVersion() < ES_3_1)
5097 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005098 context->handleError(InvalidEnum()
5099 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005100 return false;
5101 }
5102 break;
5103
5104 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005105 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005106 return false;
5107 }
5108 }
5109
5110 if (length)
5111 {
5112 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5113 {
5114 *length = 4;
5115 }
5116 else
5117 {
5118 *length = 1;
5119 }
5120 }
5121
5122 return true;
5123}
5124
Jamie Madill4928b7c2017-06-20 12:57:39 -04005125bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005126 GLint x,
5127 GLint y,
5128 GLsizei width,
5129 GLsizei height,
5130 GLenum format,
5131 GLenum type,
5132 GLsizei bufSize,
5133 GLsizei *length,
5134 GLsizei *columns,
5135 GLsizei *rows,
5136 void *pixels)
5137{
5138 if (length != nullptr)
5139 {
5140 *length = 0;
5141 }
5142 if (rows != nullptr)
5143 {
5144 *rows = 0;
5145 }
5146 if (columns != nullptr)
5147 {
5148 *columns = 0;
5149 }
5150
5151 if (width < 0 || height < 0)
5152 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005153 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005154 return false;
5155 }
5156
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005157 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005158
5159 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5160 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005161 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005162 return false;
5163 }
5164
5165 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5166 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005167 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005168 return false;
5169 }
5170
5171 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5172 ASSERT(framebuffer);
5173
5174 if (framebuffer->getReadBufferState() == GL_NONE)
5175 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005176 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005177 return false;
5178 }
5179
5180 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5181 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5182 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5183 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5184 // situation is an application error that would lead to a crash in ANGLE.
5185 if (readBuffer == nullptr)
5186 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005187 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005188 return false;
5189 }
5190
Martin Radev28031682017-07-28 14:47:56 +03005191 // ANGLE_multiview, Revision 1:
5192 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5193 // current read framebuffer is not NONE.
5194 if (readBuffer->getMultiviewLayout() != GL_NONE)
5195 {
5196 context->handleError(InvalidFramebufferOperation()
5197 << "Attempting to read from a multi-view framebuffer.");
5198 return false;
5199 }
5200
Geoff Lang280ba992017-04-18 16:30:58 -04005201 if (context->getExtensions().webglCompatibility)
5202 {
5203 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5204 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5205 // and type before validating the combination of format and type. However, the
5206 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5207 // verifies that GL_INVALID_OPERATION is generated.
5208 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5209 // dEQP/WebGL.
5210 if (!ValidReadPixelsFormatEnum(context, format))
5211 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005212 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005213 return false;
5214 }
5215
5216 if (!ValidReadPixelsTypeEnum(context, type))
5217 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005218 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005219 return false;
5220 }
5221 }
5222
Jamie Madill4928b7c2017-06-20 12:57:39 -04005223 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5224 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005225 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5226
5227 bool validFormatTypeCombination =
5228 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5229
5230 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5231 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005232 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005233 return false;
5234 }
5235
5236 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005237 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005238 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5239 {
5240 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005241 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005242 return false;
5243 }
5244
5245 // .. the data would be packed to the buffer object such that the memory writes required
5246 // would exceed the data store size.
5247 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5248 const gl::Extents size(width, height, 1);
5249 const auto &pack = context->getGLState().getPackState();
5250
5251 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5252 if (endByteOrErr.isError())
5253 {
5254 context->handleError(endByteOrErr.getError());
5255 return false;
5256 }
5257
5258 size_t endByte = endByteOrErr.getResult();
5259 if (bufSize >= 0)
5260 {
5261 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5262 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005263 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005264 return false;
5265 }
5266 }
5267
5268 if (pixelPackBuffer != nullptr)
5269 {
5270 CheckedNumeric<size_t> checkedEndByte(endByte);
5271 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5272 checkedEndByte += checkedOffset;
5273
5274 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5275 {
5276 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005277 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005278 return false;
5279 }
5280 }
5281
5282 if (pixelPackBuffer == nullptr && length != nullptr)
5283 {
5284 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5285 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005286 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005287 return false;
5288 }
5289
5290 *length = static_cast<GLsizei>(endByte);
5291 }
5292
5293 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5294 angle::CheckedNumeric<int> clippedExtent(length);
5295 if (start < 0)
5296 {
5297 // "subtract" the area that is less than 0
5298 clippedExtent += start;
5299 }
5300
5301 const int readExtent = start + length;
5302 if (readExtent > bufferSize)
5303 {
5304 // Subtract the region to the right of the read buffer
5305 clippedExtent -= (readExtent - bufferSize);
5306 }
5307
5308 if (!clippedExtent.IsValid())
5309 {
5310 return 0;
5311 }
5312
5313 return std::max(clippedExtent.ValueOrDie(), 0);
5314 };
5315
5316 if (columns != nullptr)
5317 {
5318 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5319 }
5320
5321 if (rows != nullptr)
5322 {
5323 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5324 }
5325
5326 return true;
5327}
5328
5329template <typename ParamType>
5330bool ValidateTexParameterBase(Context *context,
5331 GLenum target,
5332 GLenum pname,
5333 GLsizei bufSize,
5334 const ParamType *params)
5335{
5336 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5337 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005338 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005339 return false;
5340 }
5341
5342 if (context->getTargetTexture(target) == nullptr)
5343 {
5344 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005345 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005346 return false;
5347 }
5348
5349 const GLsizei minBufSize = 1;
5350 if (bufSize >= 0 && bufSize < minBufSize)
5351 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005352 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005353 return false;
5354 }
5355
5356 switch (pname)
5357 {
5358 case GL_TEXTURE_WRAP_R:
5359 case GL_TEXTURE_SWIZZLE_R:
5360 case GL_TEXTURE_SWIZZLE_G:
5361 case GL_TEXTURE_SWIZZLE_B:
5362 case GL_TEXTURE_SWIZZLE_A:
5363 case GL_TEXTURE_BASE_LEVEL:
5364 case GL_TEXTURE_MAX_LEVEL:
5365 case GL_TEXTURE_COMPARE_MODE:
5366 case GL_TEXTURE_COMPARE_FUNC:
5367 case GL_TEXTURE_MIN_LOD:
5368 case GL_TEXTURE_MAX_LOD:
5369 if (context->getClientMajorVersion() < 3)
5370 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005371 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005372 return false;
5373 }
5374 if (target == GL_TEXTURE_EXTERNAL_OES &&
5375 !context->getExtensions().eglImageExternalEssl3)
5376 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005377 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5378 "available without "
5379 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005380 return false;
5381 }
5382 break;
5383
5384 default:
5385 break;
5386 }
5387
JiangYizhou4cff8d62017-07-06 14:54:09 +08005388 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5389 {
5390 switch (pname)
5391 {
5392 case GL_TEXTURE_MIN_FILTER:
5393 case GL_TEXTURE_MAG_FILTER:
5394 case GL_TEXTURE_WRAP_S:
5395 case GL_TEXTURE_WRAP_T:
5396 case GL_TEXTURE_WRAP_R:
5397 case GL_TEXTURE_MIN_LOD:
5398 case GL_TEXTURE_MAX_LOD:
5399 case GL_TEXTURE_COMPARE_MODE:
5400 case GL_TEXTURE_COMPARE_FUNC:
5401 context->handleError(InvalidEnum()
5402 << "Invalid parameter for 2D multisampled textures.");
5403 return false;
5404 }
5405 }
5406
Jamie Madillbe849e42017-05-02 15:49:00 -04005407 switch (pname)
5408 {
5409 case GL_TEXTURE_WRAP_S:
5410 case GL_TEXTURE_WRAP_T:
5411 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005412 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005413 bool restrictedWrapModes =
5414 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5415 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5416 {
5417 return false;
5418 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005419 }
5420 break;
5421
5422 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005423 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005424 bool restrictedMinFilter =
5425 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5426 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5427 {
5428 return false;
5429 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005430 }
5431 break;
5432
5433 case GL_TEXTURE_MAG_FILTER:
5434 if (!ValidateTextureMagFilterValue(context, params))
5435 {
5436 return false;
5437 }
5438 break;
5439
5440 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005441 if (!context->getExtensions().textureUsage)
5442 {
5443 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5444 return false;
5445 }
5446
Jamie Madillbe849e42017-05-02 15:49:00 -04005447 switch (ConvertToGLenum(params[0]))
5448 {
5449 case GL_NONE:
5450 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5451 break;
5452
5453 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005454 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005455 return false;
5456 }
5457 break;
5458
5459 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5460 if (!context->getExtensions().textureFilterAnisotropic)
5461 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005462 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005463 return false;
5464 }
5465
5466 // we assume the parameter passed to this validation method is truncated, not rounded
5467 if (params[0] < 1)
5468 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005469 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005470 return false;
5471 }
5472 break;
5473
5474 case GL_TEXTURE_MIN_LOD:
5475 case GL_TEXTURE_MAX_LOD:
5476 // any value is permissible
5477 break;
5478
5479 case GL_TEXTURE_COMPARE_MODE:
5480 if (!ValidateTextureCompareModeValue(context, params))
5481 {
5482 return false;
5483 }
5484 break;
5485
5486 case GL_TEXTURE_COMPARE_FUNC:
5487 if (!ValidateTextureCompareFuncValue(context, params))
5488 {
5489 return false;
5490 }
5491 break;
5492
5493 case GL_TEXTURE_SWIZZLE_R:
5494 case GL_TEXTURE_SWIZZLE_G:
5495 case GL_TEXTURE_SWIZZLE_B:
5496 case GL_TEXTURE_SWIZZLE_A:
5497 switch (ConvertToGLenum(params[0]))
5498 {
5499 case GL_RED:
5500 case GL_GREEN:
5501 case GL_BLUE:
5502 case GL_ALPHA:
5503 case GL_ZERO:
5504 case GL_ONE:
5505 break;
5506
5507 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005508 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005509 return false;
5510 }
5511 break;
5512
5513 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005514 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005515 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005516 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005517 return false;
5518 }
5519 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5520 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005521 context->handleError(InvalidOperation()
5522 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005523 return false;
5524 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005525 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5526 {
5527 context->handleError(InvalidOperation()
5528 << "Base level must be 0 for multisampled textures.");
5529 return false;
5530 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005531 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5532 {
5533 context->handleError(InvalidOperation()
5534 << "Base level must be 0 for rectangle textures.");
5535 return false;
5536 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005537 break;
5538
5539 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005540 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005541 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005542 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005543 return false;
5544 }
5545 break;
5546
5547 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5548 if (context->getClientVersion() < Version(3, 1))
5549 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005550 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005551 return false;
5552 }
5553 switch (ConvertToGLenum(params[0]))
5554 {
5555 case GL_DEPTH_COMPONENT:
5556 case GL_STENCIL_INDEX:
5557 break;
5558
5559 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005560 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005561 return false;
5562 }
5563 break;
5564
5565 case GL_TEXTURE_SRGB_DECODE_EXT:
5566 if (!ValidateTextureSRGBDecodeValue(context, params))
5567 {
5568 return false;
5569 }
5570 break;
5571
5572 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005573 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005574 return false;
5575 }
5576
5577 return true;
5578}
5579
5580template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5581template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5582
Jamie Madill12e957f2017-08-26 21:42:26 -04005583bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5584{
5585 if (index >= MAX_VERTEX_ATTRIBS)
5586 {
5587 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5588 return false;
5589 }
5590
5591 return true;
5592}
5593
5594bool ValidateGetActiveUniformBlockivBase(Context *context,
5595 GLuint program,
5596 GLuint uniformBlockIndex,
5597 GLenum pname,
5598 GLsizei *length)
5599{
5600 if (length)
5601 {
5602 *length = 0;
5603 }
5604
5605 if (context->getClientMajorVersion() < 3)
5606 {
5607 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5608 return false;
5609 }
5610
5611 Program *programObject = GetValidProgram(context, program);
5612 if (!programObject)
5613 {
5614 return false;
5615 }
5616
5617 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5618 {
5619 context->handleError(InvalidValue()
5620 << "uniformBlockIndex exceeds active uniform block count.");
5621 return false;
5622 }
5623
5624 switch (pname)
5625 {
5626 case GL_UNIFORM_BLOCK_BINDING:
5627 case GL_UNIFORM_BLOCK_DATA_SIZE:
5628 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5629 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5630 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5631 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5632 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5633 break;
5634
5635 default:
5636 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5637 return false;
5638 }
5639
5640 if (length)
5641 {
5642 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5643 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005644 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005645 programObject->getUniformBlockByIndex(uniformBlockIndex);
5646 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5647 }
5648 else
5649 {
5650 *length = 1;
5651 }
5652 }
5653
5654 return true;
5655}
5656
Jamie Madill9696d072017-08-26 23:19:57 -04005657template <typename ParamType>
5658bool ValidateSamplerParameterBase(Context *context,
5659 GLuint sampler,
5660 GLenum pname,
5661 GLsizei bufSize,
5662 ParamType *params)
5663{
5664 if (context->getClientMajorVersion() < 3)
5665 {
5666 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5667 return false;
5668 }
5669
5670 if (!context->isSampler(sampler))
5671 {
5672 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5673 return false;
5674 }
5675
5676 const GLsizei minBufSize = 1;
5677 if (bufSize >= 0 && bufSize < minBufSize)
5678 {
5679 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5680 return false;
5681 }
5682
5683 switch (pname)
5684 {
5685 case GL_TEXTURE_WRAP_S:
5686 case GL_TEXTURE_WRAP_T:
5687 case GL_TEXTURE_WRAP_R:
5688 if (!ValidateTextureWrapModeValue(context, params, false))
5689 {
5690 return false;
5691 }
5692 break;
5693
5694 case GL_TEXTURE_MIN_FILTER:
5695 if (!ValidateTextureMinFilterValue(context, params, false))
5696 {
5697 return false;
5698 }
5699 break;
5700
5701 case GL_TEXTURE_MAG_FILTER:
5702 if (!ValidateTextureMagFilterValue(context, params))
5703 {
5704 return false;
5705 }
5706 break;
5707
5708 case GL_TEXTURE_MIN_LOD:
5709 case GL_TEXTURE_MAX_LOD:
5710 // any value is permissible
5711 break;
5712
5713 case GL_TEXTURE_COMPARE_MODE:
5714 if (!ValidateTextureCompareModeValue(context, params))
5715 {
5716 return false;
5717 }
5718 break;
5719
5720 case GL_TEXTURE_COMPARE_FUNC:
5721 if (!ValidateTextureCompareFuncValue(context, params))
5722 {
5723 return false;
5724 }
5725 break;
5726
5727 case GL_TEXTURE_SRGB_DECODE_EXT:
5728 if (!ValidateTextureSRGBDecodeValue(context, params))
5729 {
5730 return false;
5731 }
5732 break;
5733
5734 default:
5735 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5736 return false;
5737 }
5738
5739 return true;
5740}
5741
5742template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5743template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5744
5745bool ValidateGetSamplerParameterBase(Context *context,
5746 GLuint sampler,
5747 GLenum pname,
5748 GLsizei *length)
5749{
5750 if (length)
5751 {
5752 *length = 0;
5753 }
5754
5755 if (context->getClientMajorVersion() < 3)
5756 {
5757 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5758 return false;
5759 }
5760
5761 if (!context->isSampler(sampler))
5762 {
5763 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5764 return false;
5765 }
5766
5767 switch (pname)
5768 {
5769 case GL_TEXTURE_WRAP_S:
5770 case GL_TEXTURE_WRAP_T:
5771 case GL_TEXTURE_WRAP_R:
5772 case GL_TEXTURE_MIN_FILTER:
5773 case GL_TEXTURE_MAG_FILTER:
5774 case GL_TEXTURE_MIN_LOD:
5775 case GL_TEXTURE_MAX_LOD:
5776 case GL_TEXTURE_COMPARE_MODE:
5777 case GL_TEXTURE_COMPARE_FUNC:
5778 break;
5779
5780 case GL_TEXTURE_SRGB_DECODE_EXT:
5781 if (!context->getExtensions().textureSRGBDecode)
5782 {
5783 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5784 return false;
5785 }
5786 break;
5787
5788 default:
5789 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5790 return false;
5791 }
5792
5793 if (length)
5794 {
5795 *length = 1;
5796 }
5797 return true;
5798}
5799
5800bool ValidateGetInternalFormativBase(Context *context,
5801 GLenum target,
5802 GLenum internalformat,
5803 GLenum pname,
5804 GLsizei bufSize,
5805 GLsizei *numParams)
5806{
5807 if (numParams)
5808 {
5809 *numParams = 0;
5810 }
5811
5812 if (context->getClientMajorVersion() < 3)
5813 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005814 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005815 return false;
5816 }
5817
5818 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5819 if (!formatCaps.renderable)
5820 {
5821 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5822 return false;
5823 }
5824
5825 switch (target)
5826 {
5827 case GL_RENDERBUFFER:
5828 break;
5829
5830 case GL_TEXTURE_2D_MULTISAMPLE:
5831 if (context->getClientVersion() < ES_3_1)
5832 {
5833 context->handleError(InvalidOperation()
5834 << "Texture target requires at least OpenGL ES 3.1.");
5835 return false;
5836 }
5837 break;
5838
5839 default:
5840 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5841 return false;
5842 }
5843
5844 if (bufSize < 0)
5845 {
5846 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5847 return false;
5848 }
5849
5850 GLsizei maxWriteParams = 0;
5851 switch (pname)
5852 {
5853 case GL_NUM_SAMPLE_COUNTS:
5854 maxWriteParams = 1;
5855 break;
5856
5857 case GL_SAMPLES:
5858 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5859 break;
5860
5861 default:
5862 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5863 return false;
5864 }
5865
5866 if (numParams)
5867 {
5868 // glGetInternalFormativ will not overflow bufSize
5869 *numParams = std::min(bufSize, maxWriteParams);
5870 }
5871
5872 return true;
5873}
5874
Jamie Madillc29968b2016-01-20 11:17:23 -05005875} // namespace gl