blob: 41e859acb85a82ee296996a20a8deec5b0fcc777 [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"
21#include "libANGLE/VertexArray.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040022#include "libANGLE/formatutils.h"
jchen10a99ed552017-09-22 08:10:32 +080023#include "libANGLE/queryconversions.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040024#include "libANGLE/validationES2.h"
25#include "libANGLE/validationES3.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040026
27#include "common/mathutil.h"
28#include "common/utilities.h"
29
Jamie Madille2e406c2016-06-02 13:04:10 -040030using namespace angle;
31
Geoff Lange8ebe7f2013-08-05 15:03:13 -040032namespace gl
33{
Jamie Madill1ca74672015-07-21 15:14:11 -040034namespace
35{
jchen10a99ed552017-09-22 08:10:32 +080036
Corentin Wallez92db6942016-12-09 13:10:36 -050037bool ValidateDrawAttribs(ValidationContext *context,
38 GLint primcount,
39 GLint maxVertex,
40 GLint vertexCount)
Jamie Madill1ca74672015-07-21 15:14:11 -040041{
Jamie Madilldfde6ab2016-06-09 07:07:18 -070042 const gl::State &state = context->getGLState();
Jamie Madill1ca74672015-07-21 15:14:11 -040043 const gl::Program *program = state.getProgram();
44
Corentin Wallez327411e2016-12-09 11:09:17 -050045 bool webglCompatibility = context->getExtensions().webglCompatibility;
46
Jamie Madill231c7f52017-04-26 13:45:37 -040047 const VertexArray *vao = state.getVertexArray();
48 const auto &vertexAttribs = vao->getVertexAttributes();
Jiawei-Shao2597fb62016-12-09 16:38:02 +080049 const auto &vertexBindings = vao->getVertexBindings();
Jamie Madilld078c682018-01-02 11:50:24 -050050 for (size_t attributeIndex : vao->getEnabledAttributesMask())
Jamie Madill1ca74672015-07-21 15:14:11 -040051 {
52 const VertexAttribute &attrib = vertexAttribs[attributeIndex];
Corentin Wallez672f7f32017-06-15 17:42:17 -040053
54 // No need to range check for disabled attribs.
55 if (!attrib.enabled)
Jamie Madill1ca74672015-07-21 15:14:11 -040056 {
Corentin Wallezfd456442016-12-21 17:57:00 -050057 continue;
58 }
Jamie Madill1ca74672015-07-21 15:14:11 -040059
Jamie Madill231c7f52017-04-26 13:45:37 -040060 // If we have no buffer, then we either get an error, or there are no more checks to be
61 // done.
Corentin Wallez672f7f32017-06-15 17:42:17 -040062 const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
63 gl::Buffer *buffer = binding.getBuffer().get();
Corentin Wallezfd456442016-12-21 17:57:00 -050064 if (!buffer)
65 {
Geoff Langfeb8c682017-02-13 16:07:35 -050066 if (webglCompatibility || !state.areClientArraysEnabled())
Corentin Wallez327411e2016-12-09 11:09:17 -050067 {
68 // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
Corentin Wallezfd456442016-12-21 17:57:00 -050069 // If a vertex attribute is enabled as an array via enableVertexAttribArray but
70 // no buffer is bound to that attribute via bindBuffer and vertexAttribPointer,
71 // then calls to drawArrays or drawElements will generate an INVALID_OPERATION
72 // error.
Brandon Jonesafa75152017-07-21 13:11:29 -070073 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBuffer);
Corentin Wallezfd456442016-12-21 17:57:00 -050074 return false;
Corentin Wallez327411e2016-12-09 11:09:17 -050075 }
Corentin Wallezfd456442016-12-21 17:57:00 -050076 else if (attrib.pointer == nullptr)
Jamie Madill1ca74672015-07-21 15:14:11 -040077 {
78 // This is an application error that would normally result in a crash,
79 // but we catch it and return an error
Brandon Jonesafa75152017-07-21 13:11:29 -070080 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexArrayNoBufferPointer);
Jamie Madill1ca74672015-07-21 15:14:11 -040081 return false;
82 }
Corentin Wallezfd456442016-12-21 17:57:00 -050083 continue;
84 }
85
Corentin Wallez672f7f32017-06-15 17:42:17 -040086 // This needs to come after the check for client arrays as even unused attributes cannot use
87 // client-side arrays
88 if (!program->isAttribLocationActive(attributeIndex))
89 {
90 continue;
91 }
92
Corentin Wallezfd456442016-12-21 17:57:00 -050093 // If we're drawing zero vertices, we have enough data.
94 if (vertexCount <= 0 || primcount <= 0)
95 {
96 continue;
97 }
98
99 GLint maxVertexElement = 0;
Martin Radevdd5f27e2017-06-07 10:17:09 +0300100 GLuint divisor = binding.getDivisor();
101 if (divisor == 0)
Corentin Wallezfd456442016-12-21 17:57:00 -0500102 {
103 maxVertexElement = maxVertex;
104 }
105 else
106 {
Martin Radevdd5f27e2017-06-07 10:17:09 +0300107 maxVertexElement = (primcount - 1) / divisor;
Corentin Wallezfd456442016-12-21 17:57:00 -0500108 }
109
110 // We do manual overflow checks here instead of using safe_math.h because it was
111 // a bottleneck. Thanks to some properties of GL we know inequalities that can
112 // help us make the overflow checks faster.
113
114 // The max possible attribSize is 16 for a vector of 4 32 bit values.
115 constexpr uint64_t kMaxAttribSize = 16;
116 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
117 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
118
119 // We know attribStride is given as a GLsizei which is typedefed to int.
120 // We also know an upper bound for attribSize.
121 static_assert(std::is_same<int, GLsizei>::value, "");
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800122 uint64_t attribStride = ComputeVertexAttributeStride(attrib, binding);
Corentin Wallezfd456442016-12-21 17:57:00 -0500123 uint64_t attribSize = ComputeVertexAttributeTypeSize(attrib);
124 ASSERT(attribStride <= kIntMax && attribSize <= kMaxAttribSize);
125
126 // Computing the max offset using uint64_t without attrib.offset is overflow
127 // safe. Note: Last vertex element does not take the full stride!
128 static_assert(kIntMax * kIntMax < kUint64Max - kMaxAttribSize, "");
129 uint64_t attribDataSizeNoOffset = maxVertexElement * attribStride + attribSize;
130
131 // An overflow can happen when adding the offset, check for it.
Jiawei-Shao2597fb62016-12-09 16:38:02 +0800132 uint64_t attribOffset = ComputeVertexAttributeOffset(attrib, binding);
133 if (attribDataSizeNoOffset > kUint64Max - attribOffset)
Corentin Wallezfd456442016-12-21 17:57:00 -0500134 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700135 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallezfd456442016-12-21 17:57:00 -0500136 return false;
137 }
138 uint64_t attribDataSizeWithOffset = attribDataSizeNoOffset + attribOffset;
139
140 // [OpenGL ES 3.0.2] section 2.9.4 page 40:
141 // We can return INVALID_OPERATION if our vertex attribute does not have
142 // enough backing data.
143 if (attribDataSizeWithOffset > static_cast<uint64_t>(buffer->getSize()))
144 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700145 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientVertexBufferSize);
Corentin Wallezfd456442016-12-21 17:57:00 -0500146 return false;
Jamie Madill1ca74672015-07-21 15:14:11 -0400147 }
148 }
149
150 return true;
151}
152
Geoff Lang280ba992017-04-18 16:30:58 -0400153bool ValidReadPixelsTypeEnum(ValidationContext *context, GLenum type)
154{
155 switch (type)
156 {
157 // Types referenced in Table 3.4 of the ES 2.0.25 spec
158 case GL_UNSIGNED_BYTE:
159 case GL_UNSIGNED_SHORT_4_4_4_4:
160 case GL_UNSIGNED_SHORT_5_5_5_1:
161 case GL_UNSIGNED_SHORT_5_6_5:
162 return context->getClientVersion() >= ES_2_0;
163
164 // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
165 case GL_BYTE:
166 case GL_INT:
167 case GL_SHORT:
168 case GL_UNSIGNED_INT:
169 case GL_UNSIGNED_INT_10F_11F_11F_REV:
170 case GL_UNSIGNED_INT_24_8:
171 case GL_UNSIGNED_INT_2_10_10_10_REV:
172 case GL_UNSIGNED_INT_5_9_9_9_REV:
173 case GL_UNSIGNED_SHORT:
174 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
175 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
176 return context->getClientVersion() >= ES_3_0;
177
178 case GL_FLOAT:
Geoff Lang7d4602f2017-09-13 10:45:09 -0400179 return context->getClientVersion() >= ES_3_0 || context->getExtensions().textureFloat ||
180 context->getExtensions().colorBufferHalfFloat;
Geoff Lang280ba992017-04-18 16:30:58 -0400181
182 case GL_HALF_FLOAT:
183 return context->getClientVersion() >= ES_3_0 ||
184 context->getExtensions().textureHalfFloat;
185
186 case GL_HALF_FLOAT_OES:
187 return context->getExtensions().colorBufferHalfFloat;
188
189 default:
190 return false;
191 }
192}
193
194bool ValidReadPixelsFormatEnum(ValidationContext *context, GLenum format)
195{
196 switch (format)
197 {
198 // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
199 case GL_RGBA:
200 case GL_RGB:
201 case GL_ALPHA:
202 return context->getClientVersion() >= ES_2_0;
203
204 // Formats referenced in Table 3.2 of the ES 3.0.5 spec
205 case GL_RG:
206 case GL_RED:
207 case GL_RGBA_INTEGER:
208 case GL_RGB_INTEGER:
209 case GL_RG_INTEGER:
210 case GL_RED_INTEGER:
211 return context->getClientVersion() >= ES_3_0;
212
213 case GL_SRGB_ALPHA_EXT:
214 case GL_SRGB_EXT:
215 return context->getExtensions().sRGB;
216
217 case GL_BGRA_EXT:
218 return context->getExtensions().readFormatBGRA;
219
220 default:
221 return false;
222 }
223}
224
Geoff Langf607c602016-09-21 11:46:48 -0400225bool ValidReadPixelsFormatType(ValidationContext *context,
226 GLenum framebufferComponentType,
227 GLenum format,
228 GLenum type)
229{
230 switch (framebufferComponentType)
231 {
232 case GL_UNSIGNED_NORMALIZED:
233 // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
234 // ReadPixels with BGRA even if the extension is not present
235 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
236 (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
237 type == GL_UNSIGNED_BYTE);
238
239 case GL_SIGNED_NORMALIZED:
240 return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
241
242 case GL_INT:
243 return (format == GL_RGBA_INTEGER && type == GL_INT);
244
245 case GL_UNSIGNED_INT:
246 return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
247
248 case GL_FLOAT:
249 return (format == GL_RGBA && type == GL_FLOAT);
250
251 default:
252 UNREACHABLE();
253 return false;
254 }
255}
256
Geoff Langc1984ed2016-10-07 12:41:00 -0400257template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400258bool ValidateTextureWrapModeValue(Context *context, ParamType *params, bool restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400259{
260 switch (ConvertToGLenum(params[0]))
261 {
262 case GL_CLAMP_TO_EDGE:
263 break;
264
265 case GL_REPEAT:
266 case GL_MIRRORED_REPEAT:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400267 if (restrictedWrapModes)
Geoff Langc1984ed2016-10-07 12:41:00 -0400268 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400269 // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700270 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidWrapModeTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400271 return false;
272 }
273 break;
274
275 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700276 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureWrap);
Geoff Langc1984ed2016-10-07 12:41:00 -0400277 return false;
278 }
279
280 return true;
281}
282
283template <typename ParamType>
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400284bool ValidateTextureMinFilterValue(Context *context, ParamType *params, bool restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400285{
286 switch (ConvertToGLenum(params[0]))
287 {
288 case GL_NEAREST:
289 case GL_LINEAR:
290 break;
291
292 case GL_NEAREST_MIPMAP_NEAREST:
293 case GL_LINEAR_MIPMAP_NEAREST:
294 case GL_NEAREST_MIPMAP_LINEAR:
295 case GL_LINEAR_MIPMAP_LINEAR:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400296 if (restrictedMinFilter)
Geoff Langc1984ed2016-10-07 12:41:00 -0400297 {
298 // OES_EGL_image_external specifies this error.
Brandon Jonesafa75152017-07-21 13:11:29 -0700299 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFilterTexture);
Geoff Langc1984ed2016-10-07 12:41:00 -0400300 return false;
301 }
302 break;
303
304 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700305 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400306 return false;
307 }
308
309 return true;
310}
311
312template <typename ParamType>
313bool ValidateTextureMagFilterValue(Context *context, ParamType *params)
314{
315 switch (ConvertToGLenum(params[0]))
316 {
317 case GL_NEAREST:
318 case GL_LINEAR:
319 break;
320
321 default:
Brandon Jones6cad5662017-06-14 13:25:13 -0700322 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureFilterParam);
Geoff Langc1984ed2016-10-07 12:41:00 -0400323 return false;
324 }
325
326 return true;
327}
328
329template <typename ParamType>
330bool ValidateTextureCompareModeValue(Context *context, ParamType *params)
331{
332 // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
333 switch (ConvertToGLenum(params[0]))
334 {
335 case GL_NONE:
336 case GL_COMPARE_REF_TO_TEXTURE:
337 break;
338
339 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700340 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400341 return false;
342 }
343
344 return true;
345}
346
347template <typename ParamType>
348bool ValidateTextureCompareFuncValue(Context *context, ParamType *params)
349{
350 // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
351 switch (ConvertToGLenum(params[0]))
352 {
353 case GL_LEQUAL:
354 case GL_GEQUAL:
355 case GL_LESS:
356 case GL_GREATER:
357 case GL_EQUAL:
358 case GL_NOTEQUAL:
359 case GL_ALWAYS:
360 case GL_NEVER:
361 break;
362
363 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700364 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Langc1984ed2016-10-07 12:41:00 -0400365 return false;
366 }
367
368 return true;
369}
370
371template <typename ParamType>
Geoff Lang81c6b572016-10-19 14:07:52 -0700372bool ValidateTextureSRGBDecodeValue(Context *context, ParamType *params)
373{
374 if (!context->getExtensions().textureSRGBDecode)
375 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700376 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Geoff Lang81c6b572016-10-19 14:07:52 -0700377 return false;
378 }
379
380 switch (ConvertToGLenum(params[0]))
381 {
382 case GL_DECODE_EXT:
383 case GL_SKIP_DECODE_EXT:
384 break;
385
386 default:
Brandon Jonesafa75152017-07-21 13:11:29 -0700387 ANGLE_VALIDATION_ERR(context, InvalidEnum(), UnknownParameter);
Geoff Lang81c6b572016-10-19 14:07:52 -0700388 return false;
389 }
390
391 return true;
392}
393
Luc Ferron1b1a8642018-01-23 15:12:01 -0500394bool ValidateTextureMaxAnisotropyExtensionEnabled(Context *context)
395{
396 if (!context->getExtensions().textureFilterAnisotropic)
397 {
398 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
399 return false;
400 }
401
402 return true;
403}
404
405bool ValidateTextureMaxAnisotropyValue(Context *context, GLfloat paramValue)
406{
407 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
408 {
409 return false;
410 }
411
412 GLfloat largest = context->getExtensions().maxTextureAnisotropy;
413
414 if (paramValue < 1 || paramValue > largest)
415 {
416 ANGLE_VALIDATION_ERR(context, InvalidValue(), OutsideOfBounds);
417 return false;
418 }
419
420 return true;
421}
422
Geoff Lange0cff192017-05-30 13:04:56 -0400423bool ValidateFragmentShaderColorBufferTypeMatch(ValidationContext *context)
424{
425 const Program *program = context->getGLState().getProgram();
426 const Framebuffer *framebuffer = context->getGLState().getDrawFramebuffer();
427
Brandon Jonesc405ae72017-12-06 14:15:03 -0800428 if (!ComponentTypeMask::Validate(program->getDrawBufferTypeMask().to_ulong(),
429 framebuffer->getDrawBufferTypeMask().to_ulong(),
430 program->getActiveOutputVariables().to_ulong(),
431 framebuffer->getDrawBufferMask().to_ulong()))
Geoff Lange0cff192017-05-30 13:04:56 -0400432 {
Brandon Jones76746f92017-11-22 11:44:41 -0800433 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DrawBufferTypeMismatch);
434 return false;
Geoff Lange0cff192017-05-30 13:04:56 -0400435 }
436
437 return true;
438}
439
Geoff Lang9ab5b822017-05-30 16:19:23 -0400440bool ValidateVertexShaderAttributeTypeMatch(ValidationContext *context)
441{
Jamie Madillcac94a92017-11-10 10:09:32 -0500442 const auto &glState = context->getGLState();
Geoff Lang9ab5b822017-05-30 16:19:23 -0400443 const Program *program = context->getGLState().getProgram();
444 const VertexArray *vao = context->getGLState().getVertexArray();
445
Brandon Jonesc405ae72017-12-06 14:15:03 -0800446 unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
447 unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
448 unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
449
450 vaoAttribEnabledMask |= vaoAttribEnabledMask << MAX_COMPONENT_TYPE_MASK_INDEX;
451 vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
452 vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
453
454 if (!ComponentTypeMask::Validate(program->getAttributesTypeMask().to_ulong(), vaoAttribTypeBits,
455 program->getAttributesMask().to_ulong(), 0xFFFF))
Geoff Lang9ab5b822017-05-30 16:19:23 -0400456 {
Brandon Jonesc405ae72017-12-06 14:15:03 -0800457 ANGLE_VALIDATION_ERR(context, InvalidOperation(), VertexShaderTypeMismatch);
458 return false;
Geoff Lang9ab5b822017-05-30 16:19:23 -0400459 }
Geoff Lang9ab5b822017-05-30 16:19:23 -0400460 return true;
461}
462
Geoff Langf41a7152016-09-19 15:11:17 -0400463} // anonymous namespace
464
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500465bool ValidTextureTarget(const ValidationContext *context, GLenum target)
Jamie Madill35d15012013-10-07 10:46:37 -0400466{
Jamie Madilld7460c72014-01-21 16:38:14 -0500467 switch (target)
Jamie Madill35d15012013-10-07 10:46:37 -0400468 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800469 case GL_TEXTURE_2D:
470 case GL_TEXTURE_CUBE_MAP:
471 return true;
Jamie Madill35d15012013-10-07 10:46:37 -0400472
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400473 case GL_TEXTURE_RECTANGLE_ANGLE:
474 return context->getExtensions().textureRectangle;
475
He Yunchaoced53ae2016-11-29 15:00:51 +0800476 case GL_TEXTURE_3D:
477 case GL_TEXTURE_2D_ARRAY:
478 return (context->getClientMajorVersion() >= 3);
Jamie Madilld7460c72014-01-21 16:38:14 -0500479
He Yunchaoced53ae2016-11-29 15:00:51 +0800480 case GL_TEXTURE_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +0800481 return (context->getClientVersion() >= Version(3, 1));
Geoff Lang3b573612016-10-31 14:08:10 -0400482
He Yunchaoced53ae2016-11-29 15:00:51 +0800483 default:
484 return false;
Jamie Madilld7460c72014-01-21 16:38:14 -0500485 }
Jamie Madill35d15012013-10-07 10:46:37 -0400486}
487
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500488bool ValidTexture2DTarget(const ValidationContext *context, GLenum target)
489{
490 switch (target)
491 {
492 case GL_TEXTURE_2D:
493 case GL_TEXTURE_CUBE_MAP:
494 return true;
495
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400496 case GL_TEXTURE_RECTANGLE_ANGLE:
497 return context->getExtensions().textureRectangle;
498
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500499 default:
500 return false;
501 }
502}
503
504bool ValidTexture3DTarget(const ValidationContext *context, GLenum target)
505{
506 switch (target)
507 {
508 case GL_TEXTURE_3D:
509 case GL_TEXTURE_2D_ARRAY:
Martin Radev1be913c2016-07-11 17:59:16 +0300510 return (context->getClientMajorVersion() >= 3);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500511
512 default:
513 return false;
514 }
515}
516
Ian Ewellbda75592016-04-18 17:25:54 -0400517// Most texture GL calls are not compatible with external textures, so we have a separate validation
518// function for use in the GL calls that do
519bool ValidTextureExternalTarget(const ValidationContext *context, GLenum target)
520{
521 return (target == GL_TEXTURE_EXTERNAL_OES) &&
522 (context->getExtensions().eglImageExternal ||
523 context->getExtensions().eglStreamConsumerExternal);
524}
525
Shannon Woods4dfed832014-03-17 20:03:39 -0400526// This function differs from ValidTextureTarget in that the target must be
527// usable as the destination of a 2D operation-- so a cube face is valid, but
528// GL_TEXTURE_CUBE_MAP is not.
Jamie Madill560a8d82014-05-21 13:06:20 -0400529// Note: duplicate of IsInternalTextureTarget
Jamie Madillc29968b2016-01-20 11:17:23 -0500530bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target)
Shannon Woods4dfed832014-03-17 20:03:39 -0400531{
532 switch (target)
533 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800534 case GL_TEXTURE_2D:
535 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
536 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
537 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
538 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
539 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
540 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
541 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400542 case GL_TEXTURE_RECTANGLE_ANGLE:
543 return context->getExtensions().textureRectangle;
He Yunchaoced53ae2016-11-29 15:00:51 +0800544 default:
545 return false;
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500546 }
547}
548
Jamie Madillbe849e42017-05-02 15:49:00 -0400549bool ValidateDrawElementsInstancedBase(ValidationContext *context,
550 GLenum mode,
551 GLsizei count,
552 GLenum type,
553 const GLvoid *indices,
554 GLsizei primcount)
555{
556 if (primcount < 0)
557 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700558 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400559 return false;
560 }
561
562 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, primcount))
563 {
564 return false;
565 }
566
567 // No-op zero primitive count
568 return (primcount > 0);
569}
570
571bool ValidateDrawArraysInstancedBase(Context *context,
572 GLenum mode,
573 GLint first,
574 GLsizei count,
575 GLsizei primcount)
576{
577 if (primcount < 0)
578 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700579 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativePrimcount);
Jamie Madillbe849e42017-05-02 15:49:00 -0400580 return false;
581 }
582
583 if (!ValidateDrawArraysCommon(context, mode, first, count, primcount))
584 {
585 return false;
586 }
587
588 // No-op if zero primitive count
589 return (primcount > 0);
590}
591
Corentin Wallez0dc97812017-06-22 14:38:44 -0400592bool ValidateDrawInstancedANGLE(ValidationContext *context)
Jamie Madillbe849e42017-05-02 15:49:00 -0400593{
594 // Verify there is at least one active attribute with a divisor of zero
595 const State &state = context->getGLState();
596
597 Program *program = state.getProgram();
598
599 const auto &attribs = state.getVertexArray()->getVertexAttributes();
600 const auto &bindings = state.getVertexArray()->getVertexBindings();
601 for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
602 {
603 const VertexAttribute &attrib = attribs[attributeIndex];
604 const VertexBinding &binding = bindings[attrib.bindingIndex];
Martin Radevdd5f27e2017-06-07 10:17:09 +0300605 if (program->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
Jamie Madillbe849e42017-05-02 15:49:00 -0400606 {
607 return true;
608 }
609 }
610
Brandon Jonesafa75152017-07-21 13:11:29 -0700611 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoZeroDivisor);
Jamie Madillbe849e42017-05-02 15:49:00 -0400612 return false;
613}
614
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500615bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target)
616{
617 switch (target)
618 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800619 case GL_TEXTURE_3D:
620 case GL_TEXTURE_2D_ARRAY:
621 return true;
622 default:
623 return false;
Shannon Woods4dfed832014-03-17 20:03:39 -0400624 }
625}
626
He Yunchao11b038b2016-11-22 21:24:04 +0800627bool ValidTexLevelDestinationTarget(const ValidationContext *context, GLenum target)
628{
629 switch (target)
630 {
631 case GL_TEXTURE_2D:
632 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
633 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
634 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
635 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
636 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
637 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
638 case GL_TEXTURE_3D:
639 case GL_TEXTURE_2D_ARRAY:
640 case GL_TEXTURE_2D_MULTISAMPLE:
641 return true;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400642 case GL_TEXTURE_RECTANGLE_ANGLE:
643 return context->getExtensions().textureRectangle;
He Yunchao11b038b2016-11-22 21:24:04 +0800644 default:
645 return false;
646 }
647}
648
Geoff Lange8afa902017-09-27 15:00:43 -0400649bool ValidFramebufferTarget(const ValidationContext *context, GLenum target)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500650{
He Yunchaoced53ae2016-11-29 15:00:51 +0800651 static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
652 GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
Geoff Langd4475812015-03-18 10:53:05 -0400653 "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500654
655 switch (target)
656 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800657 case GL_FRAMEBUFFER:
658 return true;
Geoff Lange8afa902017-09-27 15:00:43 -0400659
He Yunchaoced53ae2016-11-29 15:00:51 +0800660 case GL_READ_FRAMEBUFFER:
He Yunchaoced53ae2016-11-29 15:00:51 +0800661 case GL_DRAW_FRAMEBUFFER:
Geoff Lange8afa902017-09-27 15:00:43 -0400662 return (context->getExtensions().framebufferBlit ||
663 context->getClientMajorVersion() >= 3);
664
He Yunchaoced53ae2016-11-29 15:00:51 +0800665 default:
666 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -0500667 }
668}
669
Jamie Madillc29968b2016-01-20 11:17:23 -0500670bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level)
Geoff Langce635692013-09-24 13:56:32 -0400671{
Jamie Madillc29968b2016-01-20 11:17:23 -0500672 const auto &caps = context->getCaps();
Geoff Langaae65a42014-05-26 12:43:44 -0400673 size_t maxDimension = 0;
Geoff Langce635692013-09-24 13:56:32 -0400674 switch (target)
675 {
Jamie Madillc29968b2016-01-20 11:17:23 -0500676 case GL_TEXTURE_2D:
677 maxDimension = caps.max2DTextureSize;
678 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800679 case GL_TEXTURE_CUBE_MAP:
680 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
681 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
682 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
683 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
684 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
685 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
686 maxDimension = caps.maxCubeMapTextureSize;
687 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400688 case GL_TEXTURE_RECTANGLE_ANGLE:
689 return level == 0;
He Yunchaoced53ae2016-11-29 15:00:51 +0800690 case GL_TEXTURE_3D:
691 maxDimension = caps.max3DTextureSize;
692 break;
693 case GL_TEXTURE_2D_ARRAY:
694 maxDimension = caps.max2DTextureSize;
695 break;
He Yunchao11b038b2016-11-22 21:24:04 +0800696 case GL_TEXTURE_2D_MULTISAMPLE:
697 maxDimension = caps.max2DTextureSize;
698 break;
He Yunchaoced53ae2016-11-29 15:00:51 +0800699 default:
700 UNREACHABLE();
Geoff Langce635692013-09-24 13:56:32 -0400701 }
702
Brandon Jones6cad5662017-06-14 13:25:13 -0700703 return level <= gl::log2(static_cast<int>(maxDimension)) && level >= 0;
Geoff Langce635692013-09-24 13:56:32 -0400704}
705
Brandon Jones6cad5662017-06-14 13:25:13 -0700706bool ValidImageSizeParameters(ValidationContext *context,
Austin Kinross08528e12015-10-07 16:24:40 -0700707 GLenum target,
708 GLint level,
709 GLsizei width,
710 GLsizei height,
711 GLsizei depth,
712 bool isSubImage)
Geoff Langce635692013-09-24 13:56:32 -0400713{
Brandon Jones6cad5662017-06-14 13:25:13 -0700714 if (width < 0 || height < 0 || depth < 0)
Geoff Langce635692013-09-24 13:56:32 -0400715 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700716 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langce635692013-09-24 13:56:32 -0400717 return false;
718 }
Austin Kinross08528e12015-10-07 16:24:40 -0700719 // TexSubImage parameters can be NPOT without textureNPOT extension,
720 // as long as the destination texture is POT.
Geoff Langcc507aa2016-12-12 10:09:52 -0500721 bool hasNPOTSupport =
Geoff Lang5f319a42017-01-09 16:49:19 -0500722 context->getExtensions().textureNPOT || context->getClientVersion() >= Version(3, 0);
Geoff Langcc507aa2016-12-12 10:09:52 -0500723 if (!isSubImage && !hasNPOTSupport &&
Jamie Madill4fd75c12014-06-23 10:53:54 -0400724 (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth))))
Geoff Langce635692013-09-24 13:56:32 -0400725 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700726 ANGLE_VALIDATION_ERR(context, InvalidValue(), TextureNotPow2);
Geoff Langce635692013-09-24 13:56:32 -0400727 return false;
728 }
729
730 if (!ValidMipLevel(context, target, level))
731 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700732 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langce635692013-09-24 13:56:32 -0400733 return false;
734 }
735
736 return true;
737}
738
Geoff Lang0d8b7242015-09-09 14:56:53 -0400739bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
740{
741 // List of compressed format that require that the texture size is smaller than or a multiple of
742 // the compressed block size.
743 switch (internalFormat)
744 {
745 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
746 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
747 case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
748 case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
Geoff Langfff7a7d2017-06-02 10:39:17 -0400749 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
750 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
751 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
752 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
Minmin Gonge3939b92015-12-01 15:36:51 -0800753 case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
Minmin Gong390208b2017-02-28 18:03:06 -0800754 case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
755 case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
756 case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
757 case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
758 case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
759 case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
Geoff Lang0d8b7242015-09-09 14:56:53 -0400760 return true;
761
762 default:
763 return false;
764 }
765}
766
Geoff Lang966c9402017-04-18 12:38:27 -0400767bool ValidCompressedDimension(GLsizei size, GLuint blockSize, bool smallerThanBlockSizeAllowed)
768{
769 return (smallerThanBlockSizeAllowed && (size > 0) && (blockSize % size == 0)) ||
770 (size % blockSize == 0);
771}
772
Jamie Madillc29968b2016-01-20 11:17:23 -0500773bool ValidCompressedImageSize(const ValidationContext *context,
774 GLenum internalFormat,
Geoff Lang966c9402017-04-18 12:38:27 -0400775 GLint level,
Jamie Madillc29968b2016-01-20 11:17:23 -0500776 GLsizei width,
777 GLsizei height)
Geoff Langd4f180b2013-09-24 13:57:44 -0400778{
Geoff Langca271392017-04-05 12:30:00 -0400779 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400780 if (!formatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400781 {
782 return false;
783 }
784
Geoff Lang966c9402017-04-18 12:38:27 -0400785 if (width < 0 || height < 0)
786 {
787 return false;
788 }
789
790 if (CompressedTextureFormatRequiresExactSize(internalFormat))
791 {
792 // The ANGLE extensions allow specifying compressed textures with sizes smaller than the
793 // block size for level 0 but WebGL disallows this.
794 bool smallerThanBlockSizeAllowed =
795 level > 0 || !context->getExtensions().webglCompatibility;
796
797 if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth,
798 smallerThanBlockSizeAllowed) ||
799 !ValidCompressedDimension(height, formatInfo.compressedBlockHeight,
800 smallerThanBlockSizeAllowed))
801 {
802 return false;
803 }
804 }
805
806 return true;
807}
808
809bool ValidCompressedSubImageSize(const ValidationContext *context,
810 GLenum internalFormat,
811 GLint xoffset,
812 GLint yoffset,
813 GLsizei width,
814 GLsizei height,
815 size_t textureWidth,
816 size_t textureHeight)
817{
818 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
819 if (!formatInfo.compressed)
820 {
821 return false;
822 }
823
Geoff Lang44ff5a72017-02-03 15:15:43 -0500824 if (xoffset < 0 || yoffset < 0 || width < 0 || height < 0)
Geoff Langd4f180b2013-09-24 13:57:44 -0400825 {
826 return false;
827 }
828
Geoff Lang0d8b7242015-09-09 14:56:53 -0400829 if (CompressedTextureFormatRequiresExactSize(internalFormat))
830 {
Geoff Lang44ff5a72017-02-03 15:15:43 -0500831 if (xoffset % formatInfo.compressedBlockWidth != 0 ||
Geoff Lang966c9402017-04-18 12:38:27 -0400832 yoffset % formatInfo.compressedBlockHeight != 0)
833 {
834 return false;
835 }
836
837 // Allowed to either have data that is a multiple of block size or is smaller than the block
838 // size but fills the entire mip
839 bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
840 static_cast<size_t>(width) == textureWidth &&
841 static_cast<size_t>(height) == textureHeight;
842 bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
843 (height % formatInfo.compressedBlockHeight) == 0;
844 if (!sizeMultipleOfBlockSize && !fillsEntireMip)
Geoff Lang0d8b7242015-09-09 14:56:53 -0400845 {
846 return false;
847 }
848 }
849
Geoff Langd4f180b2013-09-24 13:57:44 -0400850 return true;
851}
852
Geoff Langff5b2d52016-09-07 11:32:23 -0400853bool ValidImageDataSize(ValidationContext *context,
854 GLenum textureTarget,
855 GLsizei width,
856 GLsizei height,
857 GLsizei depth,
Geoff Langdbcced82017-06-06 15:55:54 -0400858 GLenum format,
Geoff Langff5b2d52016-09-07 11:32:23 -0400859 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400860 const void *pixels,
Geoff Langff5b2d52016-09-07 11:32:23 -0400861 GLsizei imageSize)
862{
Corentin Wallez336129f2017-10-17 15:55:40 -0400863 gl::Buffer *pixelUnpackBuffer =
864 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Langff5b2d52016-09-07 11:32:23 -0400865 if (pixelUnpackBuffer == nullptr && imageSize < 0)
866 {
867 // Checks are not required
868 return true;
869 }
870
871 // ...the data would be unpacked from the buffer object such that the memory reads required
872 // would exceed the data store size.
Geoff Langdbcced82017-06-06 15:55:54 -0400873 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
874 ASSERT(formatInfo.internalFormat != GL_NONE);
Geoff Langff5b2d52016-09-07 11:32:23 -0400875 const gl::Extents size(width, height, depth);
876 const auto &unpack = context->getGLState().getUnpackState();
877
878 bool targetIs3D = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
879 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
880 if (endByteOrErr.isError())
881 {
882 context->handleError(endByteOrErr.getError());
883 return false;
884 }
885
886 GLuint endByte = endByteOrErr.getResult();
887
888 if (pixelUnpackBuffer)
889 {
890 CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
891 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
892 checkedEndByte += checkedOffset;
893
894 if (!checkedEndByte.IsValid() ||
895 (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
896 {
897 // Overflow past the end of the buffer
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500898 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -0400899 return false;
900 }
901 }
902 else
903 {
904 ASSERT(imageSize >= 0);
905 if (pixels == nullptr && imageSize != 0)
906 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500907 context->handleError(InvalidOperation()
908 << "imageSize must be 0 if no texture data is provided.");
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400909 return false;
Geoff Langff5b2d52016-09-07 11:32:23 -0400910 }
911
Geoff Lang3feb3ff2016-10-26 10:57:45 -0400912 if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400913 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500914 context->handleError(InvalidOperation() << "imageSize must be at least " << endByte);
Geoff Langff5b2d52016-09-07 11:32:23 -0400915 return false;
916 }
917 }
918
919 return true;
920}
921
Geoff Lang37dde692014-01-31 16:34:54 -0500922bool ValidQueryType(const Context *context, GLenum queryType)
923{
He Yunchaoced53ae2016-11-29 15:00:51 +0800924 static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT,
925 "GL extension enums not equal.");
926 static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
927 "GL extension enums not equal.");
Geoff Lang37dde692014-01-31 16:34:54 -0500928
929 switch (queryType)
930 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800931 case GL_ANY_SAMPLES_PASSED:
932 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE:
Geoff Lang8c5b31c2017-09-26 18:07:44 -0400933 return context->getClientMajorVersion() >= 3 ||
934 context->getExtensions().occlusionQueryBoolean;
He Yunchaoced53ae2016-11-29 15:00:51 +0800935 case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
936 return (context->getClientMajorVersion() >= 3);
937 case GL_TIME_ELAPSED_EXT:
938 return context->getExtensions().disjointTimerQuery;
939 case GL_COMMANDS_COMPLETED_CHROMIUM:
940 return context->getExtensions().syncQuery;
941 default:
942 return false;
Geoff Lang37dde692014-01-31 16:34:54 -0500943 }
944}
945
Geoff Lang2d62ab72017-03-23 16:54:40 -0400946bool ValidateWebGLVertexAttribPointer(ValidationContext *context,
947 GLenum type,
948 GLboolean normalized,
949 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -0400950 const void *ptr,
Geoff Lang2d62ab72017-03-23 16:54:40 -0400951 bool pureInteger)
952{
953 ASSERT(context->getExtensions().webglCompatibility);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400954 // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
955 // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
956 // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
957 // parameter exceeds 255.
958 constexpr GLsizei kMaxWebGLStride = 255;
959 if (stride > kMaxWebGLStride)
960 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500961 context->handleError(InvalidValue()
962 << "Stride is over the maximum stride allowed by WebGL.");
Geoff Lang2d62ab72017-03-23 16:54:40 -0400963 return false;
964 }
965
966 // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
967 // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
968 // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
969 // or an INVALID_OPERATION error is generated.
970 VertexFormatType internalType = GetVertexFormatType(type, normalized, 1, pureInteger);
971 size_t typeSize = GetVertexFormatTypeSize(internalType);
972
973 ASSERT(isPow2(typeSize) && typeSize > 0);
974 size_t sizeMask = (typeSize - 1);
975 if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
976 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700977 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400978 return false;
979 }
980
981 if ((stride & sizeMask) != 0)
982 {
Brandon Jones6cad5662017-06-14 13:25:13 -0700983 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StrideMustBeMultipleOfType);
Geoff Lang2d62ab72017-03-23 16:54:40 -0400984 return false;
985 }
986
987 return true;
988}
989
Jamie Madillef300b12016-10-07 15:12:09 -0400990Program *GetValidProgram(ValidationContext *context, GLuint id)
Geoff Lang48dcae72014-02-05 16:28:24 -0500991{
He Yunchaoced53ae2016-11-29 15:00:51 +0800992 // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
993 // generate the error INVALID_VALUE if the provided name is not the name of either a shader
994 // or program object and INVALID_OPERATION if the provided name identifies an object
995 // that is not the expected type."
Geoff Lang48dcae72014-02-05 16:28:24 -0500996
Dian Xiang769769a2015-09-09 15:20:08 -0700997 Program *validProgram = context->getProgram(id);
998
999 if (!validProgram)
Geoff Lang48dcae72014-02-05 16:28:24 -05001000 {
Dian Xiang769769a2015-09-09 15:20:08 -07001001 if (context->getShader(id))
1002 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001003 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001004 }
1005 else
1006 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001007 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
Dian Xiang769769a2015-09-09 15:20:08 -07001008 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001009 }
Dian Xiang769769a2015-09-09 15:20:08 -07001010
1011 return validProgram;
1012}
1013
Jamie Madillef300b12016-10-07 15:12:09 -04001014Shader *GetValidShader(ValidationContext *context, GLuint id)
Dian Xiang769769a2015-09-09 15:20:08 -07001015{
1016 // See ValidProgram for spec details.
1017
1018 Shader *validShader = context->getShader(id);
1019
1020 if (!validShader)
Geoff Lang48dcae72014-02-05 16:28:24 -05001021 {
Dian Xiang769769a2015-09-09 15:20:08 -07001022 if (context->getProgram(id))
1023 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001024 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001025 }
1026 else
1027 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001028 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidShaderName);
Dian Xiang769769a2015-09-09 15:20:08 -07001029 }
Geoff Lang48dcae72014-02-05 16:28:24 -05001030 }
Dian Xiang769769a2015-09-09 15:20:08 -07001031
1032 return validShader;
Geoff Lang48dcae72014-02-05 16:28:24 -05001033}
1034
Geoff Langb1196682014-07-23 13:47:29 -04001035bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
Jamie Madillb4472272014-07-03 10:38:55 -04001036{
Geoff Langfa125c92017-10-24 13:01:46 -04001037 if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
Jamie Madillb4472272014-07-03 10:38:55 -04001038 {
Geoff Langfa125c92017-10-24 13:01:46 -04001039 if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffers)
1040 {
1041 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
1042 return false;
1043 }
Jamie Madillb4472272014-07-03 10:38:55 -04001044
Geoff Langfa125c92017-10-24 13:01:46 -04001045 // Color attachment 0 is validated below because it is always valid
1046 const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
Geoff Langaae65a42014-05-26 12:43:44 -04001047 if (colorAttachment >= context->getCaps().maxColorAttachments)
Jamie Madillb4472272014-07-03 10:38:55 -04001048 {
Geoff Langfa125c92017-10-24 13:01:46 -04001049 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langb1196682014-07-23 13:47:29 -04001050 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001051 }
1052 }
1053 else
1054 {
1055 switch (attachment)
1056 {
Geoff Langfa125c92017-10-24 13:01:46 -04001057 case GL_COLOR_ATTACHMENT0:
He Yunchaoced53ae2016-11-29 15:00:51 +08001058 case GL_DEPTH_ATTACHMENT:
1059 case GL_STENCIL_ATTACHMENT:
1060 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001061
He Yunchaoced53ae2016-11-29 15:00:51 +08001062 case GL_DEPTH_STENCIL_ATTACHMENT:
1063 if (!context->getExtensions().webglCompatibility &&
1064 context->getClientMajorVersion() < 3)
1065 {
Geoff Langfa125c92017-10-24 13:01:46 -04001066 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001067 return false;
1068 }
1069 break;
Jamie Madillb4472272014-07-03 10:38:55 -04001070
He Yunchaoced53ae2016-11-29 15:00:51 +08001071 default:
Geoff Langfa125c92017-10-24 13:01:46 -04001072 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08001073 return false;
Jamie Madillb4472272014-07-03 10:38:55 -04001074 }
1075 }
1076
1077 return true;
1078}
1079
Jamie Madille8fb6402017-02-14 17:56:40 -05001080bool ValidateRenderbufferStorageParametersBase(ValidationContext *context,
He Yunchaoced53ae2016-11-29 15:00:51 +08001081 GLenum target,
1082 GLsizei samples,
1083 GLenum internalformat,
1084 GLsizei width,
1085 GLsizei height)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001086{
1087 switch (target)
1088 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001089 case GL_RENDERBUFFER:
1090 break;
1091 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001092 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001093 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001094 }
1095
1096 if (width < 0 || height < 0 || samples < 0)
1097 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001098 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRenderbufferWidthHeight);
Geoff Langb1196682014-07-23 13:47:29 -04001099 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001100 }
1101
Jamie Madill4e0e6f82017-02-17 11:06:03 -05001102 // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
1103 GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
1104
1105 const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
Geoff Langd87878e2014-09-19 15:42:59 -04001106 if (!formatCaps.renderable)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001107 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001108 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001109 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001110 }
1111
1112 // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
1113 // 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 -08001114 // only sized internal formats.
Geoff Langca271392017-04-05 12:30:00 -04001115 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(convertedInternalFormat);
1116 if (formatInfo.internalFormat == GL_NONE)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001117 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001118 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -04001119 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001120 }
1121
Geoff Langaae65a42014-05-26 12:43:44 -04001122 if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001123 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001124 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001125 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001126 }
1127
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001128 GLuint handle = context->getGLState().getRenderbufferId();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001129 if (handle == 0)
1130 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001131 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001132 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001133 }
1134
1135 return true;
1136}
1137
He Yunchaoced53ae2016-11-29 15:00:51 +08001138bool ValidateFramebufferRenderbufferParameters(gl::Context *context,
1139 GLenum target,
1140 GLenum attachment,
1141 GLenum renderbuffertarget,
1142 GLuint renderbuffer)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001143{
Geoff Lange8afa902017-09-27 15:00:43 -04001144 if (!ValidFramebufferTarget(context, target))
Shannon Woods1da3cf62014-06-27 15:32:23 -04001145 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001146 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001147 return false;
Shannon Woods1da3cf62014-06-27 15:32:23 -04001148 }
1149
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001150 gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001151
Jamie Madill84115c92015-04-23 15:00:07 -04001152 ASSERT(framebuffer);
1153 if (framebuffer->id() == 0)
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001154 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001155 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001156 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001157 }
1158
Jamie Madillb4472272014-07-03 10:38:55 -04001159 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001160 {
Jamie Madillb4472272014-07-03 10:38:55 -04001161 return false;
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001162 }
1163
Jamie Madillab9d82c2014-01-21 16:38:14 -05001164 // [OpenGL ES 2.0.25] Section 4.4.3 page 112
1165 // [OpenGL ES 3.0.2] Section 4.4.2 page 201
1166 // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
1167 // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
1168 if (renderbuffer != 0)
1169 {
1170 if (!context->getRenderbuffer(renderbuffer))
1171 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001172 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidRenderbufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04001173 return false;
Jamie Madillab9d82c2014-01-21 16:38:14 -05001174 }
1175 }
1176
Jamie Madill1fc7e2c2014-01-21 16:47:10 -05001177 return true;
1178}
1179
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001180bool ValidateBlitFramebufferParameters(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001181 GLint srcX0,
1182 GLint srcY0,
1183 GLint srcX1,
1184 GLint srcY1,
1185 GLint dstX0,
1186 GLint dstY0,
1187 GLint dstX1,
1188 GLint dstY1,
1189 GLbitfield mask,
1190 GLenum filter)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001191{
1192 switch (filter)
1193 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001194 case GL_NEAREST:
1195 break;
1196 case GL_LINEAR:
1197 break;
1198 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001199 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08001200 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001201 }
1202
1203 if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
1204 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001205 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001206 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001207 }
1208
1209 if (mask == 0)
1210 {
1211 // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
1212 // buffers are copied.
1213 return false;
1214 }
1215
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001216 // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
1217 // color buffer, leaving only nearest being unfiltered from above
1218 if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
1219 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001220 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001221 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001222 }
1223
Jamie Madill51f40ec2016-06-15 14:06:00 -04001224 const auto &glState = context->getGLState();
1225 gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
1226 gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
Jamie Madill48faf802014-11-06 15:27:22 -05001227
1228 if (!readFramebuffer || !drawFramebuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001229 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001230 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001231 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001232 }
1233
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001234 if (readFramebuffer->id() == drawFramebuffer->id())
1235 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001236 context->handleError(InvalidOperation());
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001237 return false;
1238 }
1239
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001240 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001241 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001242 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001243 return false;
1244 }
1245
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001246 if (drawFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill48faf802014-11-06 15:27:22 -05001247 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001248 context->handleError(InvalidFramebufferOperation());
Jamie Madill48faf802014-11-06 15:27:22 -05001249 return false;
1250 }
1251
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001252 if (drawFramebuffer->getSamples(context) != 0)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001253 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001254 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001255 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001256 }
1257
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001258 bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
1259
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001260 if (mask & GL_COLOR_BUFFER_BIT)
1261 {
Jamie Madillb6bda4a2015-04-20 12:53:26 -04001262 const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer();
Jamie Madill6163c752015-12-07 16:32:59 -05001263 const Extensions &extensions = context->getExtensions();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001264
He Yunchao66a41a22016-12-15 16:45:05 +08001265 if (readColorBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001266 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001267 const Format &readFormat = readColorBuffer->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001268
Geoff Langa15472a2015-08-11 11:48:03 -04001269 for (size_t drawbufferIdx = 0;
1270 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001271 {
Geoff Langa15472a2015-08-11 11:48:03 -04001272 const FramebufferAttachment *attachment =
1273 drawFramebuffer->getDrawBuffer(drawbufferIdx);
1274 if (attachment)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001275 {
Jamie Madilla3944d42016-07-22 22:13:26 -04001276 const Format &drawFormat = attachment->getFormat();
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001277
Geoff Langb2f3d052013-08-13 12:49:27 -04001278 // The GL ES 3.0.2 spec (pg 193) states that:
1279 // 1) If the read buffer is fixed point format, the draw buffer must be as well
He Yunchaoced53ae2016-11-29 15:00:51 +08001280 // 2) If the read buffer is an unsigned integer format, the draw buffer must be
1281 // as well
1282 // 3) If the read buffer is a signed integer format, the draw buffer must be as
1283 // well
Jamie Madill6163c752015-12-07 16:32:59 -05001284 // Changes with EXT_color_buffer_float:
1285 // Case 1) is changed to fixed point OR floating point
Jamie Madilla3944d42016-07-22 22:13:26 -04001286 GLenum readComponentType = readFormat.info->componentType;
1287 GLenum drawComponentType = drawFormat.info->componentType;
He Yunchaoced53ae2016-11-29 15:00:51 +08001288 bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
Jamie Madill6163c752015-12-07 16:32:59 -05001289 readComponentType == GL_SIGNED_NORMALIZED);
1290 bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
1291 drawComponentType == GL_SIGNED_NORMALIZED);
1292
1293 if (extensions.colorBufferFloat)
1294 {
1295 bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
1296 bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
1297
1298 if (readFixedOrFloat != drawFixedOrFloat)
1299 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001300 context->handleError(InvalidOperation()
1301 << "If the read buffer contains fixed-point or "
1302 "floating-point values, the draw buffer must "
1303 "as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001304 return false;
1305 }
1306 }
1307 else if (readFixedPoint != drawFixedPoint)
1308 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001309 context->handleError(InvalidOperation()
1310 << "If the read buffer contains fixed-point values, "
1311 "the draw buffer must as well.");
Jamie Madill6163c752015-12-07 16:32:59 -05001312 return false;
1313 }
1314
1315 if (readComponentType == GL_UNSIGNED_INT &&
1316 drawComponentType != GL_UNSIGNED_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001318 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001319 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001320 }
1321
Jamie Madill6163c752015-12-07 16:32:59 -05001322 if (readComponentType == GL_INT && drawComponentType != GL_INT)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001323 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001324 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001325 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001326 }
1327
Jamie Madilla3944d42016-07-22 22:13:26 -04001328 if (readColorBuffer->getSamples() > 0 &&
Kenneth Russell69382852017-07-21 16:38:44 -04001329 (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001330 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001331 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001332 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001333 }
Geoff Lange4915782017-04-12 15:19:07 -04001334
1335 if (context->getExtensions().webglCompatibility &&
1336 *readColorBuffer == *attachment)
1337 {
1338 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001339 InvalidOperation()
1340 << "Read and write color attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001341 return false;
1342 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001343 }
1344 }
1345
Jamie Madilla3944d42016-07-22 22:13:26 -04001346 if ((readFormat.info->componentType == GL_INT ||
1347 readFormat.info->componentType == GL_UNSIGNED_INT) &&
1348 filter == GL_LINEAR)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001349 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001350 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001351 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001352 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001353 }
He Yunchao66a41a22016-12-15 16:45:05 +08001354 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1355 // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
1356 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
1357 // situation is an application error that would lead to a crash in ANGLE.
1358 else if (drawFramebuffer->hasEnabledDrawBuffer())
1359 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001360 context->handleError(
1361 InvalidOperation()
1362 << "Attempt to read from a missing color attachment of a complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001363 return false;
1364 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001365 }
1366
He Yunchaoced53ae2016-11-29 15:00:51 +08001367 GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001368 GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
1369 for (size_t i = 0; i < 2; i++)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001370 {
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001371 if (mask & masks[i])
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001372 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001373 const gl::FramebufferAttachment *readBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001374 readFramebuffer->getAttachment(context, attachments[i]);
He Yunchaoced53ae2016-11-29 15:00:51 +08001375 const gl::FramebufferAttachment *drawBuffer =
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08001376 drawFramebuffer->getAttachment(context, attachments[i]);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001377
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001378 if (readBuffer && drawBuffer)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001379 {
Kenneth Russell69382852017-07-21 16:38:44 -04001380 if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001381 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001382 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001383 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001384 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001385
Dongseong Hwang44b422c2014-12-09 15:42:01 +02001386 if (readBuffer->getSamples() > 0 && !sameBounds)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001387 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001388 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001389 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001390 }
Geoff Lange4915782017-04-12 15:19:07 -04001391
1392 if (context->getExtensions().webglCompatibility && *readBuffer == *drawBuffer)
1393 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001394 context->handleError(
1395 InvalidOperation()
1396 << "Read and write depth stencil attachments cannot be the same image.");
Geoff Lange4915782017-04-12 15:19:07 -04001397 return false;
1398 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001399 }
He Yunchao66a41a22016-12-15 16:45:05 +08001400 // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
1401 else if (drawBuffer)
1402 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001403 context->handleError(InvalidOperation() << "Attempt to read from a missing "
1404 "depth/stencil attachment of a "
1405 "complete framebuffer.");
He Yunchao66a41a22016-12-15 16:45:05 +08001406 return false;
1407 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001408 }
1409 }
1410
Martin Radeva3ed4572017-07-27 18:29:37 +03001411 // ANGLE_multiview, Revision 1:
1412 // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
1413 // multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
1414 if (readFramebuffer->getMultiviewLayout() != GL_NONE)
1415 {
1416 context->handleError(InvalidFramebufferOperation()
1417 << "Attempt to read from a multi-view framebuffer.");
1418 return false;
1419 }
1420 if (drawFramebuffer->getMultiviewLayout() != GL_NONE)
1421 {
1422 context->handleError(InvalidFramebufferOperation()
1423 << "Attempt to write to a multi-view framebuffer.");
1424 return false;
1425 }
1426
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001427 return true;
1428}
1429
Jamie Madill4928b7c2017-06-20 12:57:39 -04001430bool ValidateReadPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001431 GLint x,
1432 GLint y,
1433 GLsizei width,
1434 GLsizei height,
1435 GLenum format,
1436 GLenum type,
1437 GLsizei bufSize,
1438 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001439 GLsizei *columns,
1440 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001441 void *pixels)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001442{
1443 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madillc29968b2016-01-20 11:17:23 -05001444 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001445 return false;
1446 }
1447
Geoff Lang62fce5b2016-09-30 10:46:35 -04001448 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
Geoff Lange93daba2017-03-30 13:54:40 -04001449 columns, rows, pixels))
Jamie Madill26e91952014-03-05 15:01:27 -05001450 {
Geoff Langb1196682014-07-23 13:47:29 -04001451 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001452 }
1453
Geoff Lang62fce5b2016-09-30 10:46:35 -04001454 if (!ValidateRobustBufferSize(context, bufSize, *length))
Jamie Madill26e91952014-03-05 15:01:27 -05001455 {
Geoff Langb1196682014-07-23 13:47:29 -04001456 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001457 }
1458
Jamie Madillc29968b2016-01-20 11:17:23 -05001459 return true;
1460}
1461
1462bool ValidateReadnPixelsEXT(Context *context,
1463 GLint x,
1464 GLint y,
1465 GLsizei width,
1466 GLsizei height,
1467 GLenum format,
1468 GLenum type,
1469 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001470 void *pixels)
Jamie Madillc29968b2016-01-20 11:17:23 -05001471{
1472 if (bufSize < 0)
1473 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001474 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Jamie Madillc29968b2016-01-20 11:17:23 -05001475 return false;
1476 }
1477
Geoff Lang62fce5b2016-09-30 10:46:35 -04001478 return ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, nullptr,
Geoff Lange93daba2017-03-30 13:54:40 -04001479 nullptr, nullptr, pixels);
Geoff Lang62fce5b2016-09-30 10:46:35 -04001480}
Jamie Madill26e91952014-03-05 15:01:27 -05001481
Jamie Madill4928b7c2017-06-20 12:57:39 -04001482bool ValidateReadnPixelsRobustANGLE(Context *context,
Geoff Lang62fce5b2016-09-30 10:46:35 -04001483 GLint x,
1484 GLint y,
1485 GLsizei width,
1486 GLsizei height,
1487 GLenum format,
1488 GLenum type,
1489 GLsizei bufSize,
1490 GLsizei *length,
Geoff Lange93daba2017-03-30 13:54:40 -04001491 GLsizei *columns,
1492 GLsizei *rows,
Jamie Madill876429b2017-04-20 15:46:24 -04001493 void *data)
Geoff Lang62fce5b2016-09-30 10:46:35 -04001494{
1495 if (!ValidateRobustEntryPoint(context, bufSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001496 {
Jamie Madille2e406c2016-06-02 13:04:10 -04001497 return false;
1498 }
1499
Geoff Lange93daba2017-03-30 13:54:40 -04001500 if (!ValidateReadPixelsBase(context, x, y, width, height, format, type, bufSize, length,
1501 columns, rows, data))
Jamie Madille2e406c2016-06-02 13:04:10 -04001502 {
Jamie Madillc29968b2016-01-20 11:17:23 -05001503 return false;
Jamie Madill26e91952014-03-05 15:01:27 -05001504 }
1505
Geoff Lang62fce5b2016-09-30 10:46:35 -04001506 if (!ValidateRobustBufferSize(context, bufSize, *length))
1507 {
1508 return false;
1509 }
1510
1511 return true;
Jamie Madill26e91952014-03-05 15:01:27 -05001512}
1513
Jamie Madillf0e04492017-08-26 15:28:42 -04001514bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001515{
1516 if (!context->getExtensions().occlusionQueryBoolean &&
1517 !context->getExtensions().disjointTimerQuery)
1518 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001519 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001520 return false;
1521 }
1522
Olli Etuaho41997e72016-03-10 13:38:39 +02001523 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001524}
1525
Jamie Madillf0e04492017-08-26 15:28:42 -04001526bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001527{
1528 if (!context->getExtensions().occlusionQueryBoolean &&
1529 !context->getExtensions().disjointTimerQuery)
1530 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001531 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001532 return false;
1533 }
1534
Olli Etuaho41997e72016-03-10 13:38:39 +02001535 return ValidateGenOrDelete(context, n);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001536}
1537
Jamie Madillf0e04492017-08-26 15:28:42 -04001538bool ValidateIsQueryEXT(gl::Context *context, GLuint id)
1539{
1540 if (!context->getExtensions().occlusionQueryBoolean &&
1541 !context->getExtensions().disjointTimerQuery)
1542 {
1543 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
1544 return false;
1545 }
1546
1547 return true;
1548}
1549
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001550bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id)
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001551{
1552 if (!ValidQueryType(context, target))
1553 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001554 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001555 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001556 }
1557
1558 if (id == 0)
1559 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001560 context->handleError(InvalidOperation() << "Query id is 0");
Geoff Langb1196682014-07-23 13:47:29 -04001561 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001562 }
1563
1564 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
1565 // of zero, if the active query object name for <target> is non-zero (for the
1566 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
1567 // the active query for either target is non-zero), if <id> is the name of an
1568 // existing query object whose type does not match <target>, or if <id> is the
1569 // active query object name for any query type, the error INVALID_OPERATION is
1570 // generated.
1571
1572 // Ensure no other queries are active
1573 // NOTE: If other queries than occlusion are supported, we will need to check
1574 // separately that:
1575 // a) The query ID passed is not the current active query for any target/type
1576 // b) There are no active queries for the requested target (and in the case
1577 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1578 // no query may be active for either if glBeginQuery targets either.
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001579
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001580 if (context->getGLState().isQueryActive(target))
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001581 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001582 context->handleError(InvalidOperation() << "Other query is active");
Geoff Langb1196682014-07-23 13:47:29 -04001583 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001584 }
1585
1586 Query *queryObject = context->getQuery(id, true, target);
1587
1588 // check that name was obtained with glGenQueries
1589 if (!queryObject)
1590 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001591 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Geoff Langb1196682014-07-23 13:47:29 -04001592 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001593 }
1594
1595 // check for type mismatch
1596 if (queryObject->getType() != target)
1597 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001598 context->handleError(InvalidOperation() << "Query type does not match target");
Geoff Langb1196682014-07-23 13:47:29 -04001599 return false;
Jamie Madilldb2f14c2014-05-13 13:56:30 -04001600 }
1601
1602 return true;
1603}
1604
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001605bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id)
1606{
1607 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001608 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001609 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001610 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001611 return false;
1612 }
1613
1614 return ValidateBeginQueryBase(context, target, id);
1615}
1616
1617bool ValidateEndQueryBase(gl::Context *context, GLenum target)
Jamie Madill45c785d2014-05-13 14:09:34 -04001618{
1619 if (!ValidQueryType(context, target))
1620 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001621 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Geoff Langb1196682014-07-23 13:47:29 -04001622 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001623 }
1624
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001625 const Query *queryObject = context->getGLState().getActiveQuery(target);
Jamie Madill45c785d2014-05-13 14:09:34 -04001626
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001627 if (queryObject == nullptr)
Jamie Madill45c785d2014-05-13 14:09:34 -04001628 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001629 context->handleError(InvalidOperation() << "Query target not active");
Geoff Langb1196682014-07-23 13:47:29 -04001630 return false;
Jamie Madill45c785d2014-05-13 14:09:34 -04001631 }
1632
Jamie Madill45c785d2014-05-13 14:09:34 -04001633 return true;
1634}
1635
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001636bool ValidateEndQueryEXT(gl::Context *context, GLenum target)
1637{
1638 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001639 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001640 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001641 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001642 return false;
1643 }
1644
1645 return ValidateEndQueryBase(context, target);
1646}
1647
1648bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target)
1649{
1650 if (!context->getExtensions().disjointTimerQuery)
1651 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001652 context->handleError(InvalidOperation() << "Disjoint timer query not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001653 return false;
1654 }
1655
1656 if (target != GL_TIMESTAMP_EXT)
1657 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001658 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryTarget);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001659 return false;
1660 }
1661
1662 Query *queryObject = context->getQuery(id, true, target);
1663 if (queryObject == nullptr)
1664 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001665 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001666 return false;
1667 }
1668
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001669 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001670 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001671 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001672 return false;
1673 }
1674
1675 return true;
1676}
1677
Geoff Lang2186c382016-10-14 10:54:54 -04001678bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname, GLsizei *numParams)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001679{
Geoff Lang2186c382016-10-14 10:54:54 -04001680 if (numParams)
1681 {
1682 *numParams = 0;
1683 }
1684
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001685 if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT)
1686 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001687 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidQueryType);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001688 return false;
1689 }
1690
1691 switch (pname)
1692 {
1693 case GL_CURRENT_QUERY_EXT:
1694 if (target == GL_TIMESTAMP_EXT)
1695 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001696 context->handleError(InvalidEnum() << "Cannot use current query for timestamp");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001697 return false;
1698 }
1699 break;
1700 case GL_QUERY_COUNTER_BITS_EXT:
1701 if (!context->getExtensions().disjointTimerQuery ||
1702 (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT))
1703 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001704 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001705 return false;
1706 }
1707 break;
1708 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001709 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001710 return false;
1711 }
1712
Geoff Lang2186c382016-10-14 10:54:54 -04001713 if (numParams)
1714 {
1715 // All queries return only one value
1716 *numParams = 1;
1717 }
1718
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001719 return true;
1720}
1721
1722bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params)
1723{
1724 if (!context->getExtensions().occlusionQueryBoolean &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001725 !context->getExtensions().disjointTimerQuery && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001726 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001727 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001728 return false;
1729 }
1730
Geoff Lang2186c382016-10-14 10:54:54 -04001731 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001732}
1733
Geoff Lang2186c382016-10-14 10:54:54 -04001734bool ValidateGetQueryivRobustANGLE(Context *context,
1735 GLenum target,
1736 GLenum pname,
1737 GLsizei bufSize,
1738 GLsizei *length,
1739 GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001740{
Geoff Lang2186c382016-10-14 10:54:54 -04001741 if (!ValidateRobustEntryPoint(context, bufSize))
1742 {
1743 return false;
1744 }
1745
1746 if (!ValidateGetQueryivBase(context, target, pname, length))
1747 {
1748 return false;
1749 }
1750
1751 if (!ValidateRobustBufferSize(context, bufSize, *length))
1752 {
1753 return false;
1754 }
1755
1756 return true;
1757}
1758
1759bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname, GLsizei *numParams)
1760{
1761 if (numParams)
1762 {
1763 *numParams = 0;
1764 }
1765
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001766 Query *queryObject = context->getQuery(id, false, GL_NONE);
1767
1768 if (!queryObject)
1769 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001770 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidQueryId);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001771 return false;
1772 }
1773
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001774 if (context->getGLState().isQueryActive(queryObject))
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001775 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001776 ANGLE_VALIDATION_ERR(context, InvalidOperation(), QueryActive);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001777 return false;
1778 }
1779
1780 switch (pname)
1781 {
1782 case GL_QUERY_RESULT_EXT:
1783 case GL_QUERY_RESULT_AVAILABLE_EXT:
1784 break;
1785
1786 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07001787 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001788 return false;
1789 }
1790
Geoff Lang2186c382016-10-14 10:54:54 -04001791 if (numParams)
1792 {
1793 *numParams = 1;
1794 }
1795
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001796 return true;
1797}
1798
1799bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params)
1800{
1801 if (!context->getExtensions().disjointTimerQuery)
1802 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001803 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001804 return false;
1805 }
Geoff Lang2186c382016-10-14 10:54:54 -04001806 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1807}
1808
1809bool ValidateGetQueryObjectivRobustANGLE(Context *context,
1810 GLuint id,
1811 GLenum pname,
1812 GLsizei bufSize,
1813 GLsizei *length,
1814 GLint *params)
1815{
1816 if (!context->getExtensions().disjointTimerQuery)
1817 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001818 context->handleError(InvalidOperation() << "Timer query extension not enabled");
Geoff Lang2186c382016-10-14 10:54:54 -04001819 return false;
1820 }
1821
1822 if (!ValidateRobustEntryPoint(context, bufSize))
1823 {
1824 return false;
1825 }
1826
1827 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1828 {
1829 return false;
1830 }
1831
1832 if (!ValidateRobustBufferSize(context, bufSize, *length))
1833 {
1834 return false;
1835 }
1836
1837 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001838}
1839
1840bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params)
1841{
1842 if (!context->getExtensions().disjointTimerQuery &&
Geoff Lang2b4ce802016-04-28 13:34:50 -04001843 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001844 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001845 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001846 return false;
1847 }
Geoff Lang2186c382016-10-14 10:54:54 -04001848 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1849}
1850
1851bool ValidateGetQueryObjectuivRobustANGLE(Context *context,
1852 GLuint id,
1853 GLenum pname,
1854 GLsizei bufSize,
1855 GLsizei *length,
1856 GLuint *params)
1857{
1858 if (!context->getExtensions().disjointTimerQuery &&
1859 !context->getExtensions().occlusionQueryBoolean && !context->getExtensions().syncQuery)
1860 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001861 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001862 return false;
1863 }
1864
1865 if (!ValidateRobustEntryPoint(context, bufSize))
1866 {
1867 return false;
1868 }
1869
1870 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1871 {
1872 return false;
1873 }
1874
1875 if (!ValidateRobustBufferSize(context, bufSize, *length))
1876 {
1877 return false;
1878 }
1879
1880 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001881}
1882
1883bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params)
1884{
1885 if (!context->getExtensions().disjointTimerQuery)
1886 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001887 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001888 return false;
1889 }
Geoff Lang2186c382016-10-14 10:54:54 -04001890 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1891}
1892
1893bool ValidateGetQueryObjecti64vRobustANGLE(Context *context,
1894 GLuint id,
1895 GLenum pname,
1896 GLsizei bufSize,
1897 GLsizei *length,
1898 GLint64 *params)
1899{
1900 if (!context->getExtensions().disjointTimerQuery)
1901 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001902 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001903 return false;
1904 }
1905
1906 if (!ValidateRobustEntryPoint(context, bufSize))
1907 {
1908 return false;
1909 }
1910
1911 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1912 {
1913 return false;
1914 }
1915
1916 if (!ValidateRobustBufferSize(context, bufSize, *length))
1917 {
1918 return false;
1919 }
1920
1921 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001922}
1923
1924bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params)
1925{
1926 if (!context->getExtensions().disjointTimerQuery)
1927 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001928 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001929 return false;
1930 }
Geoff Lang2186c382016-10-14 10:54:54 -04001931 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
1932}
1933
1934bool ValidateGetQueryObjectui64vRobustANGLE(Context *context,
1935 GLuint id,
1936 GLenum pname,
1937 GLsizei bufSize,
1938 GLsizei *length,
1939 GLuint64 *params)
1940{
1941 if (!context->getExtensions().disjointTimerQuery)
1942 {
Brandon Jones6cad5662017-06-14 13:25:13 -07001943 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
Geoff Lang2186c382016-10-14 10:54:54 -04001944 return false;
1945 }
1946
1947 if (!ValidateRobustEntryPoint(context, bufSize))
1948 {
1949 return false;
1950 }
1951
1952 if (!ValidateGetQueryObjectValueBase(context, id, pname, length))
1953 {
1954 return false;
1955 }
1956
1957 if (!ValidateRobustBufferSize(context, bufSize, *length))
1958 {
1959 return false;
1960 }
1961
1962 return true;
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001963}
1964
Jiajia Qin5451d532017-11-16 17:16:34 +08001965bool ValidateUniformCommonBase(ValidationContext *context,
1966 gl::Program *program,
Frank Henigmana98a6472017-02-02 21:38:32 -05001967 GLint location,
1968 GLsizei count,
Jiajia Qin5451d532017-11-16 17:16:34 +08001969 const LinkedUniform **uniformOut)
Frank Henigmana98a6472017-02-02 21:38:32 -05001970{
Jiajia Qin5451d532017-11-16 17:16:34 +08001971 // TODO(Jiajia): Add image uniform check in future.
1972 if (count < 0)
Frank Henigmana98a6472017-02-02 21:38:32 -05001973 {
Jiajia Qin5451d532017-11-16 17:16:34 +08001974 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Frank Henigmana98a6472017-02-02 21:38:32 -05001975 return false;
1976 }
1977
Jiajia Qin5451d532017-11-16 17:16:34 +08001978 if (!program)
1979 {
1980 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidProgramName);
1981 return false;
1982 }
1983
1984 if (!program->isLinked())
1985 {
1986 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
1987 return false;
1988 }
1989
1990 if (location == -1)
1991 {
1992 // Silently ignore the uniform command
1993 return false;
1994 }
1995
1996 const auto &uniformLocations = program->getUniformLocations();
1997 size_t castedLocation = static_cast<size_t>(location);
1998 if (castedLocation >= uniformLocations.size())
1999 {
2000 context->handleError(InvalidOperation() << "Invalid uniform location");
2001 return false;
2002 }
2003
2004 const auto &uniformLocation = uniformLocations[castedLocation];
2005 if (uniformLocation.ignored)
2006 {
2007 // Silently ignore the uniform command
2008 return false;
2009 }
2010
2011 if (!uniformLocation.used())
2012 {
2013 context->handleError(InvalidOperation());
2014 return false;
2015 }
2016
2017 const auto &uniform = program->getUniformByIndex(uniformLocation.index);
2018
2019 // attempting to write an array to a non-array uniform is an INVALID_OPERATION
2020 if (!uniform.isArray() && count > 1)
2021 {
2022 context->handleError(InvalidOperation());
2023 return false;
2024 }
2025
2026 *uniformOut = &uniform;
2027 return true;
Frank Henigmana98a6472017-02-02 21:38:32 -05002028}
2029
Jiajia Qin5451d532017-11-16 17:16:34 +08002030bool ValidateUniform1ivValue(ValidationContext *context,
2031 GLenum uniformType,
2032 GLsizei count,
2033 const GLint *value)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002034{
Jiajia Qin5451d532017-11-16 17:16:34 +08002035 // Value type is GL_INT, because we only get here from glUniform1i{v}.
2036 // It is compatible with INT or BOOL.
2037 // Do these cheap tests first, for a little extra speed.
2038 if (GL_INT == uniformType || GL_BOOL == uniformType)
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002039 {
Jiajia Qin5451d532017-11-16 17:16:34 +08002040 return true;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002041 }
2042
Jiajia Qin5451d532017-11-16 17:16:34 +08002043 if (IsSamplerType(uniformType))
2044 {
2045 // Check that the values are in range.
2046 const GLint max = context->getCaps().maxCombinedTextureImageUnits;
2047 for (GLsizei i = 0; i < count; ++i)
2048 {
2049 if (value[i] < 0 || value[i] >= max)
2050 {
2051 context->handleError(InvalidValue() << "sampler uniform value out of range");
2052 return false;
2053 }
2054 }
2055 return true;
2056 }
2057
2058 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2059 return false;
2060}
2061
2062bool ValidateUniformValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2063{
2064 // Check that the value type is compatible with uniform type.
2065 // Do the cheaper test first, for a little extra speed.
2066 if (valueType == uniformType || VariableBoolVectorType(valueType) == uniformType)
2067 {
2068 return true;
2069 }
2070
2071 ANGLE_VALIDATION_ERR(context, InvalidOperation(), UniformSizeMismatch);
2072 return false;
2073}
2074
2075bool ValidateUniformMatrixValue(ValidationContext *context, GLenum valueType, GLenum uniformType)
2076{
2077 // Check that the value type is compatible with uniform type.
2078 if (valueType == uniformType)
2079 {
2080 return true;
2081 }
2082
2083 context->handleError(InvalidOperation() << "wrong type of value for uniform");
2084 return false;
Jiajia Qinee9f08c2016-11-16 10:06:10 +08002085}
2086
Jamie Madillc1d770e2017-04-13 17:31:24 -04002087bool ValidateUniform(ValidationContext *context, GLenum valueType, GLint location, GLsizei count)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002088{
Jamie Madill62d31cb2015-09-11 13:25:51 -04002089 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002090 gl::Program *programObject = context->getGLState().getProgram();
2091 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2092 ValidateUniformValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002093}
2094
Jamie Madillbe849e42017-05-02 15:49:00 -04002095bool ValidateUniform1iv(ValidationContext *context,
2096 GLint location,
2097 GLsizei count,
2098 const GLint *value)
Frank Henigmana98a6472017-02-02 21:38:32 -05002099{
2100 const LinkedUniform *uniform = nullptr;
2101 gl::Program *programObject = context->getGLState().getProgram();
2102 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2103 ValidateUniform1ivValue(context, uniform->type, count, value);
2104}
2105
Jamie Madillc1d770e2017-04-13 17:31:24 -04002106bool ValidateUniformMatrix(ValidationContext *context,
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002107 GLenum valueType,
He Yunchaoced53ae2016-11-29 15:00:51 +08002108 GLint location,
2109 GLsizei count,
Jamie Madillaa981bd2014-05-20 10:55:55 -04002110 GLboolean transpose)
2111{
Geoff Lang92019432017-11-20 13:09:34 -05002112 if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
Jamie Madillaa981bd2014-05-20 10:55:55 -04002113 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002114 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002115 return false;
Jamie Madillaa981bd2014-05-20 10:55:55 -04002116 }
2117
Jamie Madill62d31cb2015-09-11 13:25:51 -04002118 const LinkedUniform *uniform = nullptr;
Frank Henigmanf5f74ae2017-02-02 21:14:23 -05002119 gl::Program *programObject = context->getGLState().getProgram();
2120 return ValidateUniformCommonBase(context, programObject, location, count, &uniform) &&
2121 ValidateUniformMatrixValue(context, valueType, uniform->type);
Jamie Madillaa981bd2014-05-20 10:55:55 -04002122}
2123
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002124bool ValidateStateQuery(ValidationContext *context,
2125 GLenum pname,
2126 GLenum *nativeType,
2127 unsigned int *numParams)
Jamie Madill893ab082014-05-16 16:56:10 -04002128{
2129 if (!context->getQueryParameterInfo(pname, nativeType, numParams))
2130 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002131 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04002132 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002133 }
2134
Jamie Madill0af26e12015-03-05 19:54:33 -05002135 const Caps &caps = context->getCaps();
2136
Jamie Madill893ab082014-05-16 16:56:10 -04002137 if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
2138 {
2139 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
2140
Jamie Madill0af26e12015-03-05 19:54:33 -05002141 if (colorAttachment >= caps.maxDrawBuffers)
Jamie Madill893ab082014-05-16 16:56:10 -04002142 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002143 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002144 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002145 }
2146 }
2147
2148 switch (pname)
2149 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002150 case GL_TEXTURE_BINDING_2D:
2151 case GL_TEXTURE_BINDING_CUBE_MAP:
2152 case GL_TEXTURE_BINDING_3D:
2153 case GL_TEXTURE_BINDING_2D_ARRAY:
JiangYizhou24fe74c2017-07-06 16:56:50 +08002154 case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
He Yunchaoced53ae2016-11-29 15:00:51 +08002155 break;
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002156 case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
2157 if (!context->getExtensions().textureRectangle)
2158 {
2159 context->handleError(InvalidEnum()
2160 << "ANGLE_texture_rectangle extension not present");
2161 return false;
2162 }
2163 break;
He Yunchaoced53ae2016-11-29 15:00:51 +08002164 case GL_TEXTURE_BINDING_EXTERNAL_OES:
2165 if (!context->getExtensions().eglStreamConsumerExternal &&
2166 !context->getExtensions().eglImageExternal)
2167 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002168 context->handleError(InvalidEnum() << "Neither NV_EGL_stream_consumer_external "
2169 "nor GL_OES_EGL_image_external "
2170 "extensions enabled");
He Yunchaoced53ae2016-11-29 15:00:51 +08002171 return false;
2172 }
2173 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002174
He Yunchaoced53ae2016-11-29 15:00:51 +08002175 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
2176 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
Jamie Madill893ab082014-05-16 16:56:10 -04002177 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002178 if (context->getGLState().getReadFramebuffer()->checkStatus(context) !=
2179 GL_FRAMEBUFFER_COMPLETE)
Jamie Madill893ab082014-05-16 16:56:10 -04002180 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002181 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002182 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002183 }
2184
Jamie Madill51f40ec2016-06-15 14:06:00 -04002185 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
2186 ASSERT(framebuffer);
Martin Radev138064f2016-07-15 12:03:41 +03002187
2188 if (framebuffer->getReadBufferState() == GL_NONE)
2189 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002190 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002191 return false;
2192 }
2193
Jamie Madillb6bda4a2015-04-20 12:53:26 -04002194 const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
Jamie Madill3c7fa222014-06-05 13:08:51 -04002195 if (!attachment)
Jamie Madill893ab082014-05-16 16:56:10 -04002196 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002197 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002198 return false;
Jamie Madill893ab082014-05-16 16:56:10 -04002199 }
2200 }
2201 break;
2202
He Yunchaoced53ae2016-11-29 15:00:51 +08002203 default:
2204 break;
Jamie Madill893ab082014-05-16 16:56:10 -04002205 }
2206
2207 // pname is valid, but there are no parameters to return
Geoff Langff5b2d52016-09-07 11:32:23 -04002208 if (*numParams == 0)
2209 {
2210 return false;
2211 }
2212
2213 return true;
2214}
2215
2216bool ValidateRobustStateQuery(ValidationContext *context,
2217 GLenum pname,
2218 GLsizei bufSize,
2219 GLenum *nativeType,
2220 unsigned int *numParams)
2221{
2222 if (!ValidateRobustEntryPoint(context, bufSize))
2223 {
2224 return false;
2225 }
2226
2227 if (!ValidateStateQuery(context, pname, nativeType, numParams))
2228 {
2229 return false;
2230 }
2231
2232 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
Jamie Madill893ab082014-05-16 16:56:10 -04002233 {
2234 return false;
2235 }
2236
2237 return true;
2238}
2239
Jamie Madillc29968b2016-01-20 11:17:23 -05002240bool ValidateCopyTexImageParametersBase(ValidationContext *context,
2241 GLenum target,
2242 GLint level,
2243 GLenum internalformat,
2244 bool isSubImage,
2245 GLint xoffset,
2246 GLint yoffset,
2247 GLint zoffset,
2248 GLint x,
2249 GLint y,
2250 GLsizei width,
2251 GLsizei height,
2252 GLint border,
Jamie Madill0c8abca2016-07-22 20:21:26 -04002253 Format *textureFormatOut)
Jamie Madill560a8d82014-05-21 13:06:20 -04002254{
Brandon Jones6cad5662017-06-14 13:25:13 -07002255 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002256 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002257 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2258 return false;
2259 }
2260
2261 if (width < 0 || height < 0)
2262 {
2263 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Geoff Langb1196682014-07-23 13:47:29 -04002264 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002265 }
2266
He Yunchaoced53ae2016-11-29 15:00:51 +08002267 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
2268 std::numeric_limits<GLsizei>::max() - yoffset < height)
Jamie Madill560a8d82014-05-21 13:06:20 -04002269 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002270 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002271 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002272 }
2273
2274 if (border != 0)
2275 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002276 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
Geoff Langb1196682014-07-23 13:47:29 -04002277 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002278 }
2279
2280 if (!ValidMipLevel(context, target, level))
2281 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002282 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04002283 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002284 }
2285
Jamie Madill51f40ec2016-06-15 14:06:00 -04002286 const auto &state = context->getGLState();
Jamie Madillacf2f3a2017-11-21 19:22:44 -05002287 Framebuffer *readFramebuffer = state.getReadFramebuffer();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002288 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill560a8d82014-05-21 13:06:20 -04002289 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002290 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002291 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002292 }
2293
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002294 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
Jamie Madill560a8d82014-05-21 13:06:20 -04002295 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002296 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002297 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002298 }
2299
Martin Radev138064f2016-07-15 12:03:41 +03002300 if (readFramebuffer->getReadBufferState() == GL_NONE)
2301 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002302 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Martin Radev138064f2016-07-15 12:03:41 +03002303 return false;
2304 }
2305
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002306 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
2307 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
He Yunchao66a41a22016-12-15 16:45:05 +08002308 // attachment and WebGL defines it to be an error. We do the check unconditionally as the
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002309 // situation is an application error that would lead to a crash in ANGLE.
Martin Radev04e2c3b2017-07-27 16:54:35 +03002310 const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
2311 if (source == nullptr)
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002312 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002313 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Corentin Wallez3c90ed62016-12-16 16:19:28 -05002314 return false;
2315 }
2316
Martin Radev04e2c3b2017-07-27 16:54:35 +03002317 // ANGLE_multiview spec, Revision 1:
2318 // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
2319 // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
2320 // is not NONE.
2321 if (source->getMultiviewLayout() != GL_NONE)
2322 {
2323 context->handleError(InvalidFramebufferOperation()
2324 << "The active read framebuffer object has multiview attachments.");
2325 return false;
2326 }
2327
Geoff Langaae65a42014-05-26 12:43:44 -04002328 const gl::Caps &caps = context->getCaps();
2329
Geoff Langaae65a42014-05-26 12:43:44 -04002330 GLuint maxDimension = 0;
Jamie Madill560a8d82014-05-21 13:06:20 -04002331 switch (target)
2332 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002333 case GL_TEXTURE_2D:
2334 maxDimension = caps.max2DTextureSize;
2335 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002336
He Yunchaoced53ae2016-11-29 15:00:51 +08002337 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2338 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2339 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2340 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2341 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2342 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2343 maxDimension = caps.maxCubeMapTextureSize;
2344 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002345
Corentin Wallez13c0dd42017-07-04 18:27:01 -04002346 case GL_TEXTURE_RECTANGLE_ANGLE:
2347 maxDimension = caps.maxRectangleTextureSize;
2348 break;
2349
He Yunchaoced53ae2016-11-29 15:00:51 +08002350 case GL_TEXTURE_2D_ARRAY:
2351 maxDimension = caps.max2DTextureSize;
2352 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002353
He Yunchaoced53ae2016-11-29 15:00:51 +08002354 case GL_TEXTURE_3D:
2355 maxDimension = caps.max3DTextureSize;
2356 break;
Jamie Madill560a8d82014-05-21 13:06:20 -04002357
He Yunchaoced53ae2016-11-29 15:00:51 +08002358 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002359 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +08002360 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002361 }
2362
Jamie Madillc29968b2016-01-20 11:17:23 -05002363 gl::Texture *texture =
2364 state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
Jamie Madill560a8d82014-05-21 13:06:20 -04002365 if (!texture)
2366 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002367 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002368 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002369 }
2370
Geoff Lang69cce582015-09-17 13:20:36 -04002371 if (texture->getImmutableFormat() && !isSubImage)
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
Geoff Langca271392017-04-05 12:30:00 -04002377 const gl::InternalFormat &formatInfo =
Geoff Lang86f81162017-10-30 15:10:45 -04002378 isSubImage ? *texture->getFormat(target, level).info
2379 : gl::GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Geoff Lang5d601382014-07-22 15:14:06 -04002380
Geoff Lang966c9402017-04-18 12:38:27 -04002381 if (formatInfo.depthBits > 0 || formatInfo.compressed)
Jamie Madill560a8d82014-05-21 13:06:20 -04002382 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002383 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05002384 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002385 }
2386
2387 if (isSubImage)
2388 {
Geoff Langa9be0dc2014-12-17 12:34:40 -05002389 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
2390 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
2391 static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
Jamie Madill560a8d82014-05-21 13:06:20 -04002392 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002393 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002394 return false;
Jamie Madill560a8d82014-05-21 13:06:20 -04002395 }
2396 }
Jamie Madill6f38f822014-06-06 17:12:20 -04002397 else
2398 {
Geoff Lang691e58c2014-12-19 17:03:25 -05002399 if (IsCubeMapTextureTarget(target) && width != height)
Jamie Madill6f38f822014-06-06 17:12:20 -04002400 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002401 ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapIncomplete);
Geoff Langb1196682014-07-23 13:47:29 -04002402 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002403 }
2404
Geoff Langeb66a6e2016-10-31 13:06:12 -04002405 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Jamie Madill6f38f822014-06-06 17:12:20 -04002406 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002407 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langb1196682014-07-23 13:47:29 -04002408 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002409 }
2410
2411 int maxLevelDimension = (maxDimension >> level);
He Yunchaoced53ae2016-11-29 15:00:51 +08002412 if (static_cast<int>(width) > maxLevelDimension ||
2413 static_cast<int>(height) > maxLevelDimension)
Jamie Madill6f38f822014-06-06 17:12:20 -04002414 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002415 ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
Geoff Langb1196682014-07-23 13:47:29 -04002416 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -04002417 }
2418 }
Jamie Madill560a8d82014-05-21 13:06:20 -04002419
Jamie Madill0c8abca2016-07-22 20:21:26 -04002420 if (textureFormatOut)
2421 {
2422 *textureFormatOut = texture->getFormat(target, level);
2423 }
Jamie Madillf695a3a2017-01-11 17:36:35 -05002424
2425 // Detect texture copying feedback loops for WebGL.
2426 if (context->getExtensions().webglCompatibility)
2427 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002428 if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
Jamie Madillf695a3a2017-01-11 17:36:35 -05002429 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002430 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madillf695a3a2017-01-11 17:36:35 -05002431 return false;
2432 }
2433 }
2434
Jamie Madill560a8d82014-05-21 13:06:20 -04002435 return true;
2436}
2437
Jiajia Qind9671222016-11-29 16:30:31 +08002438bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
Jamie Madill250d33f2014-06-06 17:09:03 -04002439{
Jamie Madill1aeb1312014-06-20 13:21:25 -04002440 switch (mode)
2441 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002442 case GL_POINTS:
2443 case GL_LINES:
2444 case GL_LINE_LOOP:
2445 case GL_LINE_STRIP:
2446 case GL_TRIANGLES:
2447 case GL_TRIANGLE_STRIP:
2448 case GL_TRIANGLE_FAN:
2449 break;
2450 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002451 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDrawMode);
He Yunchaoced53ae2016-11-29 15:00:51 +08002452 return false;
Jamie Madill1aeb1312014-06-20 13:21:25 -04002453 }
2454
Jamie Madill250d33f2014-06-06 17:09:03 -04002455 if (count < 0)
2456 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002457 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Geoff Langb1196682014-07-23 13:47:29 -04002458 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002459 }
2460
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002461 const State &state = context->getGLState();
Geoff Langb1196682014-07-23 13:47:29 -04002462
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002463 const Extensions &extensions = context->getExtensions();
2464
2465 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2466 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2467 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2468 if (!extensions.webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002469 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002470 // Check for mapped buffers
2471 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002472 if (state.hasMappedBuffer(BufferBinding::Array))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002473 {
2474 context->handleError(InvalidOperation());
2475 return false;
2476 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002477 }
2478
Jamie Madillcbcde722017-01-06 14:50:00 -05002479 // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
2480 // Section 6.10 of the WebGL 1.0 spec.
Jamie Madill51f40ec2016-06-15 14:06:00 -04002481 Framebuffer *framebuffer = state.getDrawFramebuffer();
Martin Radevffe754b2017-07-31 10:38:07 +03002482 if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
Jamie Madillac528012014-06-20 13:21:23 -04002483 {
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002484 const FramebufferAttachment *dsAttachment =
2485 framebuffer->getStencilOrDepthStencilAttachment();
2486 GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
He Yunchaoced53ae2016-11-29 15:00:51 +08002487 GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
Jinyoung Hur85769f02015-10-20 17:08:44 -04002488 const DepthStencilState &depthStencilState = state.getDepthStencilState();
Corentin Wallezb1d0a2552016-12-19 16:15:54 -05002489
2490 bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
2491 bool differentWritemasks =
2492 (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
2493 (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
2494 bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
2495 (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
2496
2497 if (differentRefs || differentWritemasks || differentMasks)
Geoff Lang3a86ad32015-09-01 11:47:05 -04002498 {
Martin Radevffe754b2017-07-31 10:38:07 +03002499 if (!extensions.webglCompatibility)
Jamie Madillcbcde722017-01-06 14:50:00 -05002500 {
Yuly Novikovd73f8522017-01-13 17:48:57 -05002501 ERR() << "This ANGLE implementation does not support separate front/back stencil "
2502 "writemasks, reference values, or stencil mask values.";
Jamie Madillcbcde722017-01-06 14:50:00 -05002503 }
Brandon Jones6cad5662017-06-14 13:25:13 -07002504 ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
Geoff Lang3a86ad32015-09-01 11:47:05 -04002505 return false;
2506 }
Jamie Madillac528012014-06-20 13:21:23 -04002507 }
2508
Jamie Madilldd43e6c2017-03-24 14:18:49 -04002509 if (framebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002510 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002511 context->handleError(InvalidFramebufferOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002512 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04002513 }
2514
Geoff Lang7dd2e102014-11-10 15:19:26 -05002515 gl::Program *program = state.getProgram();
2516 if (!program)
Jamie Madilld4cfa572014-07-08 10:00:32 -04002517 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002518 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
Geoff Langb1196682014-07-23 13:47:29 -04002519 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002520 }
2521
Yunchao Hecddcb592017-11-13 15:27:35 +08002522 // In OpenGL ES spec for UseProgram at section 7.3, trying to render without
2523 // vertex shader stage or fragment shader stage is a undefined behaviour.
2524 // But ANGLE should clearly generate an INVALID_OPERATION error instead of
2525 // produce undefined result.
Yunchao Heece12532017-11-21 15:50:21 +08002526 if (!program->hasLinkedVertexShader() || !program->hasLinkedFragmentShader())
Yunchao Hecddcb592017-11-13 15:27:35 +08002527 {
2528 context->handleError(InvalidOperation() << "It is a undefined behaviour to render without "
2529 "vertex shader stage or fragment shader stage.");
2530 return false;
2531 }
2532
Yunchao Hef81ce4a2017-04-24 10:49:17 +08002533 if (!program->validateSamplers(nullptr, context->getCaps()))
Jamie Madilld4cfa572014-07-08 10:00:32 -04002534 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002535 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002536 return false;
Jamie Madilld4cfa572014-07-08 10:00:32 -04002537 }
2538
Martin Radevffe754b2017-07-31 10:38:07 +03002539 if (extensions.multiview)
Martin Radev7cf61662017-07-26 17:10:53 +03002540 {
Martin Radevda8e2572017-09-12 17:21:16 +03002541 const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
Martin Radev7e69f762017-07-27 14:54:13 +03002542 const int framebufferNumViews = framebuffer->getNumViews();
Martin Radevda8e2572017-09-12 17:21:16 +03002543 if (framebufferNumViews != programNumViews)
Martin Radev7cf61662017-07-26 17:10:53 +03002544 {
2545 context->handleError(InvalidOperation() << "The number of views in the active program "
2546 "and draw framebuffer does not match.");
2547 return false;
2548 }
Martin Radev7e69f762017-07-27 14:54:13 +03002549
2550 const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
2551 if (transformFeedbackObject != nullptr && transformFeedbackObject->isActive() &&
2552 framebufferNumViews > 1)
2553 {
2554 context->handleError(InvalidOperation()
2555 << "There is an active transform feedback object "
2556 "when the number of views in the active draw "
2557 "framebuffer is greater than 1.");
2558 return false;
2559 }
Martin Radevffe754b2017-07-31 10:38:07 +03002560
2561 if (extensions.disjointTimerQuery && framebufferNumViews > 1 &&
2562 state.isQueryActive(GL_TIME_ELAPSED_EXT))
2563 {
2564 context->handleError(InvalidOperation() << "There is an active query for target "
2565 "GL_TIME_ELAPSED_EXT when the number of "
2566 "views in the active draw framebuffer is "
2567 "greater than 1.");
2568 return false;
2569 }
Martin Radev7cf61662017-07-26 17:10:53 +03002570 }
2571
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002572 // Uniform buffer validation
He Yunchaoced53ae2016-11-29 15:00:51 +08002573 for (unsigned int uniformBlockIndex = 0;
2574 uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002575 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08002576 const gl::InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
He Yunchaoced53ae2016-11-29 15:00:51 +08002577 GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
Geoff Lang5d124a62015-09-15 13:03:27 -04002578 const OffsetBindingPointer<Buffer> &uniformBuffer =
2579 state.getIndexedUniformBuffer(blockBinding);
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002580
Geoff Lang5d124a62015-09-15 13:03:27 -04002581 if (uniformBuffer.get() == nullptr)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002582 {
2583 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002584 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002585 InvalidOperation()
2586 << "It is undefined behaviour to have a used but unbound uniform buffer.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002587 return false;
2588 }
2589
Geoff Lang5d124a62015-09-15 13:03:27 -04002590 size_t uniformBufferSize = uniformBuffer.getSize();
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002591 if (uniformBufferSize == 0)
2592 {
2593 // Bind the whole buffer.
Minmin Gong794e0002015-04-07 18:31:54 -07002594 uniformBufferSize = static_cast<size_t>(uniformBuffer->getSize());
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002595 }
2596
Jamie Madill62d31cb2015-09-11 13:25:51 -04002597 if (uniformBufferSize < uniformBlock.dataSize)
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002598 {
2599 // undefined behaviour
Jamie Madill437fa652016-05-03 15:13:24 -04002600 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002601 InvalidOperation()
2602 << "It is undefined behaviour to use a uniform buffer that is too small.");
Gregoire Payen de La Garanderie68694e92015-03-24 14:03:37 +00002603 return false;
2604 }
2605 }
2606
Geoff Lange0cff192017-05-30 13:04:56 -04002607 // Do some additonal WebGL-specific validation
Martin Radevffe754b2017-07-31 10:38:07 +03002608 if (extensions.webglCompatibility)
Jamie Madilla4595b82017-01-11 17:36:34 -05002609 {
Geoff Lange0cff192017-05-30 13:04:56 -04002610 // Detect rendering feedback loops for WebGL.
Jamie Madilla4595b82017-01-11 17:36:34 -05002611 if (framebuffer->formsRenderingFeedbackLoopWith(state))
2612 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002613 ANGLE_VALIDATION_ERR(context, InvalidOperation(), FeedbackLoop);
Jamie Madilla4595b82017-01-11 17:36:34 -05002614 return false;
2615 }
Geoff Lange0cff192017-05-30 13:04:56 -04002616
Geoff Lang9ab5b822017-05-30 16:19:23 -04002617 // Detect that the vertex shader input types match the attribute types
2618 if (!ValidateVertexShaderAttributeTypeMatch(context))
2619 {
2620 return false;
2621 }
2622
Geoff Lange0cff192017-05-30 13:04:56 -04002623 // Detect that the color buffer types match the fragment shader output types
2624 if (!ValidateFragmentShaderColorBufferTypeMatch(context))
2625 {
2626 return false;
2627 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002628 }
2629
Jamie Madill250d33f2014-06-06 17:09:03 -04002630 // No-op if zero count
2631 return (count > 0);
2632}
2633
Jamie Madillc1d770e2017-04-13 17:31:24 -04002634bool ValidateDrawArraysCommon(ValidationContext *context,
2635 GLenum mode,
2636 GLint first,
2637 GLsizei count,
2638 GLsizei primcount)
Jamie Madill250d33f2014-06-06 17:09:03 -04002639{
Jamie Madillfd716582014-06-06 17:09:04 -04002640 if (first < 0)
Jamie Madill250d33f2014-06-06 17:09:03 -04002641 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002642 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStart);
Geoff Langb1196682014-07-23 13:47:29 -04002643 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002644 }
2645
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002646 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002647 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002648 if (curTransformFeedback && curTransformFeedback->isActive() &&
2649 !curTransformFeedback->isPaused() && curTransformFeedback->getPrimitiveMode() != mode)
Jamie Madillfd716582014-06-06 17:09:04 -04002650 {
2651 // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
He Yunchaoced53ae2016-11-29 15:00:51 +08002652 // that does not match the current transform feedback object's draw mode (if transform
2653 // feedback
Jamie Madillfd716582014-06-06 17:09:04 -04002654 // is active), (3.0.2, section 2.14, pg 86)
Brandon Jones6cad5662017-06-14 13:25:13 -07002655 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDrawModeTransformFeedback);
Geoff Langb1196682014-07-23 13:47:29 -04002656 return false;
Jamie Madillfd716582014-06-06 17:09:04 -04002657 }
2658
Jiajia Qind9671222016-11-29 16:30:31 +08002659 if (!ValidateDrawBase(context, mode, count))
Corentin Wallez18a2fb32015-08-10 12:58:14 -07002660 {
2661 return false;
2662 }
2663
Corentin Wallez71168a02016-12-19 15:11:18 -08002664 // Check the computation of maxVertex doesn't overflow.
2665 // - first < 0 or count < 0 have been checked as an error condition
2666 // - count > 0 has been checked in ValidateDrawBase as it makes the call a noop
2667 // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
2668 ASSERT(count > 0 && first >= 0);
2669 int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
2670 if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
Corentin Wallez92db6942016-12-09 13:10:36 -05002671 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002672 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez92db6942016-12-09 13:10:36 -05002673 return false;
2674 }
2675
Corentin Wallez71168a02016-12-19 15:11:18 -08002676 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(maxVertex), count))
Jamie Madillfd716582014-06-06 17:09:04 -04002677 {
2678 return false;
2679 }
2680
2681 return true;
2682}
2683
He Yunchaoced53ae2016-11-29 15:00:51 +08002684bool ValidateDrawArraysInstancedANGLE(Context *context,
2685 GLenum mode,
2686 GLint first,
2687 GLsizei count,
2688 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002689{
Geoff Lang63c5a592017-09-27 14:08:16 -04002690 if (!context->getExtensions().instancedArrays)
2691 {
2692 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2693 return false;
2694 }
2695
Corentin Wallez170efbf2017-05-02 13:45:01 -04002696 if (!ValidateDrawArraysInstancedBase(context, mode, first, count, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002697 {
2698 return false;
2699 }
2700
Corentin Wallez0dc97812017-06-22 14:38:44 -04002701 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002702}
2703
Jiajia Qind9671222016-11-29 16:30:31 +08002704bool ValidateDrawElementsBase(ValidationContext *context, GLenum type)
Jamie Madillfd716582014-06-06 17:09:04 -04002705{
Jamie Madill250d33f2014-06-06 17:09:03 -04002706 switch (type)
2707 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002708 case GL_UNSIGNED_BYTE:
2709 case GL_UNSIGNED_SHORT:
2710 break;
2711 case GL_UNSIGNED_INT:
2712 if (context->getClientMajorVersion() < 3 && !context->getExtensions().elementIndexUint)
2713 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002714 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002715 return false;
2716 }
2717 break;
2718 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07002719 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TypeNotUnsignedShortByte);
He Yunchaoced53ae2016-11-29 15:00:51 +08002720 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002721 }
2722
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002723 const State &state = context->getGLState();
Jamie Madilld9ba4f72014-08-04 10:47:59 -04002724
2725 gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
He Yunchaoced53ae2016-11-29 15:00:51 +08002726 if (curTransformFeedback && curTransformFeedback->isActive() &&
2727 !curTransformFeedback->isPaused())
Jamie Madill250d33f2014-06-06 17:09:03 -04002728 {
He Yunchaoced53ae2016-11-29 15:00:51 +08002729 // It is an invalid operation to call DrawElements, DrawRangeElements or
2730 // DrawElementsInstanced
Jamie Madill250d33f2014-06-06 17:09:03 -04002731 // while transform feedback is active, (3.0.2, section 2.14, pg 86)
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002732 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002733 return false;
Jamie Madill250d33f2014-06-06 17:09:03 -04002734 }
2735
Jiajia Qind9671222016-11-29 16:30:31 +08002736 return true;
2737}
2738
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002739bool ValidateDrawElementsCommon(ValidationContext *context,
2740 GLenum mode,
2741 GLsizei count,
2742 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002743 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002744 GLsizei primcount)
Jiajia Qind9671222016-11-29 16:30:31 +08002745{
2746 if (!ValidateDrawElementsBase(context, type))
2747 return false;
2748
2749 const State &state = context->getGLState();
2750
Corentin Wallez170efbf2017-05-02 13:45:01 -04002751 if (!ValidateDrawBase(context, mode, count))
2752 {
2753 return false;
2754 }
2755
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002756 // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
2757 // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
2758 // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
2759 if (!context->getExtensions().webglCompatibility)
Jamie Madill250d33f2014-06-06 17:09:03 -04002760 {
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002761 // Check for mapped buffers
2762 // TODO(jmadill): Optimize this check for non - WebGL contexts.
Corentin Wallez336129f2017-10-17 15:55:40 -04002763 if (state.hasMappedBuffer(gl::BufferBinding::ElementArray))
Jiawei Shao3ef06a92017-11-03 18:41:33 +08002764 {
2765 context->handleError(InvalidOperation() << "Index buffer is mapped.");
2766 return false;
2767 }
Jamie Madill250d33f2014-06-06 17:09:03 -04002768 }
2769
He Yunchaoced53ae2016-11-29 15:00:51 +08002770 const gl::VertexArray *vao = state.getVertexArray();
Jamie Madill8e344942015-07-09 14:22:07 -04002771 gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get();
Jamie Madilld4cfa572014-07-08 10:00:32 -04002772
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002773 GLuint typeBytes = gl::GetTypeInfo(type).bytes;
2774
2775 if (context->getExtensions().webglCompatibility)
2776 {
2777 ASSERT(isPow2(typeBytes) && typeBytes > 0);
2778 if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
2779 {
2780 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2781 // The offset arguments to drawElements and [...], must be a multiple of the size of the
2782 // data type passed to the call, or an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002783 ANGLE_VALIDATION_ERR(context, InvalidOperation(), OffsetMustBeMultipleOfType);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002784 return false;
2785 }
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002786
2787 // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
2788 // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
2789 // error is generated.
2790 if (reinterpret_cast<intptr_t>(indices) < 0)
2791 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002792 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002793 return false;
2794 }
Geoff Langfeb8c682017-02-13 16:07:35 -05002795 }
2796
2797 if (context->getExtensions().webglCompatibility ||
2798 !context->getGLState().areClientArraysEnabled())
2799 {
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002800 if (!elementArrayBuffer && count > 0)
2801 {
2802 // [WebGL 1.0] Section 6.2 No Client Side Arrays
2803 // If drawElements is called with a count greater than zero, and no WebGLBuffer is bound
2804 // to the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
Brandon Jones6cad5662017-06-14 13:25:13 -07002805 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MustHaveElementArrayBinding);
Corentin Wallez3f6d4df2017-01-30 18:04:36 -05002806 return false;
2807 }
2808 }
2809
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002810 if (count > 0)
Jamie Madillae3000b2014-08-25 15:47:51 -04002811 {
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002812 if (elementArrayBuffer)
Jamie Madillae3000b2014-08-25 15:47:51 -04002813 {
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002814 // The max possible type size is 8 and count is on 32 bits so doing the multiplication
2815 // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
2816 static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
2817 constexpr uint64_t kMaxTypeSize = 8;
2818 constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
2819 constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
2820 static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002821
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002822 uint64_t typeSize = typeBytes;
2823 uint64_t elementCount = static_cast<uint64_t>(count);
2824 ASSERT(elementCount > 0 && typeSize <= kMaxTypeSize);
2825
2826 // Doing the multiplication here is overflow-safe
2827 uint64_t elementDataSizeNoOffset = typeSize * elementCount;
2828
2829 // The offset can be any value, check for overflows
2830 uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
2831 if (elementDataSizeNoOffset > kUint64Max - offset)
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002832 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002833 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002834 return false;
2835 }
2836
Corentin Wallezfe9306a2017-02-01 17:41:05 -05002837 uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
2838 if (elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize()))
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002839 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002840 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002841 return false;
2842 }
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002843
Corentin Wallez487653b2017-09-01 17:17:55 -04002844 ASSERT(isPow2(typeSize) && typeSize > 0);
2845 if ((elementArrayBuffer->getSize() & (typeSize - 1)) != 0)
Brandon Jonesed5b46f2017-07-21 08:39:17 -07002846 {
2847 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedByteCountType);
2848 return false;
2849 }
Corentin Wallez0844f2d2017-01-31 17:02:59 -05002850 }
2851 else if (!indices)
2852 {
2853 // This is an application error that would normally result in a crash,
2854 // but we catch it and return an error
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002855 context->handleError(InvalidOperation() << "No element array buffer and no pointer.");
Geoff Langb1196682014-07-23 13:47:29 -04002856 return false;
Jamie Madillae3000b2014-08-25 15:47:51 -04002857 }
Jamie Madillae3000b2014-08-25 15:47:51 -04002858 }
2859
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002860 if (context->getExtensions().robustBufferAccessBehavior)
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002861 {
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002862 // Here we use maxVertex = 0 and vertexCount = 1 to avoid retrieving IndexRange when robust
2863 // access is enabled.
2864 if (!ValidateDrawAttribs(context, primcount, 0, 1))
2865 {
2866 return false;
2867 }
2868 }
2869 else
2870 {
2871 // Use the parameter buffer to retrieve and cache the index range.
2872 const auto &params = context->getParams<HasIndexRange>();
2873 const auto &indexRangeOpt = params.getIndexRange();
2874 if (!indexRangeOpt.valid())
2875 {
2876 // Unexpected error.
2877 return false;
2878 }
2879
2880 // If we use an index greater than our maximum supported index range, return an error.
2881 // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always
2882 // return an error if possible here.
2883 if (static_cast<GLuint64>(indexRangeOpt.value().end) >= context->getCaps().maxElementIndex)
2884 {
2885 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExceedsMaxElement);
2886 return false;
2887 }
2888
2889 if (!ValidateDrawAttribs(context, primcount, static_cast<GLint>(indexRangeOpt.value().end),
2890 static_cast<GLint>(indexRangeOpt.value().vertexCount())))
2891 {
2892 return false;
2893 }
2894
2895 // No op if there are no real indices in the index data (all are primitive restart).
2896 return (indexRangeOpt.value().vertexIndexCount > 0);
Corentin Wallezc1346fb2017-08-24 16:11:26 +00002897 }
2898
Jiajia Qin8a7b3a02017-08-25 16:05:48 +08002899 return true;
Jamie Madillfd716582014-06-06 17:09:04 -04002900}
2901
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002902bool ValidateDrawElementsInstancedCommon(ValidationContext *context,
2903 GLenum mode,
2904 GLsizei count,
2905 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002906 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002907 GLsizei primcount)
Jamie Madillfd716582014-06-06 17:09:04 -04002908{
Corentin Wallez0dc97812017-06-22 14:38:44 -04002909 return ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount);
Jamie Madill250d33f2014-06-06 17:09:03 -04002910}
2911
Geoff Lang3edfe032015-09-04 16:38:24 -04002912bool ValidateDrawElementsInstancedANGLE(Context *context,
2913 GLenum mode,
2914 GLsizei count,
2915 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002916 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04002917 GLsizei primcount)
Geoff Lang87a93302014-09-16 13:29:43 -04002918{
Geoff Lang63c5a592017-09-27 14:08:16 -04002919 if (!context->getExtensions().instancedArrays)
2920 {
2921 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
2922 return false;
2923 }
2924
Corentin Wallez170efbf2017-05-02 13:45:01 -04002925 if (!ValidateDrawElementsInstancedBase(context, mode, count, type, indices, primcount))
Geoff Lang87a93302014-09-16 13:29:43 -04002926 {
2927 return false;
2928 }
2929
Corentin Wallez0dc97812017-06-22 14:38:44 -04002930 return ValidateDrawInstancedANGLE(context);
Geoff Lang87a93302014-09-16 13:29:43 -04002931}
2932
He Yunchaoced53ae2016-11-29 15:00:51 +08002933bool ValidateFramebufferTextureBase(Context *context,
2934 GLenum target,
2935 GLenum attachment,
2936 GLuint texture,
2937 GLint level)
Jamie Madill570f7c82014-07-03 10:38:54 -04002938{
Geoff Lange8afa902017-09-27 15:00:43 -04002939 if (!ValidFramebufferTarget(context, target))
Jamie Madill55ec3b12014-07-03 10:38:57 -04002940 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002941 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002942 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002943 }
2944
2945 if (!ValidateAttachmentTarget(context, attachment))
Jamie Madill570f7c82014-07-03 10:38:54 -04002946 {
2947 return false;
2948 }
2949
Jamie Madill55ec3b12014-07-03 10:38:57 -04002950 if (texture != 0)
2951 {
2952 gl::Texture *tex = context->getTexture(texture);
2953
Luc Ferronadcf0ae2018-01-24 08:27:37 -05002954 if (tex == nullptr)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002955 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002956 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04002957 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002958 }
2959
2960 if (level < 0)
2961 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002962 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002963 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002964 }
2965 }
2966
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002967 const gl::Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
Jamie Madill84115c92015-04-23 15:00:07 -04002968 ASSERT(framebuffer);
Jamie Madill55ec3b12014-07-03 10:38:57 -04002969
Jamie Madill84115c92015-04-23 15:00:07 -04002970 if (framebuffer->id() == 0)
Jamie Madill55ec3b12014-07-03 10:38:57 -04002971 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002972 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langb1196682014-07-23 13:47:29 -04002973 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04002974 }
2975
2976 return true;
2977}
2978
Geoff Langb1196682014-07-23 13:47:29 -04002979bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
Jamie Madill0063c512014-08-25 15:47:53 -04002980{
2981 if (program == 0)
2982 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002983 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04002984 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002985 }
2986
Dian Xiang769769a2015-09-09 15:20:08 -07002987 gl::Program *programObject = GetValidProgram(context, program);
2988 if (!programObject)
Shannon Woods4de4fd62014-11-07 16:22:02 -05002989 {
2990 return false;
2991 }
2992
Jamie Madill0063c512014-08-25 15:47:53 -04002993 if (!programObject || !programObject->isLinked())
2994 {
Brandon Jones6cad5662017-06-14 13:25:13 -07002995 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langb1196682014-07-23 13:47:29 -04002996 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04002997 }
2998
Geoff Lang7dd2e102014-11-10 15:19:26 -05002999 if (!programObject->isValidUniformLocation(location))
Jamie Madill549c7fd2014-08-25 15:47:56 -04003000 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003001 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04003002 return false;
Jamie Madill549c7fd2014-08-25 15:47:56 -04003003 }
3004
Jamie Madill0063c512014-08-25 15:47:53 -04003005 return true;
3006}
3007
Geoff Langf41d0ee2016-10-07 13:04:23 -04003008static bool ValidateSizedGetUniform(Context *context,
3009 GLuint program,
3010 GLint location,
3011 GLsizei bufSize,
3012 GLsizei *length)
Jamie Madill78f41802014-08-25 15:47:55 -04003013{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003014 if (length)
3015 {
3016 *length = 0;
3017 }
3018
Jamie Madill78f41802014-08-25 15:47:55 -04003019 if (!ValidateGetUniformBase(context, program, location))
Jamie Madill0063c512014-08-25 15:47:53 -04003020 {
Jamie Madill78f41802014-08-25 15:47:55 -04003021 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003022 }
3023
Geoff Langf41d0ee2016-10-07 13:04:23 -04003024 if (bufSize < 0)
3025 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003026 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003027 return false;
3028 }
3029
Jamie Madilla502c742014-08-28 17:19:13 -04003030 gl::Program *programObject = context->getProgram(program);
3031 ASSERT(programObject);
Jamie Madill0063c512014-08-25 15:47:53 -04003032
Jamie Madill78f41802014-08-25 15:47:55 -04003033 // sized queries -- ensure the provided buffer is large enough
Jamie Madill62d31cb2015-09-11 13:25:51 -04003034 const LinkedUniform &uniform = programObject->getUniformByLocation(location);
He Yunchaoced53ae2016-11-29 15:00:51 +08003035 size_t requiredBytes = VariableExternalSize(uniform.type);
Jamie Madill78f41802014-08-25 15:47:55 -04003036 if (static_cast<size_t>(bufSize) < requiredBytes)
Jamie Madill0063c512014-08-25 15:47:53 -04003037 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003038 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Geoff Langb1196682014-07-23 13:47:29 -04003039 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04003040 }
3041
Geoff Langf41d0ee2016-10-07 13:04:23 -04003042 if (length)
3043 {
Geoff Lang94177fb2016-11-14 16:12:26 -05003044 *length = VariableComponentCount(uniform.type);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003045 }
3046
Jamie Madill0063c512014-08-25 15:47:53 -04003047 return true;
3048}
3049
He Yunchaoced53ae2016-11-29 15:00:51 +08003050bool ValidateGetnUniformfvEXT(Context *context,
3051 GLuint program,
3052 GLint location,
3053 GLsizei bufSize,
3054 GLfloat *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003055{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003056 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
Jamie Madill0063c512014-08-25 15:47:53 -04003057}
3058
He Yunchaoced53ae2016-11-29 15:00:51 +08003059bool ValidateGetnUniformivEXT(Context *context,
3060 GLuint program,
3061 GLint location,
3062 GLsizei bufSize,
3063 GLint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04003064{
Geoff Langf41d0ee2016-10-07 13:04:23 -04003065 return ValidateSizedGetUniform(context, program, location, bufSize, nullptr);
3066}
3067
3068bool ValidateGetUniformfvRobustANGLE(Context *context,
3069 GLuint program,
3070 GLint location,
3071 GLsizei bufSize,
3072 GLsizei *length,
3073 GLfloat *params)
3074{
3075 if (!ValidateRobustEntryPoint(context, bufSize))
3076 {
3077 return false;
3078 }
3079
3080 // bufSize is validated in ValidateSizedGetUniform
3081 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3082}
3083
3084bool ValidateGetUniformivRobustANGLE(Context *context,
3085 GLuint program,
3086 GLint location,
3087 GLsizei bufSize,
3088 GLsizei *length,
3089 GLint *params)
3090{
3091 if (!ValidateRobustEntryPoint(context, bufSize))
3092 {
3093 return false;
3094 }
3095
3096 // bufSize is validated in ValidateSizedGetUniform
3097 return ValidateSizedGetUniform(context, program, location, bufSize, length);
3098}
3099
3100bool ValidateGetUniformuivRobustANGLE(Context *context,
3101 GLuint program,
3102 GLint location,
3103 GLsizei bufSize,
3104 GLsizei *length,
3105 GLuint *params)
3106{
3107 if (!ValidateRobustEntryPoint(context, bufSize))
3108 {
3109 return false;
3110 }
3111
3112 if (context->getClientMajorVersion() < 3)
3113 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003114 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langf41d0ee2016-10-07 13:04:23 -04003115 return false;
3116 }
3117
3118 // bufSize is validated in ValidateSizedGetUniform
3119 return ValidateSizedGetUniform(context, program, location, bufSize, length);
Jamie Madill0063c512014-08-25 15:47:53 -04003120}
3121
He Yunchaoced53ae2016-11-29 15:00:51 +08003122bool ValidateDiscardFramebufferBase(Context *context,
3123 GLenum target,
3124 GLsizei numAttachments,
3125 const GLenum *attachments,
3126 bool defaultFramebuffer)
Austin Kinross08332632015-05-05 13:35:47 -07003127{
3128 if (numAttachments < 0)
3129 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003130 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeAttachments);
Austin Kinross08332632015-05-05 13:35:47 -07003131 return false;
3132 }
3133
3134 for (GLsizei i = 0; i < numAttachments; ++i)
3135 {
Olli Etuaho84c9f592016-03-09 14:37:25 +02003136 if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
Austin Kinross08332632015-05-05 13:35:47 -07003137 {
3138 if (defaultFramebuffer)
3139 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003140 ANGLE_VALIDATION_ERR(context, InvalidEnum(), DefaultFramebufferInvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003141 return false;
3142 }
3143
3144 if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments)
3145 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003146 context->handleError(InvalidOperation() << "Requested color attachment is "
3147 "greater than the maximum supported "
3148 "color attachments");
Austin Kinross08332632015-05-05 13:35:47 -07003149 return false;
3150 }
3151 }
3152 else
3153 {
3154 switch (attachments[i])
3155 {
He Yunchaoced53ae2016-11-29 15:00:51 +08003156 case GL_DEPTH_ATTACHMENT:
3157 case GL_STENCIL_ATTACHMENT:
3158 case GL_DEPTH_STENCIL_ATTACHMENT:
3159 if (defaultFramebuffer)
3160 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003161 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3162 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003163 return false;
3164 }
3165 break;
3166 case GL_COLOR:
3167 case GL_DEPTH:
3168 case GL_STENCIL:
3169 if (!defaultFramebuffer)
3170 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003171 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
3172 DefaultFramebufferInvalidAttachment);
He Yunchaoced53ae2016-11-29 15:00:51 +08003173 return false;
3174 }
3175 break;
3176 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003177 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Austin Kinross08332632015-05-05 13:35:47 -07003178 return false;
Austin Kinross08332632015-05-05 13:35:47 -07003179 }
3180 }
3181 }
3182
3183 return true;
3184}
3185
Austin Kinross6ee1e782015-05-29 17:05:37 -07003186bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker)
3187{
Jamie Madill007530e2017-12-28 14:27:04 -05003188 if (!context->getExtensions().debugMarker)
3189 {
3190 // The debug marker calls should not set error state
3191 // However, it seems reasonable to set an error state if the extension is not enabled
3192 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3193 return false;
3194 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003195
Jamie Madill007530e2017-12-28 14:27:04 -05003196 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003197 if (length < 0)
3198 {
3199 return false;
3200 }
3201
3202 if (marker == nullptr)
3203 {
3204 return false;
3205 }
3206
3207 return true;
3208}
3209
3210bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker)
3211{
Jamie Madill007530e2017-12-28 14:27:04 -05003212 if (!context->getExtensions().debugMarker)
3213 {
3214 // The debug marker calls should not set error state
3215 // However, it seems reasonable to set an error state if the extension is not enabled
3216 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3217 return false;
3218 }
Austin Kinross6ee1e782015-05-29 17:05:37 -07003219
Jamie Madill007530e2017-12-28 14:27:04 -05003220 // Note that debug marker calls must not set error state
Austin Kinross6ee1e782015-05-29 17:05:37 -07003221 if (length < 0)
3222 {
3223 return false;
3224 }
3225
3226 if (length > 0 && marker == nullptr)
3227 {
3228 return false;
3229 }
3230
3231 return true;
3232}
3233
Jamie Madill007530e2017-12-28 14:27:04 -05003234bool ValidateEGLImageTargetTexture2DOES(Context *context, GLenum target, GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003235{
Geoff Langa8406172015-07-21 16:53:39 -04003236 if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal)
3237 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003238 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003239 return false;
3240 }
3241
3242 switch (target)
3243 {
3244 case GL_TEXTURE_2D:
Geoff Langb66a9092016-05-16 15:59:14 -04003245 if (!context->getExtensions().eglImage)
3246 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003247 context->handleError(InvalidEnum()
3248 << "GL_TEXTURE_2D texture target requires GL_OES_EGL_image.");
Geoff Langb66a9092016-05-16 15:59:14 -04003249 }
3250 break;
3251
3252 case GL_TEXTURE_EXTERNAL_OES:
3253 if (!context->getExtensions().eglImageExternal)
3254 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003255 context->handleError(InvalidEnum() << "GL_TEXTURE_EXTERNAL_OES texture target "
3256 "requires GL_OES_EGL_image_external.");
Geoff Langb66a9092016-05-16 15:59:14 -04003257 }
Geoff Langa8406172015-07-21 16:53:39 -04003258 break;
3259
3260 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003261 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003262 return false;
3263 }
3264
Jamie Madill007530e2017-12-28 14:27:04 -05003265 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3266
Jamie Madill61e16b42017-06-19 11:13:23 -04003267 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003268 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003269 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003270 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003271 return false;
3272 }
3273
Jamie Madill007530e2017-12-28 14:27:04 -05003274 if (imageObject->getSamples() > 0)
Geoff Langa8406172015-07-21 16:53:39 -04003275 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003276 context->handleError(InvalidOperation()
3277 << "cannot create a 2D texture from a multisampled EGL image.");
Geoff Langa8406172015-07-21 16:53:39 -04003278 return false;
3279 }
3280
Geoff Langca271392017-04-05 12:30:00 -04003281 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003282 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003283 if (!textureCaps.texturable)
3284 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003285 context->handleError(InvalidOperation()
3286 << "EGL image internal format is not supported as a texture.");
Geoff Langa8406172015-07-21 16:53:39 -04003287 return false;
3288 }
3289
Geoff Langdcab33b2015-07-21 13:03:16 -04003290 return true;
3291}
3292
3293bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
Geoff Langdcab33b2015-07-21 13:03:16 -04003294 GLenum target,
Jamie Madill007530e2017-12-28 14:27:04 -05003295 GLeglImageOES image)
Geoff Langdcab33b2015-07-21 13:03:16 -04003296{
Geoff Langa8406172015-07-21 16:53:39 -04003297 if (!context->getExtensions().eglImage)
3298 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003299 context->handleError(InvalidOperation());
Geoff Langa8406172015-07-21 16:53:39 -04003300 return false;
3301 }
3302
3303 switch (target)
3304 {
3305 case GL_RENDERBUFFER:
3306 break;
3307
3308 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003309 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Geoff Langa8406172015-07-21 16:53:39 -04003310 return false;
3311 }
3312
Jamie Madill007530e2017-12-28 14:27:04 -05003313 egl::Image *imageObject = reinterpret_cast<egl::Image *>(image);
3314
Jamie Madill61e16b42017-06-19 11:13:23 -04003315 ASSERT(context->getCurrentDisplay());
Jamie Madill007530e2017-12-28 14:27:04 -05003316 if (!context->getCurrentDisplay()->isValidImage(imageObject))
Geoff Langa8406172015-07-21 16:53:39 -04003317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003318 context->handleError(InvalidValue() << "EGL image is not valid.");
Geoff Langa8406172015-07-21 16:53:39 -04003319 return false;
3320 }
3321
Geoff Langca271392017-04-05 12:30:00 -04003322 const TextureCaps &textureCaps =
Jamie Madill007530e2017-12-28 14:27:04 -05003323 context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
Geoff Langa8406172015-07-21 16:53:39 -04003324 if (!textureCaps.renderable)
3325 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003326 context->handleError(InvalidOperation()
3327 << "EGL image internal format is not supported as a renderbuffer.");
Geoff Langa8406172015-07-21 16:53:39 -04003328 return false;
3329 }
3330
Geoff Langdcab33b2015-07-21 13:03:16 -04003331 return true;
3332}
Austin Kinrossbc781f32015-10-26 09:27:38 -07003333
3334bool ValidateBindVertexArrayBase(Context *context, GLuint array)
3335{
Geoff Lang36167ab2015-12-07 10:27:14 -05003336 if (!context->isVertexArrayGenerated(array))
Austin Kinrossbc781f32015-10-26 09:27:38 -07003337 {
3338 // The default VAO should always exist
3339 ASSERT(array != 0);
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003340 context->handleError(InvalidOperation());
Austin Kinrossbc781f32015-10-26 09:27:38 -07003341 return false;
3342 }
3343
3344 return true;
3345}
3346
Geoff Langc5629752015-12-07 16:29:04 -05003347bool ValidateProgramBinaryBase(Context *context,
3348 GLuint program,
3349 GLenum binaryFormat,
3350 const void *binary,
3351 GLint length)
3352{
3353 Program *programObject = GetValidProgram(context, program);
3354 if (programObject == nullptr)
3355 {
3356 return false;
3357 }
3358
3359 const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
3360 if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
3361 programBinaryFormats.end())
3362 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003363 context->handleError(InvalidEnum() << "Program binary format is not valid.");
Geoff Langc5629752015-12-07 16:29:04 -05003364 return false;
3365 }
3366
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003367 if (context->hasActiveTransformFeedback(program))
3368 {
3369 // ES 3.0.4 section 2.15 page 91
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003370 context->handleError(InvalidOperation() << "Cannot change program binary while program "
3371 "is associated with an active transform "
3372 "feedback object.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02003373 return false;
3374 }
3375
Geoff Langc5629752015-12-07 16:29:04 -05003376 return true;
3377}
3378
3379bool ValidateGetProgramBinaryBase(Context *context,
3380 GLuint program,
3381 GLsizei bufSize,
3382 GLsizei *length,
3383 GLenum *binaryFormat,
3384 void *binary)
3385{
3386 Program *programObject = GetValidProgram(context, program);
3387 if (programObject == nullptr)
3388 {
3389 return false;
3390 }
3391
3392 if (!programObject->isLinked())
3393 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003394 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
Geoff Langc5629752015-12-07 16:29:04 -05003395 return false;
3396 }
3397
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003398 if (context->getCaps().programBinaryFormats.empty())
3399 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003400 context->handleError(InvalidOperation() << "No program binary formats supported.");
Jamie Madilla7d12dc2016-12-13 15:08:19 -05003401 return false;
3402 }
3403
Geoff Langc5629752015-12-07 16:29:04 -05003404 return true;
3405}
Jamie Madillc29968b2016-01-20 11:17:23 -05003406
Jamie Madillc29968b2016-01-20 11:17:23 -05003407bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs)
3408{
3409 // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
Brandon Jonesafa75152017-07-21 13:11:29 -07003410 if (n < 0)
Jamie Madillc29968b2016-01-20 11:17:23 -05003411 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003412 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3413 return false;
3414 }
3415 if (static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
3416 {
3417 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxDrawBuffer);
Jamie Madillc29968b2016-01-20 11:17:23 -05003418 return false;
3419 }
3420
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003421 ASSERT(context->getGLState().getDrawFramebuffer());
3422 GLuint frameBufferId = context->getGLState().getDrawFramebuffer()->id();
Jamie Madillc29968b2016-01-20 11:17:23 -05003423 GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
3424
3425 // This should come first before the check for the default frame buffer
3426 // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
3427 // rather than INVALID_OPERATION
3428 for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
3429 {
3430 const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
3431
3432 if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
Olli Etuaho84c9f592016-03-09 14:37:25 +02003433 (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
3434 bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
Jamie Madillc29968b2016-01-20 11:17:23 -05003435 {
3436 // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
Olli Etuaho84c9f592016-03-09 14:37:25 +02003437 // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
3438 // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
3439 // 3.1 is still a bit ambiguous about the error, but future specs are
3440 // expected to clarify that GL_INVALID_ENUM is the correct error.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003441 context->handleError(InvalidEnum() << "Invalid buffer value");
Olli Etuaho84c9f592016-03-09 14:37:25 +02003442 return false;
3443 }
3444 else if (bufs[colorAttachment] >= maxColorAttachment)
3445 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003446 context->handleError(InvalidOperation()
3447 << "Buffer value is greater than MAX_DRAW_BUFFERS");
Jamie Madillc29968b2016-01-20 11:17:23 -05003448 return false;
3449 }
3450 else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
3451 frameBufferId != 0)
3452 {
3453 // INVALID_OPERATION-GL is bound to buffer and ith argument
3454 // is not COLOR_ATTACHMENTi or NONE
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003455 context->handleError(InvalidOperation()
3456 << "Ith value does not match COLOR_ATTACHMENTi or NONE");
Jamie Madillc29968b2016-01-20 11:17:23 -05003457 return false;
3458 }
3459 }
3460
3461 // INVALID_OPERATION is generated if GL is bound to the default framebuffer
3462 // and n is not 1 or bufs is bound to value other than BACK and NONE
3463 if (frameBufferId == 0)
3464 {
3465 if (n != 1)
3466 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003467 context->handleError(InvalidOperation()
3468 << "n must be 1 when GL is bound to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003469 return false;
3470 }
3471
3472 if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
3473 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003474 context->handleError(
3475 InvalidOperation()
3476 << "Only NONE or BACK are valid values when drawing to the default framebuffer");
Jamie Madillc29968b2016-01-20 11:17:23 -05003477 return false;
3478 }
3479 }
3480
3481 return true;
3482}
3483
Geoff Lang496c02d2016-10-20 11:38:11 -07003484bool ValidateGetBufferPointervBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003485 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07003486 GLenum pname,
3487 GLsizei *length,
3488 void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03003489{
Geoff Lang496c02d2016-10-20 11:38:11 -07003490 if (length)
3491 {
3492 *length = 0;
3493 }
3494
3495 if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapBuffer)
3496 {
3497 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003498 InvalidOperation()
3499 << "Context does not support OpenGL ES 3.0 or GL_OES_mapbuffer is not enabled.");
Geoff Lang496c02d2016-10-20 11:38:11 -07003500 return false;
3501 }
3502
Corentin Walleze4477002017-12-01 14:39:58 -05003503 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003504 {
Corentin Wallez336129f2017-10-17 15:55:40 -04003505 context->handleError(InvalidEnum() << "Buffer target not valid");
Olli Etuaho4f667482016-03-30 15:56:35 +03003506 return false;
3507 }
3508
Geoff Lang496c02d2016-10-20 11:38:11 -07003509 switch (pname)
Olli Etuaho4f667482016-03-30 15:56:35 +03003510 {
Geoff Lang496c02d2016-10-20 11:38:11 -07003511 case GL_BUFFER_MAP_POINTER:
3512 break;
Olli Etuaho4f667482016-03-30 15:56:35 +03003513
Geoff Lang496c02d2016-10-20 11:38:11 -07003514 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07003515 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Lang496c02d2016-10-20 11:38:11 -07003516 return false;
3517 }
Olli Etuaho4f667482016-03-30 15:56:35 +03003518
3519 // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
3520 // target bound to zero generate an INVALID_OPERATION error."
3521 // GLES 3.1 section 6.6 explicitly specifies this error.
Geoff Lang496c02d2016-10-20 11:38:11 -07003522 if (context->getGLState().getTargetBuffer(target) == nullptr)
Olli Etuaho4f667482016-03-30 15:56:35 +03003523 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003524 context->handleError(InvalidOperation()
3525 << "Can not get pointer for reserved buffer name zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003526 return false;
3527 }
3528
Geoff Lang496c02d2016-10-20 11:38:11 -07003529 if (length)
3530 {
3531 *length = 1;
3532 }
3533
Olli Etuaho4f667482016-03-30 15:56:35 +03003534 return true;
3535}
3536
Corentin Wallez336129f2017-10-17 15:55:40 -04003537bool ValidateUnmapBufferBase(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03003538{
Corentin Walleze4477002017-12-01 14:39:58 -05003539 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003540 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003541 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003542 return false;
3543 }
3544
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003545 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003546
3547 if (buffer == nullptr || !buffer->isMapped())
3548 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003549 context->handleError(InvalidOperation() << "Buffer not mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003550 return false;
3551 }
3552
3553 return true;
3554}
3555
3556bool ValidateMapBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003557 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003558 GLintptr offset,
3559 GLsizeiptr length,
3560 GLbitfield access)
3561{
Corentin Walleze4477002017-12-01 14:39:58 -05003562 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003563 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003564 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003565 return false;
3566 }
3567
Brandon Jones6cad5662017-06-14 13:25:13 -07003568 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003569 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003570 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3571 return false;
3572 }
3573
3574 if (length < 0)
3575 {
3576 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003577 return false;
3578 }
3579
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003580 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003581
3582 if (!buffer)
3583 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003584 context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003585 return false;
3586 }
3587
3588 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003589 CheckedNumeric<size_t> checkedOffset(offset);
3590 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003591
Jamie Madille2e406c2016-06-02 13:04:10 -04003592 if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003593 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003594 context->handleError(InvalidValue() << "Mapped range does not fit into buffer dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003595 return false;
3596 }
3597
3598 // Check for invalid bits in the mask
3599 GLbitfield allAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
3600 GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT |
3601 GL_MAP_UNSYNCHRONIZED_BIT;
3602
3603 if (access & ~(allAccessBits))
3604 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003605 context->handleError(InvalidValue()
3606 << "Invalid access bits: 0x" << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003607 return false;
3608 }
3609
3610 if (length == 0)
3611 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003612 context->handleError(InvalidOperation() << "Buffer mapping length is zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003613 return false;
3614 }
3615
3616 if (buffer->isMapped())
3617 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003618 context->handleError(InvalidOperation() << "Buffer is already mapped.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003619 return false;
3620 }
3621
3622 // Check for invalid bit combinations
3623 if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
3624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003625 context->handleError(InvalidOperation()
3626 << "Need to map buffer for either reading or writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003627 return false;
3628 }
3629
3630 GLbitfield writeOnlyBits =
3631 GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
3632
3633 if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
3634 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003635 context->handleError(InvalidOperation()
3636 << "Invalid access bits when mapping buffer for reading: 0x"
3637 << std::hex << std::uppercase << access);
Olli Etuaho4f667482016-03-30 15:56:35 +03003638 return false;
3639 }
3640
3641 if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
3642 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003643 context->handleError(
3644 InvalidOperation()
3645 << "The explicit flushing bit may only be set if the buffer is mapped for writing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003646 return false;
3647 }
Geoff Lang79f71042017-08-14 16:43:43 -04003648
3649 return ValidateMapBufferBase(context, target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003650}
3651
3652bool ValidateFlushMappedBufferRangeBase(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04003653 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03003654 GLintptr offset,
3655 GLsizeiptr length)
3656{
Brandon Jones6cad5662017-06-14 13:25:13 -07003657 if (offset < 0)
Olli Etuaho4f667482016-03-30 15:56:35 +03003658 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003659 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
3660 return false;
3661 }
3662
3663 if (length < 0)
3664 {
3665 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeLength);
Olli Etuaho4f667482016-03-30 15:56:35 +03003666 return false;
3667 }
3668
Corentin Walleze4477002017-12-01 14:39:58 -05003669 if (!context->isValidBufferBinding(target))
Olli Etuaho4f667482016-03-30 15:56:35 +03003670 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003671 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Olli Etuaho4f667482016-03-30 15:56:35 +03003672 return false;
3673 }
3674
Jamie Madilldfde6ab2016-06-09 07:07:18 -07003675 Buffer *buffer = context->getGLState().getTargetBuffer(target);
Olli Etuaho4f667482016-03-30 15:56:35 +03003676
3677 if (buffer == nullptr)
3678 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003679 context->handleError(InvalidOperation() << "Attempted to flush buffer object zero.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003680 return false;
3681 }
3682
3683 if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
3684 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003685 context->handleError(InvalidOperation()
3686 << "Attempted to flush a buffer not mapped for explicit flushing.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003687 return false;
3688 }
3689
3690 // Check for buffer overflow
Jamie Madille2e406c2016-06-02 13:04:10 -04003691 CheckedNumeric<size_t> checkedOffset(offset);
3692 auto checkedSize = checkedOffset + length;
Olli Etuaho4f667482016-03-30 15:56:35 +03003693
Jamie Madille2e406c2016-06-02 13:04:10 -04003694 if (!checkedSize.IsValid() ||
3695 checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
Olli Etuaho4f667482016-03-30 15:56:35 +03003696 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003697 context->handleError(InvalidValue()
3698 << "Flushed range does not fit into buffer mapping dimensions.");
Olli Etuaho4f667482016-03-30 15:56:35 +03003699 return false;
3700 }
3701
3702 return true;
3703}
3704
Olli Etuaho41997e72016-03-10 13:38:39 +02003705bool ValidateGenOrDelete(Context *context, GLint n)
3706{
3707 if (n < 0)
3708 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003709 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
Olli Etuaho41997e72016-03-10 13:38:39 +02003710 return false;
3711 }
3712 return true;
3713}
3714
Geoff Langff5b2d52016-09-07 11:32:23 -04003715bool ValidateRobustEntryPoint(ValidationContext *context, GLsizei bufSize)
3716{
3717 if (!context->getExtensions().robustClientMemory)
3718 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003719 context->handleError(InvalidOperation()
3720 << "GL_ANGLE_robust_client_memory is not available.");
Geoff Langff5b2d52016-09-07 11:32:23 -04003721 return false;
3722 }
3723
3724 if (bufSize < 0)
3725 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003726 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Langff5b2d52016-09-07 11:32:23 -04003727 return false;
3728 }
3729
3730 return true;
3731}
3732
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003733bool ValidateRobustBufferSize(ValidationContext *context, GLsizei bufSize, GLsizei numParams)
3734{
3735 if (bufSize < numParams)
3736 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003737 context->handleError(InvalidOperation() << numParams << " parameters are required but "
3738 << bufSize << " were provided.");
Geoff Lang2e43dbb2016-10-14 12:27:35 -04003739 return false;
3740 }
3741
3742 return true;
3743}
3744
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003745bool ValidateGetFramebufferAttachmentParameterivBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04003746 GLenum target,
3747 GLenum attachment,
3748 GLenum pname,
3749 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04003750{
Geoff Lange8afa902017-09-27 15:00:43 -04003751 if (!ValidFramebufferTarget(context, target))
Geoff Langff5b2d52016-09-07 11:32:23 -04003752 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003753 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003754 return false;
3755 }
3756
3757 int clientVersion = context->getClientMajorVersion();
3758
3759 switch (pname)
3760 {
3761 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3762 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3763 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3764 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3765 break;
3766
Martin Radeve5285d22017-07-14 16:23:53 +03003767 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_ANGLE:
3768 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_MULTIVIEW_LAYOUT_ANGLE:
3769 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_ANGLE:
3770 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE:
3771 if (clientVersion < 3 || !context->getExtensions().multiview)
3772 {
3773 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3774 return false;
3775 }
3776 break;
3777
Geoff Langff5b2d52016-09-07 11:32:23 -04003778 case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
3779 if (clientVersion < 3 && !context->getExtensions().sRGB)
3780 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003781 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003782 return false;
3783 }
3784 break;
3785
3786 case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
3787 case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
3788 case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
3789 case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
3790 case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
3791 case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
3792 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3793 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3794 if (clientVersion < 3)
3795 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003796 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003797 return false;
3798 }
3799 break;
3800
3801 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003802 context->handleError(InvalidEnum());
Geoff Langff5b2d52016-09-07 11:32:23 -04003803 return false;
3804 }
3805
3806 // Determine if the attachment is a valid enum
3807 switch (attachment)
3808 {
3809 case GL_BACK:
Geoff Langff5b2d52016-09-07 11:32:23 -04003810 case GL_DEPTH:
3811 case GL_STENCIL:
Geoff Langff5b2d52016-09-07 11:32:23 -04003812 if (clientVersion < 3)
3813 {
Geoff Langfa125c92017-10-24 13:01:46 -04003814 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003815 return false;
3816 }
3817 break;
3818
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003819 case GL_DEPTH_STENCIL_ATTACHMENT:
3820 if (clientVersion < 3 && !context->isWebGL1())
3821 {
3822 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
3823 return false;
3824 }
3825 break;
3826
Geoff Langfa125c92017-10-24 13:01:46 -04003827 case GL_COLOR_ATTACHMENT0:
Geoff Langff5b2d52016-09-07 11:32:23 -04003828 case GL_DEPTH_ATTACHMENT:
3829 case GL_STENCIL_ATTACHMENT:
3830 break;
3831
3832 default:
Geoff Langfa125c92017-10-24 13:01:46 -04003833 if ((clientVersion < 3 && !context->getExtensions().drawBuffers) ||
3834 attachment < GL_COLOR_ATTACHMENT0_EXT ||
Geoff Langff5b2d52016-09-07 11:32:23 -04003835 (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
3836 {
Geoff Langfa125c92017-10-24 13:01:46 -04003837 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003838 return false;
3839 }
3840 break;
3841 }
3842
3843 const Framebuffer *framebuffer = context->getGLState().getTargetFramebuffer(target);
3844 ASSERT(framebuffer);
3845
3846 if (framebuffer->id() == 0)
3847 {
3848 if (clientVersion < 3)
3849 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003850 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DefaultFramebufferTarget);
Geoff Langff5b2d52016-09-07 11:32:23 -04003851 return false;
3852 }
3853
3854 switch (attachment)
3855 {
3856 case GL_BACK:
3857 case GL_DEPTH:
3858 case GL_STENCIL:
3859 break;
3860
3861 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003862 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003863 return false;
3864 }
3865 }
3866 else
3867 {
3868 if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
3869 {
3870 // Valid attachment query
3871 }
3872 else
3873 {
3874 switch (attachment)
3875 {
3876 case GL_DEPTH_ATTACHMENT:
3877 case GL_STENCIL_ATTACHMENT:
3878 break;
3879
3880 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003881 if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
Geoff Langff5b2d52016-09-07 11:32:23 -04003882 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003883 context->handleError(InvalidOperation());
Geoff Langff5b2d52016-09-07 11:32:23 -04003884 return false;
3885 }
3886 break;
3887
3888 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003889 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003890 return false;
3891 }
3892 }
3893 }
3894
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08003895 const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003896 if (attachmentObject)
3897 {
3898 ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
3899 attachmentObject->type() == GL_TEXTURE ||
3900 attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
3901
3902 switch (pname)
3903 {
3904 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3905 if (attachmentObject->type() != GL_RENDERBUFFER &&
3906 attachmentObject->type() != GL_TEXTURE)
3907 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003908 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003909 return false;
3910 }
3911 break;
3912
3913 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
3914 if (attachmentObject->type() != GL_TEXTURE)
3915 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003916 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003917 return false;
3918 }
3919 break;
3920
3921 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
3922 if (attachmentObject->type() != GL_TEXTURE)
3923 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003924 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003925 return false;
3926 }
3927 break;
3928
3929 case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
3930 if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
3931 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003932 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003933 return false;
3934 }
3935 break;
3936
3937 case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
3938 if (attachmentObject->type() != GL_TEXTURE)
3939 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003940 ANGLE_VALIDATION_ERR(context, InvalidEnum(), FramebufferIncompleteAttachment);
Geoff Langff5b2d52016-09-07 11:32:23 -04003941 return false;
3942 }
3943 break;
3944
3945 default:
3946 break;
3947 }
3948 }
3949 else
3950 {
3951 // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
3952 // is NONE, then querying any other pname will generate INVALID_ENUM.
3953
3954 // ES 3.0.2 spec pg 235 states that if the attachment type is none,
3955 // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
3956 // INVALID_OPERATION for all other pnames
3957
3958 switch (pname)
3959 {
3960 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
3961 break;
3962
3963 case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
3964 if (clientVersion < 3)
3965 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003966 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003967 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003968 return false;
3969 }
3970 break;
3971
3972 default:
3973 if (clientVersion < 3)
3974 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003975 ANGLE_VALIDATION_ERR(context, InvalidEnum(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003976 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003977 return false;
3978 }
3979 else
3980 {
Brandon Jones6cad5662017-06-14 13:25:13 -07003981 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
Bryan Bernhart (Intel Americas Inc)491b0d62017-11-10 12:48:22 -08003982 InvalidFramebufferAttachmentParameter);
Geoff Langff5b2d52016-09-07 11:32:23 -04003983 return false;
3984 }
3985 }
3986 }
3987
Martin Radeve5285d22017-07-14 16:23:53 +03003988 if (numParams)
3989 {
3990 if (pname == GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_VIEWPORT_OFFSETS_ANGLE)
3991 {
3992 // Only when the viewport offsets are queried we can have a varying number of output
3993 // parameters.
3994 const int numViews = attachmentObject ? attachmentObject->getNumViews() : 1;
3995 *numParams = numViews * 2;
3996 }
3997 else
3998 {
3999 // For all other queries we can have only one output parameter.
4000 *numParams = 1;
4001 }
4002 }
4003
Geoff Langff5b2d52016-09-07 11:32:23 -04004004 return true;
4005}
4006
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -08004007bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(Context *context,
Geoff Langff5b2d52016-09-07 11:32:23 -04004008 GLenum target,
4009 GLenum attachment,
4010 GLenum pname,
4011 GLsizei bufSize,
4012 GLsizei *numParams)
4013{
4014 if (!ValidateRobustEntryPoint(context, bufSize))
4015 {
4016 return false;
4017 }
4018
Jamie Madillbe849e42017-05-02 15:49:00 -04004019 if (!ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
4020 numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004021 {
4022 return false;
4023 }
4024
4025 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4026 {
4027 return false;
4028 }
4029
4030 return true;
4031}
4032
Geoff Langff5b2d52016-09-07 11:32:23 -04004033bool ValidateGetBufferParameterivRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004034 BufferBinding target,
Geoff Langff5b2d52016-09-07 11:32:23 -04004035 GLenum pname,
4036 GLsizei bufSize,
Geoff Langebebe1c2016-10-14 12:01:31 -04004037 GLsizei *length,
4038 GLint *params)
Geoff Langff5b2d52016-09-07 11:32:23 -04004039{
4040 if (!ValidateRobustEntryPoint(context, bufSize))
4041 {
4042 return false;
4043 }
4044
Geoff Langebebe1c2016-10-14 12:01:31 -04004045 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004046 {
4047 return false;
4048 }
4049
Geoff Langebebe1c2016-10-14 12:01:31 -04004050 if (!ValidateRobustBufferSize(context, bufSize, *length))
4051 {
4052 return false;
4053 }
4054
4055 return true;
4056}
4057
Geoff Langebebe1c2016-10-14 12:01:31 -04004058bool ValidateGetBufferParameteri64vRobustANGLE(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004059 BufferBinding target,
Geoff Langebebe1c2016-10-14 12:01:31 -04004060 GLenum pname,
4061 GLsizei bufSize,
4062 GLsizei *length,
4063 GLint64 *params)
4064{
4065 if (!ValidateRobustEntryPoint(context, bufSize))
4066 {
4067 return false;
4068 }
4069
4070 if (!ValidateGetBufferParameterBase(context, target, pname, false, length))
4071 {
4072 return false;
4073 }
4074
4075 if (!ValidateRobustBufferSize(context, bufSize, *length))
Geoff Langff5b2d52016-09-07 11:32:23 -04004076 {
4077 return false;
4078 }
4079
4080 return true;
4081}
4082
Jamie Madillbe849e42017-05-02 15:49:00 -04004083bool ValidateGetProgramivBase(ValidationContext *context,
4084 GLuint program,
4085 GLenum pname,
4086 GLsizei *numParams)
Geoff Langff5b2d52016-09-07 11:32:23 -04004087{
4088 // Currently, all GetProgramiv queries return 1 parameter
Yunchao He33151a52017-04-13 09:58:17 +08004089 if (numParams)
4090 {
4091 *numParams = 1;
4092 }
Geoff Langff5b2d52016-09-07 11:32:23 -04004093
4094 Program *programObject = GetValidProgram(context, program);
4095 if (!programObject)
4096 {
4097 return false;
4098 }
4099
4100 switch (pname)
4101 {
4102 case GL_DELETE_STATUS:
4103 case GL_LINK_STATUS:
4104 case GL_VALIDATE_STATUS:
4105 case GL_INFO_LOG_LENGTH:
4106 case GL_ATTACHED_SHADERS:
4107 case GL_ACTIVE_ATTRIBUTES:
4108 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
4109 case GL_ACTIVE_UNIFORMS:
4110 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
4111 break;
4112
4113 case GL_PROGRAM_BINARY_LENGTH:
4114 if (context->getClientMajorVersion() < 3 && !context->getExtensions().getProgramBinary)
4115 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004116 context->handleError(InvalidEnum() << "Querying GL_PROGRAM_BINARY_LENGTH "
4117 "requires GL_OES_get_program_binary or "
4118 "ES 3.0.");
Geoff Langff5b2d52016-09-07 11:32:23 -04004119 return false;
4120 }
4121 break;
4122
4123 case GL_ACTIVE_UNIFORM_BLOCKS:
4124 case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
4125 case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
4126 case GL_TRANSFORM_FEEDBACK_VARYINGS:
4127 case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
4128 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
4129 if (context->getClientMajorVersion() < 3)
4130 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004131 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Geoff Langff5b2d52016-09-07 11:32:23 -04004132 return false;
4133 }
4134 break;
4135
Yunchao He61afff12017-03-14 15:34:03 +08004136 case GL_PROGRAM_SEPARABLE:
Xinghua Cao971f8502017-10-17 13:01:24 +08004137 case GL_COMPUTE_WORK_GROUP_SIZE:
jchen1058f67be2017-10-27 08:59:27 +08004138 case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
Yunchao He61afff12017-03-14 15:34:03 +08004139 if (context->getClientVersion() < Version(3, 1))
4140 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08004141 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
Yunchao He61afff12017-03-14 15:34:03 +08004142 return false;
4143 }
4144 break;
4145
Geoff Langff5b2d52016-09-07 11:32:23 -04004146 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004147 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Geoff Langff5b2d52016-09-07 11:32:23 -04004148 return false;
4149 }
4150
4151 return true;
4152}
4153
4154bool ValidateGetProgramivRobustANGLE(Context *context,
4155 GLuint program,
4156 GLenum pname,
4157 GLsizei bufSize,
4158 GLsizei *numParams)
4159{
4160 if (!ValidateRobustEntryPoint(context, bufSize))
4161 {
4162 return false;
4163 }
4164
Jamie Madillbe849e42017-05-02 15:49:00 -04004165 if (!ValidateGetProgramivBase(context, program, pname, numParams))
Geoff Langff5b2d52016-09-07 11:32:23 -04004166 {
4167 return false;
4168 }
4169
4170 if (!ValidateRobustBufferSize(context, bufSize, *numParams))
4171 {
4172 return false;
4173 }
4174
4175 return true;
4176}
4177
Geoff Lang740d9022016-10-07 11:20:52 -04004178bool ValidateGetRenderbufferParameterivRobustANGLE(Context *context,
4179 GLenum target,
4180 GLenum pname,
4181 GLsizei bufSize,
4182 GLsizei *length,
4183 GLint *params)
4184{
4185 if (!ValidateRobustEntryPoint(context, bufSize))
4186 {
4187 return false;
4188 }
4189
4190 if (!ValidateGetRenderbufferParameterivBase(context, target, pname, length))
4191 {
4192 return false;
4193 }
4194
4195 if (!ValidateRobustBufferSize(context, bufSize, *length))
4196 {
4197 return false;
4198 }
4199
4200 return true;
4201}
4202
Geoff Langd7d0ed32016-10-07 11:33:51 -04004203bool ValidateGetShaderivRobustANGLE(Context *context,
4204 GLuint shader,
4205 GLenum pname,
4206 GLsizei bufSize,
4207 GLsizei *length,
4208 GLint *params)
4209{
4210 if (!ValidateRobustEntryPoint(context, bufSize))
4211 {
4212 return false;
4213 }
4214
4215 if (!ValidateGetShaderivBase(context, shader, pname, length))
4216 {
4217 return false;
4218 }
4219
4220 if (!ValidateRobustBufferSize(context, bufSize, *length))
4221 {
4222 return false;
4223 }
4224
4225 return true;
4226}
4227
Geoff Langc1984ed2016-10-07 12:41:00 -04004228bool ValidateGetTexParameterfvRobustANGLE(Context *context,
4229 GLenum target,
4230 GLenum pname,
4231 GLsizei bufSize,
4232 GLsizei *length,
4233 GLfloat *params)
4234{
4235 if (!ValidateRobustEntryPoint(context, bufSize))
4236 {
4237 return false;
4238 }
4239
4240 if (!ValidateGetTexParameterBase(context, target, pname, length))
4241 {
4242 return false;
4243 }
4244
4245 if (!ValidateRobustBufferSize(context, bufSize, *length))
4246 {
4247 return false;
4248 }
4249
4250 return true;
4251}
4252
Geoff Langc1984ed2016-10-07 12:41:00 -04004253bool ValidateGetTexParameterivRobustANGLE(Context *context,
4254 GLenum target,
4255 GLenum pname,
4256 GLsizei bufSize,
4257 GLsizei *length,
4258 GLint *params)
4259{
4260 if (!ValidateRobustEntryPoint(context, bufSize))
4261 {
4262 return false;
4263 }
4264
4265 if (!ValidateGetTexParameterBase(context, target, pname, length))
4266 {
4267 return false;
4268 }
4269
4270 if (!ValidateRobustBufferSize(context, bufSize, *length))
4271 {
4272 return false;
4273 }
4274
4275 return true;
4276}
4277
Geoff Langc1984ed2016-10-07 12:41:00 -04004278bool ValidateTexParameterfvRobustANGLE(Context *context,
4279 GLenum target,
4280 GLenum pname,
4281 GLsizei bufSize,
4282 const GLfloat *params)
4283{
4284 if (!ValidateRobustEntryPoint(context, bufSize))
4285 {
4286 return false;
4287 }
4288
4289 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4290}
4291
Geoff Langc1984ed2016-10-07 12:41:00 -04004292bool ValidateTexParameterivRobustANGLE(Context *context,
4293 GLenum target,
4294 GLenum pname,
4295 GLsizei bufSize,
4296 const GLint *params)
4297{
4298 if (!ValidateRobustEntryPoint(context, bufSize))
4299 {
4300 return false;
4301 }
4302
4303 return ValidateTexParameterBase(context, target, pname, bufSize, params);
4304}
4305
Geoff Langc1984ed2016-10-07 12:41:00 -04004306bool ValidateGetSamplerParameterfvRobustANGLE(Context *context,
4307 GLuint sampler,
4308 GLenum pname,
4309 GLuint bufSize,
4310 GLsizei *length,
4311 GLfloat *params)
4312{
4313 if (!ValidateRobustEntryPoint(context, bufSize))
4314 {
4315 return false;
4316 }
4317
4318 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4319 {
4320 return false;
4321 }
4322
4323 if (!ValidateRobustBufferSize(context, bufSize, *length))
4324 {
4325 return false;
4326 }
4327
4328 return true;
4329}
4330
Geoff Langc1984ed2016-10-07 12:41:00 -04004331bool ValidateGetSamplerParameterivRobustANGLE(Context *context,
4332 GLuint sampler,
4333 GLenum pname,
4334 GLuint bufSize,
4335 GLsizei *length,
4336 GLint *params)
4337{
4338 if (!ValidateRobustEntryPoint(context, bufSize))
4339 {
4340 return false;
4341 }
4342
4343 if (!ValidateGetSamplerParameterBase(context, sampler, pname, length))
4344 {
4345 return false;
4346 }
4347
4348 if (!ValidateRobustBufferSize(context, bufSize, *length))
4349 {
4350 return false;
4351 }
4352
4353 return true;
4354}
4355
Geoff Langc1984ed2016-10-07 12:41:00 -04004356bool ValidateSamplerParameterfvRobustANGLE(Context *context,
4357 GLuint sampler,
4358 GLenum pname,
4359 GLsizei bufSize,
4360 const GLfloat *params)
4361{
4362 if (!ValidateRobustEntryPoint(context, bufSize))
4363 {
4364 return false;
4365 }
4366
4367 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4368}
4369
Geoff Langc1984ed2016-10-07 12:41:00 -04004370bool ValidateSamplerParameterivRobustANGLE(Context *context,
4371 GLuint sampler,
4372 GLenum pname,
4373 GLsizei bufSize,
4374 const GLint *params)
4375{
4376 if (!ValidateRobustEntryPoint(context, bufSize))
4377 {
4378 return false;
4379 }
4380
4381 return ValidateSamplerParameterBase(context, sampler, pname, bufSize, params);
4382}
4383
Geoff Lang0b031062016-10-13 14:30:04 -04004384bool ValidateGetVertexAttribfvRobustANGLE(Context *context,
4385 GLuint index,
4386 GLenum pname,
4387 GLsizei bufSize,
4388 GLsizei *length,
4389 GLfloat *params)
4390{
4391 if (!ValidateRobustEntryPoint(context, bufSize))
4392 {
4393 return false;
4394 }
4395
4396 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4397 {
4398 return false;
4399 }
4400
4401 if (!ValidateRobustBufferSize(context, bufSize, *length))
4402 {
4403 return false;
4404 }
4405
4406 return true;
4407}
4408
Geoff Lang0b031062016-10-13 14:30:04 -04004409bool ValidateGetVertexAttribivRobustANGLE(Context *context,
4410 GLuint index,
4411 GLenum pname,
4412 GLsizei bufSize,
4413 GLsizei *length,
4414 GLint *params)
4415{
4416 if (!ValidateRobustEntryPoint(context, bufSize))
4417 {
4418 return false;
4419 }
4420
4421 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, false))
4422 {
4423 return false;
4424 }
4425
4426 if (!ValidateRobustBufferSize(context, bufSize, *length))
4427 {
4428 return false;
4429 }
4430
4431 return true;
4432}
4433
Geoff Lang0b031062016-10-13 14:30:04 -04004434bool ValidateGetVertexAttribPointervRobustANGLE(Context *context,
4435 GLuint index,
4436 GLenum pname,
4437 GLsizei bufSize,
4438 GLsizei *length,
4439 void **pointer)
4440{
4441 if (!ValidateRobustEntryPoint(context, bufSize))
4442 {
4443 return false;
4444 }
4445
4446 if (!ValidateGetVertexAttribBase(context, index, pname, length, true, false))
4447 {
4448 return false;
4449 }
4450
4451 if (!ValidateRobustBufferSize(context, bufSize, *length))
4452 {
4453 return false;
4454 }
4455
4456 return true;
4457}
4458
Geoff Lang0b031062016-10-13 14:30:04 -04004459bool ValidateGetVertexAttribIivRobustANGLE(Context *context,
4460 GLuint index,
4461 GLenum pname,
4462 GLsizei bufSize,
4463 GLsizei *length,
4464 GLint *params)
4465{
4466 if (!ValidateRobustEntryPoint(context, bufSize))
4467 {
4468 return false;
4469 }
4470
4471 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4472 {
4473 return false;
4474 }
4475
4476 if (!ValidateRobustBufferSize(context, bufSize, *length))
4477 {
4478 return false;
4479 }
4480
4481 return true;
4482}
4483
Geoff Lang0b031062016-10-13 14:30:04 -04004484bool ValidateGetVertexAttribIuivRobustANGLE(Context *context,
4485 GLuint index,
4486 GLenum pname,
4487 GLsizei bufSize,
4488 GLsizei *length,
4489 GLuint *params)
4490{
4491 if (!ValidateRobustEntryPoint(context, bufSize))
4492 {
4493 return false;
4494 }
4495
4496 if (!ValidateGetVertexAttribBase(context, index, pname, length, false, true))
4497 {
4498 return false;
4499 }
4500
4501 if (!ValidateRobustBufferSize(context, bufSize, *length))
4502 {
4503 return false;
4504 }
4505
4506 return true;
4507}
4508
Geoff Lang6899b872016-10-14 11:30:13 -04004509bool ValidateGetActiveUniformBlockivRobustANGLE(Context *context,
4510 GLuint program,
4511 GLuint uniformBlockIndex,
4512 GLenum pname,
4513 GLsizei bufSize,
4514 GLsizei *length,
4515 GLint *params)
4516{
4517 if (!ValidateRobustEntryPoint(context, bufSize))
4518 {
4519 return false;
4520 }
4521
4522 if (!ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, length))
4523 {
4524 return false;
4525 }
4526
4527 if (!ValidateRobustBufferSize(context, bufSize, *length))
4528 {
4529 return false;
4530 }
4531
4532 return true;
4533}
4534
Geoff Lang0a9661f2016-10-20 10:59:20 -07004535bool ValidateGetInternalFormativRobustANGLE(Context *context,
4536 GLenum target,
4537 GLenum internalformat,
4538 GLenum pname,
4539 GLsizei bufSize,
4540 GLsizei *length,
4541 GLint *params)
4542{
4543 if (!ValidateRobustEntryPoint(context, bufSize))
4544 {
4545 return false;
4546 }
4547
4548 if (!ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize, length))
4549 {
4550 return false;
4551 }
4552
4553 if (!ValidateRobustBufferSize(context, bufSize, *length))
4554 {
4555 return false;
4556 }
4557
4558 return true;
4559}
4560
Shao80957d92017-02-20 21:25:59 +08004561bool ValidateVertexFormatBase(ValidationContext *context,
4562 GLuint attribIndex,
4563 GLint size,
4564 GLenum type,
4565 GLboolean pureInteger)
4566{
4567 const Caps &caps = context->getCaps();
4568 if (attribIndex >= caps.maxVertexAttributes)
4569 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004570 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Shao80957d92017-02-20 21:25:59 +08004571 return false;
4572 }
4573
4574 if (size < 1 || size > 4)
4575 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004576 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidVertexAttrSize);
Geoff Lang8700a982017-06-13 10:15:13 -04004577 return false;
Shao80957d92017-02-20 21:25:59 +08004578 }
4579
4580 switch (type)
4581 {
4582 case GL_BYTE:
4583 case GL_UNSIGNED_BYTE:
4584 case GL_SHORT:
4585 case GL_UNSIGNED_SHORT:
4586 break;
4587
4588 case GL_INT:
4589 case GL_UNSIGNED_INT:
4590 if (context->getClientMajorVersion() < 3)
4591 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004592 context->handleError(InvalidEnum()
4593 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004594 return false;
4595 }
4596 break;
4597
4598 case GL_FIXED:
4599 case GL_FLOAT:
4600 if (pureInteger)
4601 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004602 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004603 return false;
4604 }
4605 break;
4606
4607 case GL_HALF_FLOAT:
4608 if (context->getClientMajorVersion() < 3)
4609 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004610 context->handleError(InvalidEnum()
4611 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004612 return false;
4613 }
4614 if (pureInteger)
4615 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004616 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004617 return false;
4618 }
4619 break;
4620
4621 case GL_INT_2_10_10_10_REV:
4622 case GL_UNSIGNED_INT_2_10_10_10_REV:
4623 if (context->getClientMajorVersion() < 3)
4624 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004625 context->handleError(InvalidEnum()
4626 << "Vertex type not supported before OpenGL ES 3.0.");
Shao80957d92017-02-20 21:25:59 +08004627 return false;
4628 }
4629 if (pureInteger)
4630 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004631 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTypePureInt);
Shao80957d92017-02-20 21:25:59 +08004632 return false;
4633 }
4634 if (size != 4)
4635 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004636 context->handleError(InvalidOperation() << "Type is INT_2_10_10_10_REV or "
4637 "UNSIGNED_INT_2_10_10_10_REV and "
4638 "size is not 4.");
Shao80957d92017-02-20 21:25:59 +08004639 return false;
4640 }
4641 break;
4642
4643 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004644 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Shao80957d92017-02-20 21:25:59 +08004645 return false;
4646 }
4647
4648 return true;
4649}
4650
Geoff Lang76e65652017-03-27 14:58:02 -04004651// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
4652// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
4653// specified clear value and the type of a buffer that is being cleared generates an
4654// INVALID_OPERATION error instead of producing undefined results
4655bool ValidateWebGLFramebufferAttachmentClearType(ValidationContext *context,
4656 GLint drawbuffer,
4657 const GLenum *validComponentTypes,
4658 size_t validComponentTypeCount)
4659{
4660 const FramebufferAttachment *attachment =
4661 context->getGLState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
4662 if (attachment)
4663 {
4664 GLenum componentType = attachment->getFormat().info->componentType;
4665 const GLenum *end = validComponentTypes + validComponentTypeCount;
4666 if (std::find(validComponentTypes, end, componentType) == end)
4667 {
4668 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004669 InvalidOperation()
4670 << "No defined conversion between clear value and attachment format.");
Geoff Lang76e65652017-03-27 14:58:02 -04004671 return false;
4672 }
4673 }
4674
4675 return true;
4676}
4677
Corentin Wallezb2931602017-04-11 15:58:57 -04004678bool ValidateRobustCompressedTexImageBase(ValidationContext *context,
4679 GLsizei imageSize,
4680 GLsizei dataSize)
4681{
4682 if (!ValidateRobustEntryPoint(context, dataSize))
4683 {
4684 return false;
4685 }
4686
Corentin Wallez336129f2017-10-17 15:55:40 -04004687 gl::Buffer *pixelUnpackBuffer =
4688 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezb2931602017-04-11 15:58:57 -04004689 if (pixelUnpackBuffer == nullptr)
4690 {
4691 if (dataSize < imageSize)
4692 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004693 context->handleError(InvalidOperation() << "dataSize must be at least " << imageSize);
Corentin Wallezb2931602017-04-11 15:58:57 -04004694 }
4695 }
4696 return true;
4697}
4698
Jamie Madillbe849e42017-05-02 15:49:00 -04004699bool ValidateGetBufferParameterBase(ValidationContext *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004700 BufferBinding target,
Jamie Madillbe849e42017-05-02 15:49:00 -04004701 GLenum pname,
4702 bool pointerVersion,
4703 GLsizei *numParams)
4704{
4705 if (numParams)
4706 {
4707 *numParams = 0;
4708 }
4709
Corentin Walleze4477002017-12-01 14:39:58 -05004710 if (!context->isValidBufferBinding(target))
Jamie Madillbe849e42017-05-02 15:49:00 -04004711 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004712 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
Jamie Madillbe849e42017-05-02 15:49:00 -04004713 return false;
4714 }
4715
4716 const Buffer *buffer = context->getGLState().getTargetBuffer(target);
4717 if (!buffer)
4718 {
4719 // A null buffer means that "0" is bound to the requested buffer target
Brandon Jones6cad5662017-06-14 13:25:13 -07004720 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004721 return false;
4722 }
4723
4724 const Extensions &extensions = context->getExtensions();
4725
4726 switch (pname)
4727 {
4728 case GL_BUFFER_USAGE:
4729 case GL_BUFFER_SIZE:
4730 break;
4731
4732 case GL_BUFFER_ACCESS_OES:
4733 if (!extensions.mapBuffer)
4734 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004735 context->handleError(InvalidEnum()
4736 << "pname requires OpenGL ES 3.0 or GL_OES_mapbuffer.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004737 return false;
4738 }
4739 break;
4740
4741 case GL_BUFFER_MAPPED:
4742 static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
4743 if (context->getClientMajorVersion() < 3 && !extensions.mapBuffer &&
4744 !extensions.mapBufferRange)
4745 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004746 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0, "
4747 "GL_OES_mapbuffer or "
4748 "GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004749 return false;
4750 }
4751 break;
4752
4753 case GL_BUFFER_MAP_POINTER:
4754 if (!pointerVersion)
4755 {
4756 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004757 InvalidEnum()
4758 << "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004759 return false;
4760 }
4761 break;
4762
4763 case GL_BUFFER_ACCESS_FLAGS:
4764 case GL_BUFFER_MAP_OFFSET:
4765 case GL_BUFFER_MAP_LENGTH:
4766 if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRange)
4767 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004768 context->handleError(InvalidEnum()
4769 << "pname requires OpenGL ES 3.0 or GL_EXT_map_buffer_range.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004770 return false;
4771 }
4772 break;
4773
4774 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004775 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004776 return false;
4777 }
4778
4779 // All buffer parameter queries return one value.
4780 if (numParams)
4781 {
4782 *numParams = 1;
4783 }
4784
4785 return true;
4786}
4787
4788bool ValidateGetRenderbufferParameterivBase(Context *context,
4789 GLenum target,
4790 GLenum pname,
4791 GLsizei *length)
4792{
4793 if (length)
4794 {
4795 *length = 0;
4796 }
4797
4798 if (target != GL_RENDERBUFFER)
4799 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004800 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004801 return false;
4802 }
4803
4804 Renderbuffer *renderbuffer = context->getGLState().getCurrentRenderbuffer();
4805 if (renderbuffer == nullptr)
4806 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004807 ANGLE_VALIDATION_ERR(context, InvalidOperation(), RenderbufferNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004808 return false;
4809 }
4810
4811 switch (pname)
4812 {
4813 case GL_RENDERBUFFER_WIDTH:
4814 case GL_RENDERBUFFER_HEIGHT:
4815 case GL_RENDERBUFFER_INTERNAL_FORMAT:
4816 case GL_RENDERBUFFER_RED_SIZE:
4817 case GL_RENDERBUFFER_GREEN_SIZE:
4818 case GL_RENDERBUFFER_BLUE_SIZE:
4819 case GL_RENDERBUFFER_ALPHA_SIZE:
4820 case GL_RENDERBUFFER_DEPTH_SIZE:
4821 case GL_RENDERBUFFER_STENCIL_SIZE:
4822 break;
4823
4824 case GL_RENDERBUFFER_SAMPLES_ANGLE:
4825 if (!context->getExtensions().framebufferMultisample)
4826 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004827 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004828 return false;
4829 }
4830 break;
4831
4832 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004833 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004834 return false;
4835 }
4836
4837 if (length)
4838 {
4839 *length = 1;
4840 }
4841 return true;
4842}
4843
4844bool ValidateGetShaderivBase(Context *context, GLuint shader, GLenum pname, GLsizei *length)
4845{
4846 if (length)
4847 {
4848 *length = 0;
4849 }
4850
4851 if (GetValidShader(context, shader) == nullptr)
4852 {
4853 return false;
4854 }
4855
4856 switch (pname)
4857 {
4858 case GL_SHADER_TYPE:
4859 case GL_DELETE_STATUS:
4860 case GL_COMPILE_STATUS:
4861 case GL_INFO_LOG_LENGTH:
4862 case GL_SHADER_SOURCE_LENGTH:
4863 break;
4864
4865 case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
4866 if (!context->getExtensions().translatedShaderSource)
4867 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004868 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004869 return false;
4870 }
4871 break;
4872
4873 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004874 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004875 return false;
4876 }
4877
4878 if (length)
4879 {
4880 *length = 1;
4881 }
4882 return true;
4883}
4884
4885bool ValidateGetTexParameterBase(Context *context, GLenum target, GLenum pname, GLsizei *length)
4886{
4887 if (length)
4888 {
4889 *length = 0;
4890 }
4891
4892 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
4893 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004894 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04004895 return false;
4896 }
4897
4898 if (context->getTargetTexture(target) == nullptr)
4899 {
4900 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07004901 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04004902 return false;
4903 }
4904
4905 switch (pname)
4906 {
4907 case GL_TEXTURE_MAG_FILTER:
4908 case GL_TEXTURE_MIN_FILTER:
4909 case GL_TEXTURE_WRAP_S:
4910 case GL_TEXTURE_WRAP_T:
4911 break;
4912
4913 case GL_TEXTURE_USAGE_ANGLE:
4914 if (!context->getExtensions().textureUsage)
4915 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004916 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004917 return false;
4918 }
4919 break;
4920
4921 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Luc Ferron1b1a8642018-01-23 15:12:01 -05004922 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
Jamie Madillbe849e42017-05-02 15:49:00 -04004923 {
Jamie Madillbe849e42017-05-02 15:49:00 -04004924 return false;
4925 }
4926 break;
4927
4928 case GL_TEXTURE_IMMUTABLE_FORMAT:
4929 if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorage)
4930 {
Brandon Jones6cad5662017-06-14 13:25:13 -07004931 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ExtensionNotEnabled);
Jamie Madillbe849e42017-05-02 15:49:00 -04004932 return false;
4933 }
4934 break;
4935
4936 case GL_TEXTURE_WRAP_R:
4937 case GL_TEXTURE_IMMUTABLE_LEVELS:
4938 case GL_TEXTURE_SWIZZLE_R:
4939 case GL_TEXTURE_SWIZZLE_G:
4940 case GL_TEXTURE_SWIZZLE_B:
4941 case GL_TEXTURE_SWIZZLE_A:
4942 case GL_TEXTURE_BASE_LEVEL:
4943 case GL_TEXTURE_MAX_LEVEL:
4944 case GL_TEXTURE_MIN_LOD:
4945 case GL_TEXTURE_MAX_LOD:
4946 case GL_TEXTURE_COMPARE_MODE:
4947 case GL_TEXTURE_COMPARE_FUNC:
4948 if (context->getClientMajorVersion() < 3)
4949 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004950 context->handleError(InvalidEnum() << "pname requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004951 return false;
4952 }
4953 break;
4954
4955 case GL_TEXTURE_SRGB_DECODE_EXT:
4956 if (!context->getExtensions().textureSRGBDecode)
4957 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004958 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004959 return false;
4960 }
4961 break;
4962
4963 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07004964 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04004965 return false;
4966 }
4967
4968 if (length)
4969 {
4970 *length = 1;
4971 }
4972 return true;
4973}
4974
4975bool ValidateGetVertexAttribBase(Context *context,
4976 GLuint index,
4977 GLenum pname,
4978 GLsizei *length,
4979 bool pointer,
4980 bool pureIntegerEntryPoint)
4981{
4982 if (length)
4983 {
4984 *length = 0;
4985 }
4986
4987 if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
4988 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05004989 context->handleError(InvalidOperation() << "Context does not support OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04004990 return false;
4991 }
4992
4993 if (index >= context->getCaps().maxVertexAttributes)
4994 {
Brandon Jonesafa75152017-07-21 13:11:29 -07004995 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
Jamie Madillbe849e42017-05-02 15:49:00 -04004996 return false;
4997 }
4998
4999 if (pointer)
5000 {
5001 if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
5002 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005003 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005004 return false;
5005 }
5006 }
5007 else
5008 {
5009 switch (pname)
5010 {
5011 case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
5012 case GL_VERTEX_ATTRIB_ARRAY_SIZE:
5013 case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
5014 case GL_VERTEX_ATTRIB_ARRAY_TYPE:
5015 case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
5016 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
5017 case GL_CURRENT_VERTEX_ATTRIB:
5018 break;
5019
5020 case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
5021 static_assert(
5022 GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
5023 "ANGLE extension enums not equal to GL enums.");
5024 if (context->getClientMajorVersion() < 3 &&
5025 !context->getExtensions().instancedArrays)
5026 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005027 context->handleError(InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_DIVISOR "
5028 "requires OpenGL ES 3.0 or "
5029 "GL_ANGLE_instanced_arrays.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005030 return false;
5031 }
5032 break;
5033
5034 case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
5035 if (context->getClientMajorVersion() < 3)
5036 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005037 context->handleError(
5038 InvalidEnum() << "GL_VERTEX_ATTRIB_ARRAY_INTEGER requires OpenGL ES 3.0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005039 return false;
5040 }
5041 break;
5042
5043 case GL_VERTEX_ATTRIB_BINDING:
5044 case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
5045 if (context->getClientVersion() < ES_3_1)
5046 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005047 context->handleError(InvalidEnum()
5048 << "Vertex Attrib Bindings require OpenGL ES 3.1.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005049 return false;
5050 }
5051 break;
5052
5053 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005054 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005055 return false;
5056 }
5057 }
5058
5059 if (length)
5060 {
5061 if (pname == GL_CURRENT_VERTEX_ATTRIB)
5062 {
5063 *length = 4;
5064 }
5065 else
5066 {
5067 *length = 1;
5068 }
5069 }
5070
5071 return true;
5072}
5073
Jamie Madill4928b7c2017-06-20 12:57:39 -04005074bool ValidateReadPixelsBase(Context *context,
Jamie Madillbe849e42017-05-02 15:49:00 -04005075 GLint x,
5076 GLint y,
5077 GLsizei width,
5078 GLsizei height,
5079 GLenum format,
5080 GLenum type,
5081 GLsizei bufSize,
5082 GLsizei *length,
5083 GLsizei *columns,
5084 GLsizei *rows,
5085 void *pixels)
5086{
5087 if (length != nullptr)
5088 {
5089 *length = 0;
5090 }
5091 if (rows != nullptr)
5092 {
5093 *rows = 0;
5094 }
5095 if (columns != nullptr)
5096 {
5097 *columns = 0;
5098 }
5099
5100 if (width < 0 || height < 0)
5101 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005102 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005103 return false;
5104 }
5105
Jamie Madillacf2f3a2017-11-21 19:22:44 -05005106 Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
Jamie Madillbe849e42017-05-02 15:49:00 -04005107
5108 if (readFramebuffer->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
5109 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005110 context->handleError(InvalidFramebufferOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005111 return false;
5112 }
5113
5114 if (readFramebuffer->id() != 0 && readFramebuffer->getSamples(context) != 0)
5115 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005116 context->handleError(InvalidOperation());
Jamie Madillbe849e42017-05-02 15:49:00 -04005117 return false;
5118 }
5119
5120 const Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
5121 ASSERT(framebuffer);
5122
5123 if (framebuffer->getReadBufferState() == GL_NONE)
5124 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005125 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ReadBufferNone);
Jamie Madillbe849e42017-05-02 15:49:00 -04005126 return false;
5127 }
5128
5129 const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
5130 // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
5131 // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
5132 // attachment and WebGL defines it to be an error. We do the check unconditionnaly as the
5133 // situation is an application error that would lead to a crash in ANGLE.
5134 if (readBuffer == nullptr)
5135 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005136 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
Jamie Madillbe849e42017-05-02 15:49:00 -04005137 return false;
5138 }
5139
Martin Radev28031682017-07-28 14:47:56 +03005140 // ANGLE_multiview, Revision 1:
5141 // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
5142 // current read framebuffer is not NONE.
5143 if (readBuffer->getMultiviewLayout() != GL_NONE)
5144 {
5145 context->handleError(InvalidFramebufferOperation()
5146 << "Attempting to read from a multi-view framebuffer.");
5147 return false;
5148 }
5149
Geoff Lang280ba992017-04-18 16:30:58 -04005150 if (context->getExtensions().webglCompatibility)
5151 {
5152 // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
5153 // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
5154 // and type before validating the combination of format and type. However, the
5155 // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
5156 // verifies that GL_INVALID_OPERATION is generated.
5157 // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
5158 // dEQP/WebGL.
5159 if (!ValidReadPixelsFormatEnum(context, format))
5160 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005161 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang280ba992017-04-18 16:30:58 -04005162 return false;
5163 }
5164
5165 if (!ValidReadPixelsTypeEnum(context, type))
5166 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005167 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang280ba992017-04-18 16:30:58 -04005168 return false;
5169 }
5170 }
5171
Jamie Madill4928b7c2017-06-20 12:57:39 -04005172 GLenum currentFormat = framebuffer->getImplementationColorReadFormat(context);
5173 GLenum currentType = framebuffer->getImplementationColorReadType(context);
Jamie Madillbe849e42017-05-02 15:49:00 -04005174 GLenum currentComponentType = readBuffer->getFormat().info->componentType;
5175
5176 bool validFormatTypeCombination =
5177 ValidReadPixelsFormatType(context, currentComponentType, format, type);
5178
5179 if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
5180 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005181 ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
Jamie Madillbe849e42017-05-02 15:49:00 -04005182 return false;
5183 }
5184
5185 // Check for pixel pack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -04005186 gl::Buffer *pixelPackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelPack);
Jamie Madillbe849e42017-05-02 15:49:00 -04005187 if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
5188 {
5189 // ...the buffer object's data store is currently mapped.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005190 context->handleError(InvalidOperation() << "Pixel pack buffer is mapped.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005191 return false;
5192 }
5193
5194 // .. the data would be packed to the buffer object such that the memory writes required
5195 // would exceed the data store size.
5196 const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
5197 const gl::Extents size(width, height, 1);
5198 const auto &pack = context->getGLState().getPackState();
5199
5200 auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
5201 if (endByteOrErr.isError())
5202 {
5203 context->handleError(endByteOrErr.getError());
5204 return false;
5205 }
5206
5207 size_t endByte = endByteOrErr.getResult();
5208 if (bufSize >= 0)
5209 {
5210 if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
5211 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005212 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005213 return false;
5214 }
5215 }
5216
5217 if (pixelPackBuffer != nullptr)
5218 {
5219 CheckedNumeric<size_t> checkedEndByte(endByte);
5220 CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
5221 checkedEndByte += checkedOffset;
5222
5223 if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
5224 {
5225 // Overflow past the end of the buffer
Brandon Jones6cad5662017-06-14 13:25:13 -07005226 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ParamOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005227 return false;
5228 }
5229 }
5230
5231 if (pixelPackBuffer == nullptr && length != nullptr)
5232 {
5233 if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
5234 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005235 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madillbe849e42017-05-02 15:49:00 -04005236 return false;
5237 }
5238
5239 *length = static_cast<GLsizei>(endByte);
5240 }
5241
5242 auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize) {
5243 angle::CheckedNumeric<int> clippedExtent(length);
5244 if (start < 0)
5245 {
5246 // "subtract" the area that is less than 0
5247 clippedExtent += start;
5248 }
5249
5250 const int readExtent = start + length;
5251 if (readExtent > bufferSize)
5252 {
5253 // Subtract the region to the right of the read buffer
5254 clippedExtent -= (readExtent - bufferSize);
5255 }
5256
5257 if (!clippedExtent.IsValid())
5258 {
5259 return 0;
5260 }
5261
5262 return std::max(clippedExtent.ValueOrDie(), 0);
5263 };
5264
5265 if (columns != nullptr)
5266 {
5267 *columns = getClippedExtent(x, width, readBuffer->getSize().width);
5268 }
5269
5270 if (rows != nullptr)
5271 {
5272 *rows = getClippedExtent(y, height, readBuffer->getSize().height);
5273 }
5274
5275 return true;
5276}
5277
5278template <typename ParamType>
5279bool ValidateTexParameterBase(Context *context,
5280 GLenum target,
5281 GLenum pname,
5282 GLsizei bufSize,
5283 const ParamType *params)
5284{
5285 if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
5286 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005287 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
Jamie Madillbe849e42017-05-02 15:49:00 -04005288 return false;
5289 }
5290
5291 if (context->getTargetTexture(target) == nullptr)
5292 {
5293 // Should only be possible for external textures
Brandon Jones6cad5662017-06-14 13:25:13 -07005294 ANGLE_VALIDATION_ERR(context, InvalidEnum(), TextureNotBound);
Jamie Madillbe849e42017-05-02 15:49:00 -04005295 return false;
5296 }
5297
5298 const GLsizei minBufSize = 1;
5299 if (bufSize >= 0 && bufSize < minBufSize)
5300 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005301 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
Jamie Madillbe849e42017-05-02 15:49:00 -04005302 return false;
5303 }
5304
5305 switch (pname)
5306 {
5307 case GL_TEXTURE_WRAP_R:
5308 case GL_TEXTURE_SWIZZLE_R:
5309 case GL_TEXTURE_SWIZZLE_G:
5310 case GL_TEXTURE_SWIZZLE_B:
5311 case GL_TEXTURE_SWIZZLE_A:
5312 case GL_TEXTURE_BASE_LEVEL:
5313 case GL_TEXTURE_MAX_LEVEL:
5314 case GL_TEXTURE_COMPARE_MODE:
5315 case GL_TEXTURE_COMPARE_FUNC:
5316 case GL_TEXTURE_MIN_LOD:
5317 case GL_TEXTURE_MAX_LOD:
5318 if (context->getClientMajorVersion() < 3)
5319 {
Brandon Jonesafa75152017-07-21 13:11:29 -07005320 ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
Jamie Madillbe849e42017-05-02 15:49:00 -04005321 return false;
5322 }
5323 if (target == GL_TEXTURE_EXTERNAL_OES &&
5324 !context->getExtensions().eglImageExternalEssl3)
5325 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005326 context->handleError(InvalidEnum() << "ES3 texture parameters are not "
5327 "available without "
5328 "GL_OES_EGL_image_external_essl3.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005329 return false;
5330 }
5331 break;
5332
5333 default:
5334 break;
5335 }
5336
JiangYizhou4cff8d62017-07-06 14:54:09 +08005337 if (target == GL_TEXTURE_2D_MULTISAMPLE)
5338 {
5339 switch (pname)
5340 {
5341 case GL_TEXTURE_MIN_FILTER:
5342 case GL_TEXTURE_MAG_FILTER:
5343 case GL_TEXTURE_WRAP_S:
5344 case GL_TEXTURE_WRAP_T:
5345 case GL_TEXTURE_WRAP_R:
5346 case GL_TEXTURE_MIN_LOD:
5347 case GL_TEXTURE_MAX_LOD:
5348 case GL_TEXTURE_COMPARE_MODE:
5349 case GL_TEXTURE_COMPARE_FUNC:
5350 context->handleError(InvalidEnum()
5351 << "Invalid parameter for 2D multisampled textures.");
5352 return false;
5353 }
5354 }
5355
Jamie Madillbe849e42017-05-02 15:49:00 -04005356 switch (pname)
5357 {
5358 case GL_TEXTURE_WRAP_S:
5359 case GL_TEXTURE_WRAP_T:
5360 case GL_TEXTURE_WRAP_R:
Jamie Madillbe849e42017-05-02 15:49:00 -04005361 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005362 bool restrictedWrapModes =
5363 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5364 if (!ValidateTextureWrapModeValue(context, params, restrictedWrapModes))
5365 {
5366 return false;
5367 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005368 }
5369 break;
5370
5371 case GL_TEXTURE_MIN_FILTER:
Jamie Madillbe849e42017-05-02 15:49:00 -04005372 {
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005373 bool restrictedMinFilter =
5374 target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ANGLE;
5375 if (!ValidateTextureMinFilterValue(context, params, restrictedMinFilter))
5376 {
5377 return false;
5378 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005379 }
5380 break;
5381
5382 case GL_TEXTURE_MAG_FILTER:
5383 if (!ValidateTextureMagFilterValue(context, params))
5384 {
5385 return false;
5386 }
5387 break;
5388
5389 case GL_TEXTURE_USAGE_ANGLE:
Geoff Lang91ab54b2017-10-30 15:12:42 -04005390 if (!context->getExtensions().textureUsage)
5391 {
5392 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5393 return false;
5394 }
5395
Jamie Madillbe849e42017-05-02 15:49:00 -04005396 switch (ConvertToGLenum(params[0]))
5397 {
5398 case GL_NONE:
5399 case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
5400 break;
5401
5402 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005403 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005404 return false;
5405 }
5406 break;
5407
5408 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
Jamie Madillbe849e42017-05-02 15:49:00 -04005409 {
Luc Ferron1b1a8642018-01-23 15:12:01 -05005410 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5411 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5412 {
5413 return false;
5414 }
5415 ASSERT(static_cast<ParamType>(paramValue) == params[0]);
Jamie Madillbe849e42017-05-02 15:49:00 -04005416 }
5417 break;
5418
5419 case GL_TEXTURE_MIN_LOD:
5420 case GL_TEXTURE_MAX_LOD:
5421 // any value is permissible
5422 break;
5423
5424 case GL_TEXTURE_COMPARE_MODE:
5425 if (!ValidateTextureCompareModeValue(context, params))
5426 {
5427 return false;
5428 }
5429 break;
5430
5431 case GL_TEXTURE_COMPARE_FUNC:
5432 if (!ValidateTextureCompareFuncValue(context, params))
5433 {
5434 return false;
5435 }
5436 break;
5437
5438 case GL_TEXTURE_SWIZZLE_R:
5439 case GL_TEXTURE_SWIZZLE_G:
5440 case GL_TEXTURE_SWIZZLE_B:
5441 case GL_TEXTURE_SWIZZLE_A:
5442 switch (ConvertToGLenum(params[0]))
5443 {
5444 case GL_RED:
5445 case GL_GREEN:
5446 case GL_BLUE:
5447 case GL_ALPHA:
5448 case GL_ZERO:
5449 case GL_ONE:
5450 break;
5451
5452 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005453 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005454 return false;
5455 }
5456 break;
5457
5458 case GL_TEXTURE_BASE_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005459 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005460 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005461 context->handleError(InvalidValue() << "Base level must be at least 0.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005462 return false;
5463 }
5464 if (target == GL_TEXTURE_EXTERNAL_OES && static_cast<GLuint>(params[0]) != 0)
5465 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05005466 context->handleError(InvalidOperation()
5467 << "Base level must be 0 for external textures.");
Jamie Madillbe849e42017-05-02 15:49:00 -04005468 return false;
5469 }
JiangYizhou4cff8d62017-07-06 14:54:09 +08005470 if (target == GL_TEXTURE_2D_MULTISAMPLE && static_cast<GLuint>(params[0]) != 0)
5471 {
5472 context->handleError(InvalidOperation()
5473 << "Base level must be 0 for multisampled textures.");
5474 return false;
5475 }
Corentin Wallez13c0dd42017-07-04 18:27:01 -04005476 if (target == GL_TEXTURE_RECTANGLE_ANGLE && static_cast<GLuint>(params[0]) != 0)
5477 {
5478 context->handleError(InvalidOperation()
5479 << "Base level must be 0 for rectangle textures.");
5480 return false;
5481 }
Jamie Madillbe849e42017-05-02 15:49:00 -04005482 break;
5483
5484 case GL_TEXTURE_MAX_LEVEL:
Geoff Langfb7685f2017-11-13 11:44:11 -05005485 if (ConvertToGLint(params[0]) < 0)
Jamie Madillbe849e42017-05-02 15:49:00 -04005486 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005487 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
Jamie Madillbe849e42017-05-02 15:49:00 -04005488 return false;
5489 }
5490 break;
5491
5492 case GL_DEPTH_STENCIL_TEXTURE_MODE:
5493 if (context->getClientVersion() < Version(3, 1))
5494 {
Brandon Jones6cad5662017-06-14 13:25:13 -07005495 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
Jamie Madillbe849e42017-05-02 15:49:00 -04005496 return false;
5497 }
5498 switch (ConvertToGLenum(params[0]))
5499 {
5500 case GL_DEPTH_COMPONENT:
5501 case GL_STENCIL_INDEX:
5502 break;
5503
5504 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005505 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005506 return false;
5507 }
5508 break;
5509
5510 case GL_TEXTURE_SRGB_DECODE_EXT:
5511 if (!ValidateTextureSRGBDecodeValue(context, params))
5512 {
5513 return false;
5514 }
5515 break;
5516
5517 default:
Brandon Jones6cad5662017-06-14 13:25:13 -07005518 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
Jamie Madillbe849e42017-05-02 15:49:00 -04005519 return false;
5520 }
5521
5522 return true;
5523}
5524
5525template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLfloat *);
5526template bool ValidateTexParameterBase(Context *, GLenum, GLenum, GLsizei, const GLint *);
5527
Jamie Madill12e957f2017-08-26 21:42:26 -04005528bool ValidateVertexAttribIndex(ValidationContext *context, GLuint index)
5529{
5530 if (index >= MAX_VERTEX_ATTRIBS)
5531 {
5532 ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
5533 return false;
5534 }
5535
5536 return true;
5537}
5538
5539bool ValidateGetActiveUniformBlockivBase(Context *context,
5540 GLuint program,
5541 GLuint uniformBlockIndex,
5542 GLenum pname,
5543 GLsizei *length)
5544{
5545 if (length)
5546 {
5547 *length = 0;
5548 }
5549
5550 if (context->getClientMajorVersion() < 3)
5551 {
5552 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5553 return false;
5554 }
5555
5556 Program *programObject = GetValidProgram(context, program);
5557 if (!programObject)
5558 {
5559 return false;
5560 }
5561
5562 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
5563 {
5564 context->handleError(InvalidValue()
5565 << "uniformBlockIndex exceeds active uniform block count.");
5566 return false;
5567 }
5568
5569 switch (pname)
5570 {
5571 case GL_UNIFORM_BLOCK_BINDING:
5572 case GL_UNIFORM_BLOCK_DATA_SIZE:
5573 case GL_UNIFORM_BLOCK_NAME_LENGTH:
5574 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
5575 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
5576 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
5577 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
5578 break;
5579
5580 default:
5581 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5582 return false;
5583 }
5584
5585 if (length)
5586 {
5587 if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
5588 {
Jiajia Qin729b2c62017-08-14 09:36:11 +08005589 const InterfaceBlock &uniformBlock =
Jamie Madill12e957f2017-08-26 21:42:26 -04005590 programObject->getUniformBlockByIndex(uniformBlockIndex);
5591 *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
5592 }
5593 else
5594 {
5595 *length = 1;
5596 }
5597 }
5598
5599 return true;
5600}
5601
Jamie Madill9696d072017-08-26 23:19:57 -04005602template <typename ParamType>
5603bool ValidateSamplerParameterBase(Context *context,
5604 GLuint sampler,
5605 GLenum pname,
5606 GLsizei bufSize,
5607 ParamType *params)
5608{
5609 if (context->getClientMajorVersion() < 3)
5610 {
5611 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5612 return false;
5613 }
5614
5615 if (!context->isSampler(sampler))
5616 {
5617 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5618 return false;
5619 }
5620
5621 const GLsizei minBufSize = 1;
5622 if (bufSize >= 0 && bufSize < minBufSize)
5623 {
5624 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InsufficientBufferSize);
5625 return false;
5626 }
5627
5628 switch (pname)
5629 {
5630 case GL_TEXTURE_WRAP_S:
5631 case GL_TEXTURE_WRAP_T:
5632 case GL_TEXTURE_WRAP_R:
5633 if (!ValidateTextureWrapModeValue(context, params, false))
5634 {
5635 return false;
5636 }
5637 break;
5638
5639 case GL_TEXTURE_MIN_FILTER:
5640 if (!ValidateTextureMinFilterValue(context, params, false))
5641 {
5642 return false;
5643 }
5644 break;
5645
5646 case GL_TEXTURE_MAG_FILTER:
5647 if (!ValidateTextureMagFilterValue(context, params))
5648 {
5649 return false;
5650 }
5651 break;
5652
5653 case GL_TEXTURE_MIN_LOD:
5654 case GL_TEXTURE_MAX_LOD:
5655 // any value is permissible
5656 break;
5657
5658 case GL_TEXTURE_COMPARE_MODE:
5659 if (!ValidateTextureCompareModeValue(context, params))
5660 {
5661 return false;
5662 }
5663 break;
5664
5665 case GL_TEXTURE_COMPARE_FUNC:
5666 if (!ValidateTextureCompareFuncValue(context, params))
5667 {
5668 return false;
5669 }
5670 break;
5671
5672 case GL_TEXTURE_SRGB_DECODE_EXT:
5673 if (!ValidateTextureSRGBDecodeValue(context, params))
5674 {
5675 return false;
5676 }
5677 break;
5678
Luc Ferron1b1a8642018-01-23 15:12:01 -05005679 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5680 {
5681 GLfloat paramValue = static_cast<GLfloat>(params[0]);
5682 if (!ValidateTextureMaxAnisotropyValue(context, paramValue))
5683 {
5684 return false;
5685 }
5686 }
5687 break;
5688
Jamie Madill9696d072017-08-26 23:19:57 -04005689 default:
5690 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5691 return false;
5692 }
5693
5694 return true;
5695}
5696
5697template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLfloat *);
5698template bool ValidateSamplerParameterBase(Context *, GLuint, GLenum, GLsizei, GLint *);
5699
5700bool ValidateGetSamplerParameterBase(Context *context,
5701 GLuint sampler,
5702 GLenum pname,
5703 GLsizei *length)
5704{
5705 if (length)
5706 {
5707 *length = 0;
5708 }
5709
5710 if (context->getClientMajorVersion() < 3)
5711 {
5712 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
5713 return false;
5714 }
5715
5716 if (!context->isSampler(sampler))
5717 {
5718 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSampler);
5719 return false;
5720 }
5721
5722 switch (pname)
5723 {
5724 case GL_TEXTURE_WRAP_S:
5725 case GL_TEXTURE_WRAP_T:
5726 case GL_TEXTURE_WRAP_R:
5727 case GL_TEXTURE_MIN_FILTER:
5728 case GL_TEXTURE_MAG_FILTER:
5729 case GL_TEXTURE_MIN_LOD:
5730 case GL_TEXTURE_MAX_LOD:
5731 case GL_TEXTURE_COMPARE_MODE:
5732 case GL_TEXTURE_COMPARE_FUNC:
5733 break;
5734
Luc Ferron1b1a8642018-01-23 15:12:01 -05005735 case GL_TEXTURE_MAX_ANISOTROPY_EXT:
5736 if (!ValidateTextureMaxAnisotropyExtensionEnabled(context))
5737 {
5738 return false;
5739 }
5740 break;
5741
Jamie Madill9696d072017-08-26 23:19:57 -04005742 case GL_TEXTURE_SRGB_DECODE_EXT:
5743 if (!context->getExtensions().textureSRGBDecode)
5744 {
5745 context->handleError(InvalidEnum() << "GL_EXT_texture_sRGB_decode is not enabled.");
5746 return false;
5747 }
5748 break;
5749
5750 default:
5751 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5752 return false;
5753 }
5754
5755 if (length)
5756 {
5757 *length = 1;
5758 }
5759 return true;
5760}
5761
5762bool ValidateGetInternalFormativBase(Context *context,
5763 GLenum target,
5764 GLenum internalformat,
5765 GLenum pname,
5766 GLsizei bufSize,
5767 GLsizei *numParams)
5768{
5769 if (numParams)
5770 {
5771 *numParams = 0;
5772 }
5773
5774 if (context->getClientMajorVersion() < 3)
5775 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08005776 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9696d072017-08-26 23:19:57 -04005777 return false;
5778 }
5779
5780 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
5781 if (!formatCaps.renderable)
5782 {
5783 context->handleError(InvalidEnum() << "Internal format is not renderable.");
5784 return false;
5785 }
5786
5787 switch (target)
5788 {
5789 case GL_RENDERBUFFER:
5790 break;
5791
5792 case GL_TEXTURE_2D_MULTISAMPLE:
5793 if (context->getClientVersion() < ES_3_1)
5794 {
5795 context->handleError(InvalidOperation()
5796 << "Texture target requires at least OpenGL ES 3.1.");
5797 return false;
5798 }
5799 break;
5800
5801 default:
5802 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTarget);
5803 return false;
5804 }
5805
5806 if (bufSize < 0)
5807 {
5808 ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
5809 return false;
5810 }
5811
5812 GLsizei maxWriteParams = 0;
5813 switch (pname)
5814 {
5815 case GL_NUM_SAMPLE_COUNTS:
5816 maxWriteParams = 1;
5817 break;
5818
5819 case GL_SAMPLES:
5820 maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
5821 break;
5822
5823 default:
5824 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
5825 return false;
5826 }
5827
5828 if (numParams)
5829 {
5830 // glGetInternalFormativ will not overflow bufSize
5831 *numParams = std::min(bufSize, maxWriteParams);
5832 }
5833
5834 return true;
5835}
5836
Jamie Madillc29968b2016-01-20 11:17:23 -05005837} // namespace gl