blob: 9b2434db6be3203931768cd717b44ef174fa86f8 [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{
Martin Radev1be913c2016-07-11 17:59:16 +03002189 if (transpose != GL_FALSE && 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();
2364 auto 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:
3860 case GL_FRONT:
3861 case GL_DEPTH:
3862 case GL_STENCIL:
3863 case GL_DEPTH_STENCIL_ATTACHMENT:
3864 if (clientVersion < 3)
3865 {
Geoff Langfa125c92017-10-24 13:01:46 -04003866 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003867 return false;
3868 }
3869 break;
3870
Geoff Langfa125c92017-10-24 13:01:46 -04003871 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003872 case GL_DEPTH_ATTACHMENT:
3873 case GL_STENCIL_ATTACHMENT:
3874 break;
3875
3876 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003877 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3878 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003879 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3880 {
Geoff Langfa125c92017-10-24 13:01:46 -04003881 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003882 return false;
3883 }
3884 break;
3885 }
3886
3887 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3888 ASSERT(framebuffer);
3889
3890 if (framebuffer->id() == 0)
3891 {
3892 if (clientVersion < 3)
3893 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003894 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003895 return false;
3896 }
3897
3898 switch (attachment)
3899 {
3900 case GL_BACK:
3901 case GL_DEPTH:
3902 case GL_STENCIL:
3903 break;
3904
3905 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003906 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003907 return false;
3908 }
3909 }
3910 else
3911 {
3912 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3913 {
3914 // Valid attachment query
3915 }
3916 else
3917 {
3918 switch (attachment)
3919 {
3920 case GL_DEPTH_ATTACHMENT:
3921 case GL_STENCIL_ATTACHMENT:
3922 break;
3923
3924 case GL_DEPTH_STENCIL_ATTACHMENT:
3925 if (!framebuffer->hasValidDepthStencil())
3926 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003927 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003928 return false;
3929 }
3930 break;
3931
3932 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003933 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003934 return false;
3935 }
3936 }
3937 }
3938
3939 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
3940 if (attachmentObject)
3941 {
3942 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3943 attachmentObject->type() == GL_TEXTURE ||
3944 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3945
3946 switch (pname)
3947 {
3948 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3949 if (attachmentObject->type() != GL_RENDERBUFFER &&
3950 attachmentObject->type() != GL_TEXTURE)
3951 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003952 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003953 return false;
3954 }
3955 break;
3956
3957 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3958 if (attachmentObject->type() != GL_TEXTURE)
3959 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003960 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003961 return false;
3962 }
3963 break;
3964
3965 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3966 if (attachmentObject->type() != GL_TEXTURE)
3967 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003968 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003969 return false;
3970 }
3971 break;
3972
3973 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3974 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3975 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003976 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003977 return false;
3978 }
3979 break;
3980
3981 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3982 if (attachmentObject->type() != GL_TEXTURE)
3983 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003984 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003985 return false;
3986 }
3987 break;
3988
3989 default:
3990 break;
3991 }
3992 }
3993 else
3994 {
3995 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3996 // is NONE, then querying any other pname will generate INVALID_ENUM.
3997
3998 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3999 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
4000 // INVALID_OPERATION for all other pnames
4001
4002 switch (pname)
4003 {
4004 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
4005 break;
4006
4007 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
4008 if (clientVersion < 3)
4009 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004010 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004011 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004012 return false;
4013 }
4014 break;
4015
4016 default:
4017 if (clientVersion < 3)
4018 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004019 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004020 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004021 return false;
4022 }
4023 else
4024 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004025 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Brandon Jonesafa75152017-07-21 13:11:29 -07004026 InvalidFramebufferTextureParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04004027 return false;
4028 }
4029 }
4030 }
4031
Martin Radeve5285d22017-07-14 16:23:53 +03004032 if (numParams)
4033 {
4034 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
4035 {
4036 // Only when the viewport offsets are queried we can have a varying number of output
4037 // parameters.
4038 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
4039 *numParams = numViews * 2;
4040 }
4041 else
4042 {
4043 // For all other queries we can have only one output parameter.
4044 *numParams = 1;
4045 }
4046 }
4047
Geoff Langff5b2d52016-09-07 11:32:23 -04004048 return true;
4049}
4050
4051bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(ValidationContext *context,
4052 GLenum target,
4053 GLenum attachment,
4054 GLenum pname,
4055 GLsizei bufSize,
4056 GLsizei *numParams)
4057{
4058 if (!ValidateRobustEntryPoint(context, bufSize))
4059 {
4060 return false;
4061 }
4062
Jamie Madillbe849e42017-05-02 15:49:00 -04004063 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4064 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004065 {
4066 return false;
4067 }
4068
4069 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4070 {
4071 return false;
4072 }
4073
4074 return true;
4075}
4076
Geoff Langff5b2d52016-09-07 11:32:23 -04004077bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004078 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004079 GLenum pname,
4080 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004081 GLsizei *length,
4082 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004083{
4084 if (!ValidateRobustEntryPoint(context, bufSize))
4085 {
4086 return false;
4087 }
4088
Geoff Langebebe1c2016-10-14 12:01:31 -04004089 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004090 {
4091 return false;
4092 }
4093
Geoff Langebebe1c2016-10-14 12:01:31 -04004094 if (!ValidateRobustBufferSize(context, bufSize, *length))
4095 {
4096 return false;
4097 }
4098
4099 return true;
4100}
4101
Geoff Langebebe1c2016-10-14 12:01:31 -04004102bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004103 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004104 GLenum pname,
4105 GLsizei bufSize,
4106 GLsizei *length,
4107 GLint64 *params)
4108{
4109 if (!ValidateRobustEntryPoint(context, bufSize))
4110 {
4111 return false;
4112 }
4113
4114 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4115 {
4116 return false;
4117 }
4118
4119 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004120 {
4121 return false;
4122 }
4123
4124 return true;
4125}
4126
Jamie Madillbe849e42017-05-02 15:49:00 -04004127bool ValidateGetProgramivBase(ValidationContext *context,
4128 GLuint program,
4129 GLenum pname,
4130 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004131{
4132 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004133 if (numParams)
4134 {
4135 *numParams = 1;
4136 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004137
4138 Program *programObject = GetValidProgram(context, program);
4139 if (!programObject)
4140 {
4141 return false;
4142 }
4143
4144 switch (pname)
4145 {
4146 case GL_DELETE_STATUS:
4147 case GL_LINK_STATUS:
4148 case GL_VALIDATE_STATUS:
4149 case GL_INFO_LOG_LENGTH:
4150 case GL_ATTACHED_SHADERS:
4151 case GL_ACTIVE_ATTRIBUTES:
4152 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4153 case GL_ACTIVE_UNIFORMS:
4154 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4155 break;
4156
4157 case GL_PROGRAM_BINARY_LENGTH:
4158 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4159 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004160 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4161 "requires GL_OES_get_program_binary or "
4162 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004163 return false;
4164 }
4165 break;
4166
4167 case GL_ACTIVE_UNIFORM_BLOCKS:
4168 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4169 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4170 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4171 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4172 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4173 if (context->getClientMajorVersion() < 3)
4174 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004175 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004176 return false;
4177 }
4178 break;
4179
Yunchao He61afff12017-03-14 15:34:03 +08004180 case GL_PROGRAM_SEPARABLE:
Xinghua Cao971f8502017-10-17 13:01:24 +08004181 case GL_COMPUTE_WORK_GROUP_SIZE:
jchen1058f67be2017-10-27 08:59:27 +08004182 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004183 if (context->getClientVersion() < Version(3, 1))
4184 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004185 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004186 return false;
4187 }
4188 break;
4189
Geoff Langff5b2d52016-09-07 11:32:23 -04004190 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004191 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004192 return false;
4193 }
4194
4195 return true;
4196}
4197
4198bool ValidateGetProgramivRobustANGLE(Context *context,
4199 GLuint program,
4200 GLenum pname,
4201 GLsizei bufSize,
4202 GLsizei *numParams)
4203{
4204 if (!ValidateRobustEntryPoint(context, bufSize))
4205 {
4206 return false;
4207 }
4208
Jamie Madillbe849e42017-05-02 15:49:00 -04004209 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004210 {
4211 return false;
4212 }
4213
4214 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4215 {
4216 return false;
4217 }
4218
4219 return true;
4220}
4221
Geoff Lang740d9022016-10-07 11:20:52 -04004222bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4223 GLenum target,
4224 GLenum pname,
4225 GLsizei bufSize,
4226 GLsizei *length,
4227 GLint *params)
4228{
4229 if (!ValidateRobustEntryPoint(context, bufSize))
4230 {
4231 return false;
4232 }
4233
4234 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4235 {
4236 return false;
4237 }
4238
4239 if (!ValidateRobustBufferSize(context, bufSize, *length))
4240 {
4241 return false;
4242 }
4243
4244 return true;
4245}
4246
Geoff Langd7d0ed32016-10-07 11:33:51 -04004247bool ValidateGetShaderivRobustANGLE(Context *context,
4248 GLuint shader,
4249 GLenum pname,
4250 GLsizei bufSize,
4251 GLsizei *length,
4252 GLint *params)
4253{
4254 if (!ValidateRobustEntryPoint(context, bufSize))
4255 {
4256 return false;
4257 }
4258
4259 if (!ValidateGetShaderivBase(context, shader, pname, length))
4260 {
4261 return false;
4262 }
4263
4264 if (!ValidateRobustBufferSize(context, bufSize, *length))
4265 {
4266 return false;
4267 }
4268
4269 return true;
4270}
4271
Geoff Langc1984ed2016-10-07 12:41:00 -04004272bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4273 GLenum target,
4274 GLenum pname,
4275 GLsizei bufSize,
4276 GLsizei *length,
4277 GLfloat *params)
4278{
4279 if (!ValidateRobustEntryPoint(context, bufSize))
4280 {
4281 return false;
4282 }
4283
4284 if (!ValidateGetTexParameterBase(context, target, pname, length))
4285 {
4286 return false;
4287 }
4288
4289 if (!ValidateRobustBufferSize(context, bufSize, *length))
4290 {
4291 return false;
4292 }
4293
4294 return true;
4295}
4296
Geoff Langc1984ed2016-10-07 12:41:00 -04004297bool ValidateGetTexParameterivRobustANGLE(Context *context,
4298 GLenum target,
4299 GLenum pname,
4300 GLsizei bufSize,
4301 GLsizei *length,
4302 GLint *params)
4303{
4304 if (!ValidateRobustEntryPoint(context, bufSize))
4305 {
4306 return false;
4307 }
4308
4309 if (!ValidateGetTexParameterBase(context, target, pname, length))
4310 {
4311 return false;
4312 }
4313
4314 if (!ValidateRobustBufferSize(context, bufSize, *length))
4315 {
4316 return false;
4317 }
4318
4319 return true;
4320}
4321
Geoff Langc1984ed2016-10-07 12:41:00 -04004322bool ValidateTexParameterfvRobustANGLE(Context *context,
4323 GLenum target,
4324 GLenum pname,
4325 GLsizei bufSize,
4326 const GLfloat *params)
4327{
4328 if (!ValidateRobustEntryPoint(context, bufSize))
4329 {
4330 return false;
4331 }
4332
4333 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4334}
4335
Geoff Langc1984ed2016-10-07 12:41:00 -04004336bool ValidateTexParameterivRobustANGLE(Context *context,
4337 GLenum target,
4338 GLenum pname,
4339 GLsizei bufSize,
4340 const GLint *params)
4341{
4342 if (!ValidateRobustEntryPoint(context, bufSize))
4343 {
4344 return false;
4345 }
4346
4347 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4348}
4349
Geoff Langc1984ed2016-10-07 12:41:00 -04004350bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4351 GLuint sampler,
4352 GLenum pname,
4353 GLuint bufSize,
4354 GLsizei *length,
4355 GLfloat *params)
4356{
4357 if (!ValidateRobustEntryPoint(context, bufSize))
4358 {
4359 return false;
4360 }
4361
4362 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4363 {
4364 return false;
4365 }
4366
4367 if (!ValidateRobustBufferSize(context, bufSize, *length))
4368 {
4369 return false;
4370 }
4371
4372 return true;
4373}
4374
Geoff Langc1984ed2016-10-07 12:41:00 -04004375bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4376 GLuint sampler,
4377 GLenum pname,
4378 GLuint bufSize,
4379 GLsizei *length,
4380 GLint *params)
4381{
4382 if (!ValidateRobustEntryPoint(context, bufSize))
4383 {
4384 return false;
4385 }
4386
4387 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4388 {
4389 return false;
4390 }
4391
4392 if (!ValidateRobustBufferSize(context, bufSize, *length))
4393 {
4394 return false;
4395 }
4396
4397 return true;
4398}
4399
Geoff Langc1984ed2016-10-07 12:41:00 -04004400bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4401 GLuint sampler,
4402 GLenum pname,
4403 GLsizei bufSize,
4404 const GLfloat *params)
4405{
4406 if (!ValidateRobustEntryPoint(context, bufSize))
4407 {
4408 return false;
4409 }
4410
4411 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4412}
4413
Geoff Langc1984ed2016-10-07 12:41:00 -04004414bool ValidateSamplerParameterivRobustANGLE(Context *context,
4415 GLuint sampler,
4416 GLenum pname,
4417 GLsizei bufSize,
4418 const GLint *params)
4419{
4420 if (!ValidateRobustEntryPoint(context, bufSize))
4421 {
4422 return false;
4423 }
4424
4425 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4426}
4427
Geoff Lang0b031062016-10-13 14:30:04 -04004428bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4429 GLuint index,
4430 GLenum pname,
4431 GLsizei bufSize,
4432 GLsizei *length,
4433 GLfloat *params)
4434{
4435 if (!ValidateRobustEntryPoint(context, bufSize))
4436 {
4437 return false;
4438 }
4439
4440 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4441 {
4442 return false;
4443 }
4444
4445 if (!ValidateRobustBufferSize(context, bufSize, *length))
4446 {
4447 return false;
4448 }
4449
4450 return true;
4451}
4452
Geoff Lang0b031062016-10-13 14:30:04 -04004453bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4454 GLuint index,
4455 GLenum pname,
4456 GLsizei bufSize,
4457 GLsizei *length,
4458 GLint *params)
4459{
4460 if (!ValidateRobustEntryPoint(context, bufSize))
4461 {
4462 return false;
4463 }
4464
4465 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4466 {
4467 return false;
4468 }
4469
4470 if (!ValidateRobustBufferSize(context, bufSize, *length))
4471 {
4472 return false;
4473 }
4474
4475 return true;
4476}
4477
Geoff Lang0b031062016-10-13 14:30:04 -04004478bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4479 GLuint index,
4480 GLenum pname,
4481 GLsizei bufSize,
4482 GLsizei *length,
4483 void **pointer)
4484{
4485 if (!ValidateRobustEntryPoint(context, bufSize))
4486 {
4487 return false;
4488 }
4489
4490 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4491 {
4492 return false;
4493 }
4494
4495 if (!ValidateRobustBufferSize(context, bufSize, *length))
4496 {
4497 return false;
4498 }
4499
4500 return true;
4501}
4502
Geoff Lang0b031062016-10-13 14:30:04 -04004503bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4504 GLuint index,
4505 GLenum pname,
4506 GLsizei bufSize,
4507 GLsizei *length,
4508 GLint *params)
4509{
4510 if (!ValidateRobustEntryPoint(context, bufSize))
4511 {
4512 return false;
4513 }
4514
4515 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4516 {
4517 return false;
4518 }
4519
4520 if (!ValidateRobustBufferSize(context, bufSize, *length))
4521 {
4522 return false;
4523 }
4524
4525 return true;
4526}
4527
Geoff Lang0b031062016-10-13 14:30:04 -04004528bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4529 GLuint index,
4530 GLenum pname,
4531 GLsizei bufSize,
4532 GLsizei *length,
4533 GLuint *params)
4534{
4535 if (!ValidateRobustEntryPoint(context, bufSize))
4536 {
4537 return false;
4538 }
4539
4540 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4541 {
4542 return false;
4543 }
4544
4545 if (!ValidateRobustBufferSize(context, bufSize, *length))
4546 {
4547 return false;
4548 }
4549
4550 return true;
4551}
4552
Geoff Lang6899b872016-10-14 11:30:13 -04004553bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4554 GLuint program,
4555 GLuint uniformBlockIndex,
4556 GLenum pname,
4557 GLsizei bufSize,
4558 GLsizei *length,
4559 GLint *params)
4560{
4561 if (!ValidateRobustEntryPoint(context, bufSize))
4562 {
4563 return false;
4564 }
4565
4566 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4567 {
4568 return false;
4569 }
4570
4571 if (!ValidateRobustBufferSize(context, bufSize, *length))
4572 {
4573 return false;
4574 }
4575
4576 return true;
4577}
4578
Geoff Lang0a9661f2016-10-20 10:59:20 -07004579bool ValidateGetInternalFormativRobustANGLE(Context *context,
4580 GLenum target,
4581 GLenum internalformat,
4582 GLenum pname,
4583 GLsizei bufSize,
4584 GLsizei *length,
4585 GLint *params)
4586{
4587 if (!ValidateRobustEntryPoint(context, bufSize))
4588 {
4589 return false;
4590 }
4591
4592 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4593 {
4594 return false;
4595 }
4596
4597 if (!ValidateRobustBufferSize(context, bufSize, *length))
4598 {
4599 return false;
4600 }
4601
4602 return true;
4603}
4604
Shao80957d92017-02-20 21:25:59 +08004605bool ValidateVertexFormatBase(ValidationContext *context,
4606 GLuint attribIndex,
4607 GLint size,
4608 GLenum type,
4609 GLboolean pureInteger)
4610{
4611 const Caps &caps = context->getCaps();
4612 if (attribIndex >= caps.maxVertexAttributes)
4613 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004614 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004615 return false;
4616 }
4617
4618 if (size < 1 || size > 4)
4619 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004620 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004621 return false;
Shao80957d92017-02-20 21:25:59 +08004622 }
4623
4624 switch (type)
4625 {
4626 case GL_BYTE:
4627 case GL_UNSIGNED_BYTE:
4628 case GL_SHORT:
4629 case GL_UNSIGNED_SHORT:
4630 break;
4631
4632 case GL_INT:
4633 case GL_UNSIGNED_INT:
4634 if (context->getClientMajorVersion() < 3)
4635 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004636 context->handleError(InvalidEnum()
4637 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004638 return false;
4639 }
4640 break;
4641
4642 case GL_FIXED:
4643 case GL_FLOAT:
4644 if (pureInteger)
4645 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004646 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004647 return false;
4648 }
4649 break;
4650
4651 case GL_HALF_FLOAT:
4652 if (context->getClientMajorVersion() < 3)
4653 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004654 context->handleError(InvalidEnum()
4655 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004656 return false;
4657 }
4658 if (pureInteger)
4659 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004660 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004661 return false;
4662 }
4663 break;
4664
4665 case GL_INT_2_10_10_10_REV:
4666 case GL_UNSIGNED_INT_2_10_10_10_REV:
4667 if (context->getClientMajorVersion() < 3)
4668 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004669 context->handleError(InvalidEnum()
4670 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004671 return false;
4672 }
4673 if (pureInteger)
4674 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004675 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004676 return false;
4677 }
4678 if (size != 4)
4679 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004680 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4681 "UNSIGNED_INT_2_10_10_10_REV and "
4682 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004683 return false;
4684 }
4685 break;
4686
4687 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004688 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004689 return false;
4690 }
4691
4692 return true;
4693}
4694
Geoff Lang76e65652017-03-27 14:58:02 -04004695// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4696// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4697// specified clear value and the type of a buffer that is being cleared generates an
4698// INVALID_OPERATION error instead of producing undefined results
4699bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4700 GLint drawbuffer,
4701 const GLenum *validComponentTypes,
4702 size_t validComponentTypeCount)
4703{
4704 const FramebufferAttachment *attachment =
4705 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4706 if (attachment)
4707 {
4708 GLenum componentType = attachment->getFormat().info->componentType;
4709 const GLenum *end = validComponentTypes + validComponentTypeCount;
4710 if (std::find(validComponentTypes, end, componentType) == end)
4711 {
4712 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004713 InvalidOperation()
4714 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004715 return false;
4716 }
4717 }
4718
4719 return true;
4720}
4721
Corentin Wallezb2931602017-04-11 15:58:57 -04004722bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4723 GLsizei imageSize,
4724 GLsizei dataSize)
4725{
4726 if (!ValidateRobustEntryPoint(context, dataSize))
4727 {
4728 return false;
4729 }
4730
Corentin Wallez336129f2017-10-17 15:55:40 -04004731 gl::Buffer *pixelUnpackBuffer =
4732 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004733 if (pixelUnpackBuffer == nullptr)
4734 {
4735 if (dataSize < imageSize)
4736 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004737 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004738 }
4739 }
4740 return true;
4741}
4742
Jamie Madillbe849e42017-05-02 15:49:00 -04004743bool ValidateGetBufferParameterBase(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004744 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004745 GLenum pname,
4746 bool pointerVersion,
4747 GLsizei *numParams)
4748{
4749 if (numParams)
4750 {
4751 *numParams = 0;
4752 }
4753
Corentin Wallez336129f2017-10-17 15:55:40 -04004754 if (!ValidBufferType(context, target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004755 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004756 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004757 return false;
4758 }
4759
4760 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4761 if (!buffer)
4762 {
4763 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004764 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004765 return false;
4766 }
4767
4768 const Extensions &extensions = context->getExtensions();
4769
4770 switch (pname)
4771 {
4772 case GL_BUFFER_USAGE:
4773 case GL_BUFFER_SIZE:
4774 break;
4775
4776 case GL_BUFFER_ACCESS_OES:
4777 if (!extensions.mapBuffer)
4778 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004779 context->handleError(InvalidEnum()
4780 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004781 return false;
4782 }
4783 break;
4784
4785 case GL_BUFFER_MAPPED:
4786 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4787 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4788 !extensions.mapBufferRange)
4789 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004790 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4791 "GL_OES_mapbuffer or "
4792 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004793 return false;
4794 }
4795 break;
4796
4797 case GL_BUFFER_MAP_POINTER:
4798 if (!pointerVersion)
4799 {
4800 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004801 InvalidEnum()
4802 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004803 return false;
4804 }
4805 break;
4806
4807 case GL_BUFFER_ACCESS_FLAGS:
4808 case GL_BUFFER_MAP_OFFSET:
4809 case GL_BUFFER_MAP_LENGTH:
4810 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4811 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004812 context->handleError(InvalidEnum()
4813 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004814 return false;
4815 }
4816 break;
4817
4818 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004819 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004820 return false;
4821 }
4822
4823 // All buffer parameter queries return one value.
4824 if (numParams)
4825 {
4826 *numParams = 1;
4827 }
4828
4829 return true;
4830}
4831
4832bool ValidateGetRenderbufferParameterivBase(Context *context,
4833 GLenum target,
4834 GLenum pname,
4835 GLsizei *length)
4836{
4837 if (length)
4838 {
4839 *length = 0;
4840 }
4841
4842 if (target != GL_RENDERBUFFER)
4843 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004844 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004845 return false;
4846 }
4847
4848 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4849 if (renderbuffer == nullptr)
4850 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004851 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004852 return false;
4853 }
4854
4855 switch (pname)
4856 {
4857 case GL_RENDERBUFFER_WIDTH:
4858 case GL_RENDERBUFFER_HEIGHT:
4859 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4860 case GL_RENDERBUFFER_RED_SIZE:
4861 case GL_RENDERBUFFER_GREEN_SIZE:
4862 case GL_RENDERBUFFER_BLUE_SIZE:
4863 case GL_RENDERBUFFER_ALPHA_SIZE:
4864 case GL_RENDERBUFFER_DEPTH_SIZE:
4865 case GL_RENDERBUFFER_STENCIL_SIZE:
4866 break;
4867
4868 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4869 if (!context->getExtensions().framebufferMultisample)
4870 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004871 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004872 return false;
4873 }
4874 break;
4875
4876 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004877 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004878 return false;
4879 }
4880
4881 if (length)
4882 {
4883 *length = 1;
4884 }
4885 return true;
4886}
4887
4888bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4889{
4890 if (length)
4891 {
4892 *length = 0;
4893 }
4894
4895 if (GetValidShader(context, shader) == nullptr)
4896 {
4897 return false;
4898 }
4899
4900 switch (pname)
4901 {
4902 case GL_SHADER_TYPE:
4903 case GL_DELETE_STATUS:
4904 case GL_COMPILE_STATUS:
4905 case GL_INFO_LOG_LENGTH:
4906 case GL_SHADER_SOURCE_LENGTH:
4907 break;
4908
4909 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4910 if (!context->getExtensions().translatedShaderSource)
4911 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004912 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004913 return false;
4914 }
4915 break;
4916
4917 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004918 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004919 return false;
4920 }
4921
4922 if (length)
4923 {
4924 *length = 1;
4925 }
4926 return true;
4927}
4928
4929bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4930{
4931 if (length)
4932 {
4933 *length = 0;
4934 }
4935
4936 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4937 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004938 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004939 return false;
4940 }
4941
4942 if (context->getTargetTexture(target) == nullptr)
4943 {
4944 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004945 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004946 return false;
4947 }
4948
4949 switch (pname)
4950 {
4951 case GL_TEXTURE_MAG_FILTER:
4952 case GL_TEXTURE_MIN_FILTER:
4953 case GL_TEXTURE_WRAP_S:
4954 case GL_TEXTURE_WRAP_T:
4955 break;
4956
4957 case GL_TEXTURE_USAGE_ANGLE:
4958 if (!context->getExtensions().textureUsage)
4959 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004960 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004961 return false;
4962 }
4963 break;
4964
4965 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
4966 if (!context->getExtensions().textureFilterAnisotropic)
4967 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004968 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004969 return false;
4970 }
4971 break;
4972
4973 case GL_TEXTURE_IMMUTABLE_FORMAT:
4974 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4975 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004976 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004977 return false;
4978 }
4979 break;
4980
4981 case GL_TEXTURE_WRAP_R:
4982 case GL_TEXTURE_IMMUTABLE_LEVELS:
4983 case GL_TEXTURE_SWIZZLE_R:
4984 case GL_TEXTURE_SWIZZLE_G:
4985 case GL_TEXTURE_SWIZZLE_B:
4986 case GL_TEXTURE_SWIZZLE_A:
4987 case GL_TEXTURE_BASE_LEVEL:
4988 case GL_TEXTURE_MAX_LEVEL:
4989 case GL_TEXTURE_MIN_LOD:
4990 case GL_TEXTURE_MAX_LOD:
4991 case GL_TEXTURE_COMPARE_MODE:
4992 case GL_TEXTURE_COMPARE_FUNC:
4993 if (context->getClientMajorVersion() < 3)
4994 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004995 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004996 return false;
4997 }
4998 break;
4999
5000 case GL_TEXTURE_SRGB_DECODE_EXT:
5001 if (!context->getExtensions().textureSRGBDecode)
5002 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005003 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005004 return false;
5005 }
5006 break;
5007
5008 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005009 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005010 return false;
5011 }
5012
5013 if (length)
5014 {
5015 *length = 1;
5016 }
5017 return true;
5018}
5019
5020bool ValidateGetVertexAttribBase(Context *context,
5021 GLuint index,
5022 GLenum pname,
5023 GLsizei *length,
5024 bool pointer,
5025 bool pureIntegerEntryPoint)
5026{
5027 if (length)
5028 {
5029 *length = 0;
5030 }
5031
5032 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
5033 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005034 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005035 return false;
5036 }
5037
5038 if (index >= context->getCaps().maxVertexAttributes)
5039 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005040 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04005041 return false;
5042 }
5043
5044 if (pointer)
5045 {
5046 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5047 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005048 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005049 return false;
5050 }
5051 }
5052 else
5053 {
5054 switch (pname)
5055 {
5056 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5057 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5058 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5059 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5060 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5061 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5062 case GL_CURRENT_VERTEX_ATTRIB:
5063 break;
5064
5065 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5066 static_assert(
5067 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5068 "ANGLE extension enums not equal to GL enums.");
5069 if (context->getClientMajorVersion() < 3 &&
5070 !context->getExtensions().instancedArrays)
5071 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005072 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5073 "requires OpenGL ES 3.0 or "
5074 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005075 return false;
5076 }
5077 break;
5078
5079 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5080 if (context->getClientMajorVersion() < 3)
5081 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005082 context->handleError(
5083 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005084 return false;
5085 }
5086 break;
5087
5088 case GL_VERTEX_ATTRIB_BINDING:
5089 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5090 if (context->getClientVersion() < ES_3_1)
5091 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005092 context->handleError(InvalidEnum()
5093 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005094 return false;
5095 }
5096 break;
5097
5098 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005099 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005100 return false;
5101 }
5102 }
5103
5104 if (length)
5105 {
5106 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5107 {
5108 *length = 4;
5109 }
5110 else
5111 {
5112 *length = 1;
5113 }
5114 }
5115
5116 return true;
5117}
5118
Jamie Madill4928b7c2017-06-20 12:57:39 -04005119bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005120 GLint x,
5121 GLint y,
5122 GLsizei width,
5123 GLsizei height,
5124 GLenum format,
5125 GLenum type,
5126 GLsizei bufSize,
5127 GLsizei *length,
5128 GLsizei *columns,
5129 GLsizei *rows,
5130 void *pixels)
5131{
5132 if (length != nullptr)
5133 {
5134 *length = 0;
5135 }
5136 if (rows != nullptr)
5137 {
5138 *rows = 0;
5139 }
5140 if (columns != nullptr)
5141 {
5142 *columns = 0;
5143 }
5144
5145 if (width < 0 || height < 0)
5146 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005147 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005148 return false;
5149 }
5150
5151 auto readFramebuffer = context->getGLState().getReadFramebuffer();
5152
5153 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5154 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005155 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005156 return false;
5157 }
5158
5159 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5160 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005161 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005162 return false;
5163 }
5164
5165 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5166 ASSERT(framebuffer);
5167
5168 if (framebuffer->getReadBufferState() == GL_NONE)
5169 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005170 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005171 return false;
5172 }
5173
5174 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5175 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5176 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5177 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5178 // situation is an application error that would lead to a crash in ANGLE.
5179 if (readBuffer == nullptr)
5180 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005181 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005182 return false;
5183 }
5184
Martin Radev28031682017-07-28 14:47:56 +03005185 // ANGLE_multiview, Revision 1:
5186 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5187 // current read framebuffer is not NONE.
5188 if (readBuffer->getMultiviewLayout() != GL_NONE)
5189 {
5190 context->handleError(InvalidFramebufferOperation()
5191 << "Attempting to read from a multi-view framebuffer.");
5192 return false;
5193 }
5194
Geoff Lang280ba992017-04-18 16:30:58 -04005195 if (context->getExtensions().webglCompatibility)
5196 {
5197 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5198 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5199 // and type before validating the combination of format and type. However, the
5200 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5201 // verifies that GL_INVALID_OPERATION is generated.
5202 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5203 // dEQP/WebGL.
5204 if (!ValidReadPixelsFormatEnum(context, format))
5205 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005206 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005207 return false;
5208 }
5209
5210 if (!ValidReadPixelsTypeEnum(context, type))
5211 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005212 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005213 return false;
5214 }
5215 }
5216
Jamie Madill4928b7c2017-06-20 12:57:39 -04005217 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5218 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005219 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5220
5221 bool validFormatTypeCombination =
5222 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5223
5224 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5225 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005226 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005227 return false;
5228 }
5229
5230 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005231 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005232 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5233 {
5234 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005235 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005236 return false;
5237 }
5238
5239 // .. the data would be packed to the buffer object such that the memory writes required
5240 // would exceed the data store size.
5241 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5242 const gl::Extents size(width, height, 1);
5243 const auto &pack = context->getGLState().getPackState();
5244
5245 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5246 if (endByteOrErr.isError())
5247 {
5248 context->handleError(endByteOrErr.getError());
5249 return false;
5250 }
5251
5252 size_t endByte = endByteOrErr.getResult();
5253 if (bufSize >= 0)
5254 {
5255 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5256 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005257 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005258 return false;
5259 }
5260 }
5261
5262 if (pixelPackBuffer != nullptr)
5263 {
5264 CheckedNumeric<size_t> checkedEndByte(endByte);
5265 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5266 checkedEndByte += checkedOffset;
5267
5268 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5269 {
5270 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005271 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005272 return false;
5273 }
5274 }
5275
5276 if (pixelPackBuffer == nullptr && length != nullptr)
5277 {
5278 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5279 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005280 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005281 return false;
5282 }
5283
5284 *length = static_cast<GLsizei>(endByte);
5285 }
5286
5287 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5288 angle::CheckedNumeric<int> clippedExtent(length);
5289 if (start < 0)
5290 {
5291 // "subtract" the area that is less than 0
5292 clippedExtent += start;
5293 }
5294
5295 const int readExtent = start + length;
5296 if (readExtent > bufferSize)
5297 {
5298 // Subtract the region to the right of the read buffer
5299 clippedExtent -= (readExtent - bufferSize);
5300 }
5301
5302 if (!clippedExtent.IsValid())
5303 {
5304 return 0;
5305 }
5306
5307 return std::max(clippedExtent.ValueOrDie(), 0);
5308 };
5309
5310 if (columns != nullptr)
5311 {
5312 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5313 }
5314
5315 if (rows != nullptr)
5316 {
5317 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5318 }
5319
5320 return true;
5321}
5322
5323template <typename ParamType>
5324bool ValidateTexParameterBase(Context *context,
5325 GLenum target,
5326 GLenum pname,
5327 GLsizei bufSize,
5328 const ParamType *params)
5329{
5330 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5331 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005332 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005333 return false;
5334 }
5335
5336 if (context->getTargetTexture(target) == nullptr)
5337 {
5338 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005339 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005340 return false;
5341 }
5342
5343 const GLsizei minBufSize = 1;
5344 if (bufSize >= 0 && bufSize < minBufSize)
5345 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005346 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005347 return false;
5348 }
5349
5350 switch (pname)
5351 {
5352 case GL_TEXTURE_WRAP_R:
5353 case GL_TEXTURE_SWIZZLE_R:
5354 case GL_TEXTURE_SWIZZLE_G:
5355 case GL_TEXTURE_SWIZZLE_B:
5356 case GL_TEXTURE_SWIZZLE_A:
5357 case GL_TEXTURE_BASE_LEVEL:
5358 case GL_TEXTURE_MAX_LEVEL:
5359 case GL_TEXTURE_COMPARE_MODE:
5360 case GL_TEXTURE_COMPARE_FUNC:
5361 case GL_TEXTURE_MIN_LOD:
5362 case GL_TEXTURE_MAX_LOD:
5363 if (context->getClientMajorVersion() < 3)
5364 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005365 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005366 return false;
5367 }
5368 if (target == GL_TEXTURE_EXTERNAL_OES &&
5369 !context->getExtensions().eglImageExternalEssl3)
5370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005371 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5372 "available without "
5373 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005374 return false;
5375 }
5376 break;
5377
5378 default:
5379 break;
5380 }
5381
JiangYizhou4cff8d62017-07-06 14:54:09 +08005382 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5383 {
5384 switch (pname)
5385 {
5386 case GL_TEXTURE_MIN_FILTER:
5387 case GL_TEXTURE_MAG_FILTER:
5388 case GL_TEXTURE_WRAP_S:
5389 case GL_TEXTURE_WRAP_T:
5390 case GL_TEXTURE_WRAP_R:
5391 case GL_TEXTURE_MIN_LOD:
5392 case GL_TEXTURE_MAX_LOD:
5393 case GL_TEXTURE_COMPARE_MODE:
5394 case GL_TEXTURE_COMPARE_FUNC:
5395 context->handleError(InvalidEnum()
5396 << "Invalid parameter for 2D multisampled textures.");
5397 return false;
5398 }
5399 }
5400
Jamie Madillbe849e42017-05-02 15:49:00 -04005401 switch (pname)
5402 {
5403 case GL_TEXTURE_WRAP_S:
5404 case GL_TEXTURE_WRAP_T:
5405 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005406 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005407 bool restrictedWrapModes =
5408 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5409 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5410 {
5411 return false;
5412 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005413 }
5414 break;
5415
5416 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005417 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005418 bool restrictedMinFilter =
5419 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5420 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5421 {
5422 return false;
5423 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005424 }
5425 break;
5426
5427 case GL_TEXTURE_MAG_FILTER:
5428 if (!ValidateTextureMagFilterValue(context, params))
5429 {
5430 return false;
5431 }
5432 break;
5433
5434 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005435 if (!context->getExtensions().textureUsage)
5436 {
5437 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5438 return false;
5439 }
5440
Jamie Madillbe849e42017-05-02 15:49:00 -04005441 switch (ConvertToGLenum(params[0]))
5442 {
5443 case GL_NONE:
5444 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5445 break;
5446
5447 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005448 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005449 return false;
5450 }
5451 break;
5452
5453 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5454 if (!context->getExtensions().textureFilterAnisotropic)
5455 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005456 context->handleError(InvalidEnum() << "GL_EXT_texture_anisotropic is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005457 return false;
5458 }
5459
5460 // we assume the parameter passed to this validation method is truncated, not rounded
5461 if (params[0] < 1)
5462 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005463 context->handleError(InvalidValue() << "Max anisotropy must be at least 1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005464 return false;
5465 }
5466 break;
5467
5468 case GL_TEXTURE_MIN_LOD:
5469 case GL_TEXTURE_MAX_LOD:
5470 // any value is permissible
5471 break;
5472
5473 case GL_TEXTURE_COMPARE_MODE:
5474 if (!ValidateTextureCompareModeValue(context, params))
5475 {
5476 return false;
5477 }
5478 break;
5479
5480 case GL_TEXTURE_COMPARE_FUNC:
5481 if (!ValidateTextureCompareFuncValue(context, params))
5482 {
5483 return false;
5484 }
5485 break;
5486
5487 case GL_TEXTURE_SWIZZLE_R:
5488 case GL_TEXTURE_SWIZZLE_G:
5489 case GL_TEXTURE_SWIZZLE_B:
5490 case GL_TEXTURE_SWIZZLE_A:
5491 switch (ConvertToGLenum(params[0]))
5492 {
5493 case GL_RED:
5494 case GL_GREEN:
5495 case GL_BLUE:
5496 case GL_ALPHA:
5497 case GL_ZERO:
5498 case GL_ONE:
5499 break;
5500
5501 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005502 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005503 return false;
5504 }
5505 break;
5506
5507 case GL_TEXTURE_BASE_LEVEL:
5508 if (params[0] < 0)
5509 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005510 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005511 return false;
5512 }
5513 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5514 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005515 context->handleError(InvalidOperation()
5516 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005517 return false;
5518 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005519 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5520 {
5521 context->handleError(InvalidOperation()
5522 << "Base level must be 0 for multisampled textures.");
5523 return false;
5524 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005525 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5526 {
5527 context->handleError(InvalidOperation()
5528 << "Base level must be 0 for rectangle textures.");
5529 return false;
5530 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005531 break;
5532
5533 case GL_TEXTURE_MAX_LEVEL:
5534 if (params[0] < 0)
5535 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005536 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005537 return false;
5538 }
5539 break;
5540
5541 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5542 if (context->getClientVersion() < Version(3, 1))
5543 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005544 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005545 return false;
5546 }
5547 switch (ConvertToGLenum(params[0]))
5548 {
5549 case GL_DEPTH_COMPONENT:
5550 case GL_STENCIL_INDEX:
5551 break;
5552
5553 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005554 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005555 return false;
5556 }
5557 break;
5558
5559 case GL_TEXTURE_SRGB_DECODE_EXT:
5560 if (!ValidateTextureSRGBDecodeValue(context, params))
5561 {
5562 return false;
5563 }
5564 break;
5565
5566 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005567 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005568 return false;
5569 }
5570
5571 return true;
5572}
5573
5574template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5575template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5576
Jamie Madill12e957f2017-08-26 21:42:26 -04005577bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5578{
5579 if (index >= MAX_VERTEX_ATTRIBS)
5580 {
5581 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5582 return false;
5583 }
5584
5585 return true;
5586}
5587
5588bool ValidateGetActiveUniformBlockivBase(Context *context,
5589 GLuint program,
5590 GLuint uniformBlockIndex,
5591 GLenum pname,
5592 GLsizei *length)
5593{
5594 if (length)
5595 {
5596 *length = 0;
5597 }
5598
5599 if (context->getClientMajorVersion() < 3)
5600 {
5601 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5602 return false;
5603 }
5604
5605 Program *programObject = GetValidProgram(context, program);
5606 if (!programObject)
5607 {
5608 return false;
5609 }
5610
5611 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5612 {
5613 context->handleError(InvalidValue()
5614 << "uniformBlockIndex exceeds active uniform block count.");
5615 return false;
5616 }
5617
5618 switch (pname)
5619 {
5620 case GL_UNIFORM_BLOCK_BINDING:
5621 case GL_UNIFORM_BLOCK_DATA_SIZE:
5622 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5623 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5624 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5625 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5626 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5627 break;
5628
5629 default:
5630 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5631 return false;
5632 }
5633
5634 if (length)
5635 {
5636 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5637 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005638 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005639 programObject->getUniformBlockByIndex(uniformBlockIndex);
5640 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5641 }
5642 else
5643 {
5644 *length = 1;
5645 }
5646 }
5647
5648 return true;
5649}
5650
Jamie Madill9696d072017-08-26 23:19:57 -04005651template <typename ParamType>
5652bool ValidateSamplerParameterBase(Context *context,
5653 GLuint sampler,
5654 GLenum pname,
5655 GLsizei bufSize,
5656 ParamType *params)
5657{
5658 if (context->getClientMajorVersion() < 3)
5659 {
5660 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5661 return false;
5662 }
5663
5664 if (!context->isSampler(sampler))
5665 {
5666 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5667 return false;
5668 }
5669
5670 const GLsizei minBufSize = 1;
5671 if (bufSize >= 0 && bufSize < minBufSize)
5672 {
5673 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5674 return false;
5675 }
5676
5677 switch (pname)
5678 {
5679 case GL_TEXTURE_WRAP_S:
5680 case GL_TEXTURE_WRAP_T:
5681 case GL_TEXTURE_WRAP_R:
5682 if (!ValidateTextureWrapModeValue(context, params, false))
5683 {
5684 return false;
5685 }
5686 break;
5687
5688 case GL_TEXTURE_MIN_FILTER:
5689 if (!ValidateTextureMinFilterValue(context, params, false))
5690 {
5691 return false;
5692 }
5693 break;
5694
5695 case GL_TEXTURE_MAG_FILTER:
5696 if (!ValidateTextureMagFilterValue(context, params))
5697 {
5698 return false;
5699 }
5700 break;
5701
5702 case GL_TEXTURE_MIN_LOD:
5703 case GL_TEXTURE_MAX_LOD:
5704 // any value is permissible
5705 break;
5706
5707 case GL_TEXTURE_COMPARE_MODE:
5708 if (!ValidateTextureCompareModeValue(context, params))
5709 {
5710 return false;
5711 }
5712 break;
5713
5714 case GL_TEXTURE_COMPARE_FUNC:
5715 if (!ValidateTextureCompareFuncValue(context, params))
5716 {
5717 return false;
5718 }
5719 break;
5720
5721 case GL_TEXTURE_SRGB_DECODE_EXT:
5722 if (!ValidateTextureSRGBDecodeValue(context, params))
5723 {
5724 return false;
5725 }
5726 break;
5727
5728 default:
5729 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5730 return false;
5731 }
5732
5733 return true;
5734}
5735
5736template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5737template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5738
5739bool ValidateGetSamplerParameterBase(Context *context,
5740 GLuint sampler,
5741 GLenum pname,
5742 GLsizei *length)
5743{
5744 if (length)
5745 {
5746 *length = 0;
5747 }
5748
5749 if (context->getClientMajorVersion() < 3)
5750 {
5751 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5752 return false;
5753 }
5754
5755 if (!context->isSampler(sampler))
5756 {
5757 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5758 return false;
5759 }
5760
5761 switch (pname)
5762 {
5763 case GL_TEXTURE_WRAP_S:
5764 case GL_TEXTURE_WRAP_T:
5765 case GL_TEXTURE_WRAP_R:
5766 case GL_TEXTURE_MIN_FILTER:
5767 case GL_TEXTURE_MAG_FILTER:
5768 case GL_TEXTURE_MIN_LOD:
5769 case GL_TEXTURE_MAX_LOD:
5770 case GL_TEXTURE_COMPARE_MODE:
5771 case GL_TEXTURE_COMPARE_FUNC:
5772 break;
5773
5774 case GL_TEXTURE_SRGB_DECODE_EXT:
5775 if (!context->getExtensions().textureSRGBDecode)
5776 {
5777 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5778 return false;
5779 }
5780 break;
5781
5782 default:
5783 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5784 return false;
5785 }
5786
5787 if (length)
5788 {
5789 *length = 1;
5790 }
5791 return true;
5792}
5793
5794bool ValidateGetInternalFormativBase(Context *context,
5795 GLenum target,
5796 GLenum internalformat,
5797 GLenum pname,
5798 GLsizei bufSize,
5799 GLsizei *numParams)
5800{
5801 if (numParams)
5802 {
5803 *numParams = 0;
5804 }
5805
5806 if (context->getClientMajorVersion() < 3)
5807 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005808 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005809 return false;
5810 }
5811
5812 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5813 if (!formatCaps.renderable)
5814 {
5815 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5816 return false;
5817 }
5818
5819 switch (target)
5820 {
5821 case GL_RENDERBUFFER:
5822 break;
5823
5824 case GL_TEXTURE_2D_MULTISAMPLE:
5825 if (context->getClientVersion() < ES_3_1)
5826 {
5827 context->handleError(InvalidOperation()
5828 << "Texture target requires at least OpenGL ES 3.1.");
5829 return false;
5830 }
5831 break;
5832
5833 default:
5834 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5835 return false;
5836 }
5837
5838 if (bufSize < 0)
5839 {
5840 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5841 return false;
5842 }
5843
5844 GLsizei maxWriteParams = 0;
5845 switch (pname)
5846 {
5847 case GL_NUM_SAMPLE_COUNTS:
5848 maxWriteParams = 1;
5849 break;
5850
5851 case GL_SAMPLES:
5852 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5853 break;
5854
5855 default:
5856 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5857 return false;
5858 }
5859
5860 if (numParams)
5861 {
5862 // glGetInternalFormativ will not overflow bufSize
5863 *numParams = std::min(bufSize, maxWriteParams);
5864 }
5865
5866 return true;
5867}
5868
Jamie Madillc29968b2016-01-20 11:17:23 -05005869} // namespace gl