blob: efb25e63b841c5ba19f2fc98b711558a3f7a2771 [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// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
8
Geoff Lang2b5420c2014-11-19 14:20:15 -05009#include "libANGLE/validationES3.h"
Jamie Madille2e406c2016-06-02 13:04:10 -040010
Jamie Madill5ea762a2017-06-07 14:59:51 -040011#include "anglebase/numerics/safe_conversions.h"
Jamie Madilld2f0c742016-11-02 10:34:41 -040012#include "common/mathutil.h"
13#include "common/utilities.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Context.h"
Martin Radev137032d2017-07-13 10:11:12 +030015#include "libANGLE/ErrorStrings.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050016#include "libANGLE/Framebuffer.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050017#include "libANGLE/FramebufferAttachment.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040018#include "libANGLE/Renderbuffer.h"
19#include "libANGLE/Texture.h"
Jamie Madillc1fd7372018-10-26 22:48:39 -040020#include "libANGLE/VertexArray.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040021#include "libANGLE/formatutils.h"
22#include "libANGLE/validationES.h"
Geoff Lange8ebe7f2013-08-05 15:03:13 -040023
Jamie Madille2e406c2016-06-02 13:04:10 -040024using namespace angle;
25
Geoff Lange8ebe7f2013-08-05 15:03:13 -040026namespace gl
27{
28
Martin Radev137032d2017-07-13 10:11:12 +030029namespace
30{
31bool ValidateFramebufferTextureMultiviewBaseANGLE(Context *context,
32 GLenum target,
33 GLenum attachment,
34 GLuint texture,
35 GLint level,
36 GLsizei numViews)
37{
38 if (!context->getExtensions().multiview)
39 {
40 context->handleError(InvalidOperation() << "ANGLE_multiview is not available.");
41 return false;
42 }
43
44 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
45 {
46 return false;
47 }
48
Martin Radev14b21262017-08-25 13:54:37 +030049 if (texture != 0 && numViews < 1)
Martin Radev137032d2017-07-13 10:11:12 +030050 {
51 context->handleError(InvalidValue() << "numViews cannot be less than 1.");
52 return false;
53 }
54
55 const Extensions &extensions = context->getExtensions();
56 if (static_cast<GLuint>(numViews) > extensions.maxViews)
57 {
58 context->handleError(InvalidValue()
59 << "numViews cannot be greater than GL_MAX_VIEWS_ANGLE.");
60 return false;
61 }
62
63 return true;
64}
65
66bool ValidateFramebufferTextureMultiviewLevelAndFormat(Context *context,
67 Texture *texture,
68 GLint level)
69{
Corentin Wallezf0e89be2017-11-08 14:00:32 -080070 TextureType type = texture->getType();
71 if (!ValidMipLevel(context, type, level))
Martin Radev137032d2017-07-13 10:11:12 +030072 {
73 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
74 return false;
75 }
76
Corentin Wallezf0e89be2017-11-08 14:00:32 -080077 const auto &format = texture->getFormat(NonCubeTextureTypeToTarget(type), level);
Martin Radev137032d2017-07-13 10:11:12 +030078 if (format.info->compressed)
79 {
80 ANGLE_VALIDATION_ERR(context, InvalidOperation(), CompressedTexturesNotAttachable);
81 return false;
82 }
83 return true;
84}
85
Jamie Madillff325f12017-08-26 15:06:05 -040086bool ValidateUniformES3(Context *context, GLenum uniformType, GLint location, GLint count)
87{
88 if (context->getClientMajorVersion() < 3)
89 {
90 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
91 return false;
92 }
93
94 return ValidateUniform(context, uniformType, location, count);
95}
96
Jamie Madillc8c95812017-08-26 18:40:09 -040097bool ValidateUniformMatrixES3(Context *context,
98 GLenum valueType,
99 GLint location,
100 GLsizei count,
101 GLboolean transpose)
102{
103 // Check for ES3 uniform entry points
104 if (context->getClientMajorVersion() < 3)
105 {
106 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
107 return false;
108 }
109
110 return ValidateUniformMatrix(context, valueType, location, count, transpose);
111}
112
Yunchao Hef0fd87d2017-09-12 04:55:05 +0800113bool ValidateGenOrDeleteES3(Context *context, GLint n)
114{
115 if (context->getClientMajorVersion() < 3)
116 {
117 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
118 return false;
119 }
120 return ValidateGenOrDelete(context, n);
121}
122
123bool ValidateGenOrDeleteCountES3(Context *context, GLint count)
124{
125 if (context->getClientMajorVersion() < 3)
126 {
127 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
128 return false;
129 }
130 if (count < 0)
131 {
132 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
133 return false;
134 }
135 return true;
136}
137
Brandon Jones4e6f2ae2018-09-19 11:09:51 -0700138bool ValidateCopyTexture3DCommon(Context *context,
139 const Texture *source,
140 GLint sourceLevel,
141 GLint srcInternalFormat,
142 const Texture *dest,
143 GLint destLevel,
144 GLint internalFormat,
145 TextureTarget destTarget)
146{
147 if (context->getClientMajorVersion() < 3)
148 {
149 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
150 return false;
151 }
152
153 if (!context->getExtensions().copyTexture3d)
154 {
155 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ANGLECopyTexture3DUnavailable);
156 return false;
157 }
158
159 if (!ValidTexture3DTarget(context, source->getType()))
160 {
161 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
162 return false;
163 }
164
165 // Table 1.1 from the ANGLE_copy_texture_3d spec
166 switch (GetUnsizedFormat(srcInternalFormat))
167 {
168 case GL_ALPHA:
169 case GL_LUMINANCE:
170 case GL_LUMINANCE_ALPHA:
171 case GL_RED:
172 case GL_RED_INTEGER:
173 case GL_RG:
174 case GL_RG_INTEGER:
175 case GL_RGB:
176 case GL_RGB_INTEGER:
177 case GL_RGBA:
178 case GL_RGBA_INTEGER:
179 case GL_DEPTH_COMPONENT:
180 case GL_DEPTH_STENCIL:
181 break;
182 default:
183 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
184 return false;
185 }
186
187 if (!ValidTexture3DTarget(context, TextureTargetToType(destTarget)))
188 {
189 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
190 return false;
191 }
192
193 // Table 1.0 from the ANGLE_copy_texture_3d spec
194 switch (internalFormat)
195 {
196 case GL_RGB:
197 case GL_RGBA:
198 case GL_LUMINANCE:
199 case GL_LUMINANCE_ALPHA:
200 case GL_ALPHA:
201 case GL_R8:
202 case GL_R8_SNORM:
203 case GL_R16F:
204 case GL_R32F:
205 case GL_R8UI:
206 case GL_R8I:
207 case GL_R16UI:
208 case GL_R16I:
209 case GL_R32UI:
210 case GL_R32I:
211 case GL_RG:
212 case GL_RG8:
213 case GL_RG8_SNORM:
214 case GL_RG16F:
215 case GL_RG32F:
216 case GL_RG8UI:
217 case GL_RG8I:
218 case GL_RG16UI:
219 case GL_RG16I:
220 case GL_RG32UI:
221 case GL_RG32I:
222 case GL_RGB8:
223 case GL_SRGB8:
224 case GL_RGB565:
225 case GL_RGB8_SNORM:
226 case GL_R11F_G11F_B10F:
227 case GL_RGB9_E5:
228 case GL_RGB16F:
229 case GL_RGB32F:
230 case GL_RGB8UI:
231 case GL_RGB8I:
232 case GL_RGB16UI:
233 case GL_RGB16I:
234 case GL_RGB32UI:
235 case GL_RGB32I:
236 case GL_RGBA8:
237 case GL_SRGB8_ALPHA8:
238 case GL_RGBA8_SNORM:
239 case GL_RGB5_A1:
240 case GL_RGBA4:
241 case GL_RGB10_A2:
242 case GL_RGBA16F:
243 case GL_RGBA32F:
244 case GL_RGBA8UI:
245 case GL_RGBA8I:
246 case GL_RGB10_A2UI:
247 case GL_RGBA16UI:
248 case GL_RGBA16I:
249 case GL_RGBA32I:
250 case GL_RGBA32UI:
251 break;
252 default:
253 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
254 return false;
255 }
256
257 return true;
258}
Jamie Madillff325f12017-08-26 15:06:05 -0400259} // anonymous namespace
Martin Radev137032d2017-07-13 10:11:12 +0300260
He Yunchaoced53ae2016-11-29 15:00:51 +0800261static bool ValidateTexImageFormatCombination(gl::Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800262 TextureType target,
He Yunchaoced53ae2016-11-29 15:00:51 +0800263 GLenum internalFormat,
264 GLenum format,
265 GLenum type)
Geoff Lang5d601382014-07-22 15:14:06 -0400266{
Geoff Lang5d601382014-07-22 15:14:06 -0400267
268 // The type and format are valid if any supported internal format has that type and format
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400269 if (!ValidES3Format(format))
Geoff Lang5d601382014-07-22 15:14:06 -0400270 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700271 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFormat);
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400272 return false;
273 }
274
275 if (!ValidES3Type(type))
276 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700277 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400278 return false;
279 }
280
281 // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
282 // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
283 // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
284 // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
285 if (!ValidES3InternalFormat(internalFormat))
286 {
Brandon Jonesafa75152017-07-21 13:11:29 -0700287 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidInternalFormat);
Geoff Langb1196682014-07-23 13:47:29 -0400288 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400289 }
290
Geoff Langca271392017-04-05 12:30:00 -0400291 // From the ES 3.0 spec section 3.8.3:
292 // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
293 // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
294 // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
295 // INVALID_OPERATION error.
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800296 if (target == TextureType::_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
Geoff Langca271392017-04-05 12:30:00 -0400297 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500298 context->handleError(InvalidOperation() << "Format cannot be GL_DEPTH_COMPONENT or "
299 "GL_DEPTH_STENCIL if target is "
300 "GL_TEXTURE_3D");
Geoff Langca271392017-04-05 12:30:00 -0400301 return false;
302 }
303
Geoff Lang5d601382014-07-22 15:14:06 -0400304 // Check if this is a valid format combination to load texture data
Jamie Madill55e98212016-10-05 16:39:13 -0400305 if (!ValidES3FormatCombination(format, type, internalFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400306 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500307 context->handleError(InvalidOperation()
308 << "Invalid combination of format, type and internalFormat.");
Geoff Lang6d1ccf02017-04-24 14:09:58 -0400309 return false;
310 }
311
312 const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
313 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
314 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500315 context->handleError(InvalidOperation() << "Unsupported internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400316 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400317 }
318
319 return true;
320}
321
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500322bool ValidateES3TexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800323 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500324 GLint level,
325 GLenum internalformat,
326 bool isCompressed,
327 bool isSubImage,
328 GLint xoffset,
329 GLint yoffset,
330 GLint zoffset,
331 GLsizei width,
332 GLsizei height,
333 GLsizei depth,
334 GLint border,
335 GLenum format,
336 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400337 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400338 const void *pixels)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400339{
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800340 TextureType texType = TextureTargetToType(target);
341
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400342 // Validate image size
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800343 if (!ValidImageSizeParameters(context, texType, level, width, height, depth, isSubImage))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400344 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500345 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400346 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400347 }
348
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400349 // Verify zero border
350 if (border != 0)
351 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500352 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400353 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400354 }
355
Jamie Madill6f38f822014-06-06 17:12:20 -0400356 if (xoffset < 0 || yoffset < 0 || zoffset < 0 ||
357 std::numeric_limits<GLsizei>::max() - xoffset < width ||
358 std::numeric_limits<GLsizei>::max() - yoffset < height ||
359 std::numeric_limits<GLsizei>::max() - zoffset < depth)
360 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500361 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400362 return false;
Jamie Madill6f38f822014-06-06 17:12:20 -0400363 }
364
Geoff Langaae65a42014-05-26 12:43:44 -0400365 const gl::Caps &caps = context->getCaps();
366
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800367 switch (texType)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400368 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800369 case TextureType::_2D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800370 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
371 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
372 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500373 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800374 return false;
375 }
376 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400377
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800378 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -0400379 ASSERT(level == 0);
380 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
381 static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
382 {
383 context->handleError(InvalidValue());
384 return false;
385 }
386 if (isCompressed)
387 {
388 context->handleError(InvalidEnum()
389 << "Rectangle texture cannot have a compressed format.");
390 return false;
391 }
392 break;
393
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800394 case TextureType::CubeMap:
He Yunchaoced53ae2016-11-29 15:00:51 +0800395 if (!isSubImage && width != height)
396 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500397 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800398 return false;
399 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400400
He Yunchaoced53ae2016-11-29 15:00:51 +0800401 if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
402 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500403 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800404 return false;
405 }
406 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400407
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800408 case TextureType::_3D:
He Yunchaoced53ae2016-11-29 15:00:51 +0800409 if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
410 static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
411 static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
412 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500413 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800414 return false;
415 }
416 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400417
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800418 case TextureType::_2DArray:
He Yunchaoced53ae2016-11-29 15:00:51 +0800419 if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
420 static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
421 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
422 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500423 context->handleError(InvalidValue());
He Yunchaoced53ae2016-11-29 15:00:51 +0800424 return false;
425 }
426 break;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400427
He Yunchaoced53ae2016-11-29 15:00:51 +0800428 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500429 context->handleError(InvalidEnum());
He Yunchaoced53ae2016-11-29 15:00:51 +0800430 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400431 }
432
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800433 gl::Texture *texture = context->getTargetTexture(texType);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400434 if (!texture)
435 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500436 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400437 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400438 }
439
Geoff Lang69cce582015-09-17 13:20:36 -0400440 if (texture->getImmutableFormat() && !isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400441 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500442 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400443 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400444 }
445
446 // Validate texture formats
Jamie Madilla3944d42016-07-22 22:13:26 -0400447 GLenum actualInternalFormat =
Geoff Langc4e93662017-05-01 10:45:59 -0400448 isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
Geoff Langc51642b2016-11-14 16:18:26 -0500449 if (isSubImage && actualInternalFormat == GL_NONE)
450 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500451 context->handleError(InvalidOperation() << "Texture level does not exist.");
Geoff Langc51642b2016-11-14 16:18:26 -0500452 return false;
453 }
454
Geoff Langc4e93662017-05-01 10:45:59 -0400455 const gl::InternalFormat &actualFormatInfo = isSubImage
456 ? *texture->getFormat(target, level).info
457 : GetInternalFormatInfo(internalformat, type);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400458 if (isCompressed)
459 {
tmartino7c102692015-10-02 16:43:40 -0400460 if (!actualFormatInfo.compressed)
Geoff Langd4f180b2013-09-24 13:57:44 -0400461 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500462 context->handleError(
463 InvalidEnum() << "internalformat is not a supported compressed internal format.");
Geoff Langb1196682014-07-23 13:47:29 -0400464 return false;
Geoff Langd4f180b2013-09-24 13:57:44 -0400465 }
466
Geoff Lang966c9402017-04-18 12:38:27 -0400467 if (isSubImage)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400468 {
Geoff Lang966c9402017-04-18 12:38:27 -0400469 if (!ValidCompressedSubImageSize(
470 context, actualFormatInfo.internalFormat, xoffset, yoffset, width, height,
471 texture->getWidth(target, level), texture->getHeight(target, level)))
472 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500473 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400474 return false;
475 }
476
477 if (format != actualInternalFormat)
478 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500479 context->handleError(InvalidOperation()
480 << "Format must match the internal format of the texture.");
Geoff Lang966c9402017-04-18 12:38:27 -0400481 return false;
482 }
Geoff Lang86f81162017-10-30 15:10:45 -0400483
484 if (actualInternalFormat == GL_ETC1_RGB8_OES)
485 {
486 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
487 return false;
488 }
Geoff Lang966c9402017-04-18 12:38:27 -0400489 }
490 else
491 {
492 if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
493 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500494 context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
Geoff Lang966c9402017-04-18 12:38:27 -0400495 return false;
496 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400497 }
498
Geoff Langeb66a6e2016-10-31 13:06:12 -0400499 if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang839ce0b2015-10-23 13:13:12 -0400500 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500501 context->handleError(InvalidEnum());
Geoff Lang839ce0b2015-10-23 13:13:12 -0400502 return false;
503 }
504
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800505 if (texType == TextureType::_3D)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400506 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500507 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400508 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400509 }
510 }
511 else
512 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800513 if (!ValidateTexImageFormatCombination(context, texType, actualInternalFormat, format,
514 type))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400515 {
Geoff Lang5d601382014-07-22 15:14:06 -0400516 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400517 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400518 }
519
520 // Validate sub image parameters
521 if (isSubImage)
522 {
Geoff Langa9be0dc2014-12-17 12:34:40 -0500523 if (isCompressed != actualFormatInfo.compressed)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400524 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500525 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400526 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400527 }
528
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400529 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
530 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500531 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400532 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400533 }
534
535 if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
536 std::numeric_limits<GLsizei>::max() - yoffset < height ||
537 std::numeric_limits<GLsizei>::max() - zoffset < depth)
538 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500539 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400540 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400541 }
542
Geoff Langa9be0dc2014-12-17 12:34:40 -0500543 if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
544 static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
545 static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400546 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500547 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -0400548 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400549 }
Geoff Langfb052642017-10-24 13:42:09 -0400550
551 if (width > 0 && height > 0 && depth > 0 && pixels == nullptr &&
Corentin Wallez336129f2017-10-17 15:55:40 -0400552 context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack) == nullptr)
Geoff Langfb052642017-10-24 13:42:09 -0400553 {
554 ANGLE_VALIDATION_ERR(context, InvalidValue(), PixelDataNull);
555 return false;
556 }
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400557 }
558
Geoff Langdbcced82017-06-06 15:55:54 -0400559 GLenum sizeCheckFormat = isSubImage ? format : internalformat;
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800560 if (!ValidImageDataSize(context, texType, width, height, depth, sizeCheckFormat, type, pixels,
Geoff Langdbcced82017-06-06 15:55:54 -0400561 imageSize))
Geoff Langff5b2d52016-09-07 11:32:23 -0400562 {
563 return false;
564 }
565
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400566 // Check for pixel unpack buffer related API errors
Corentin Wallez336129f2017-10-17 15:55:40 -0400567 gl::Buffer *pixelUnpackBuffer =
568 context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Corentin Wallezece7c5a2016-09-21 15:28:23 -0400569 if (pixelUnpackBuffer != nullptr)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400570 {
He Yunchaoced53ae2016-11-29 15:00:51 +0800571 // ...data is not evenly divisible into the number of bytes needed to store in memory a
572 // datum
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400573 // indicated by type.
Jamie Madillc751d1e2014-10-21 17:46:29 -0400574 if (!isCompressed)
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400575 {
Geoff Langff5b2d52016-09-07 11:32:23 -0400576 size_t offset = reinterpret_cast<size_t>(pixels);
Jamie Madillc751d1e2014-10-21 17:46:29 -0400577 size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
578
Geoff Langff5b2d52016-09-07 11:32:23 -0400579 if ((offset % dataBytesPerPixel) != 0)
Jamie Madillc751d1e2014-10-21 17:46:29 -0400580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500581 context->handleError(InvalidOperation()
582 << "Reads would overflow the pixel unpack buffer.");
Jamie Madillc751d1e2014-10-21 17:46:29 -0400583 return false;
584 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400585 }
586
Jamie Madill7a5f7382014-03-05 15:01:24 -0500587 // ...the buffer object's data store is currently mapped.
Brandon Jonesd38f9262014-06-18 16:26:45 -0700588 if (pixelUnpackBuffer->isMapped())
Jamie Madill7a5f7382014-03-05 15:01:24 -0500589 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500590 context->handleError(InvalidOperation() << "Pixel unpack buffer is mapped.");
Geoff Langb1196682014-07-23 13:47:29 -0400591 return false;
Jamie Madill7a5f7382014-03-05 15:01:24 -0500592 }
Jamie Madillefb2a6f2013-09-24 10:22:42 -0400593 }
594
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400595 return true;
596}
597
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500598bool ValidateES3TexImage2DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800599 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500600 GLint level,
601 GLenum internalformat,
602 bool isCompressed,
603 bool isSubImage,
604 GLint xoffset,
605 GLint yoffset,
606 GLint zoffset,
607 GLsizei width,
608 GLsizei height,
609 GLsizei depth,
610 GLint border,
611 GLenum format,
612 GLenum type,
Geoff Langff5b2d52016-09-07 11:32:23 -0400613 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400614 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500615{
616 if (!ValidTexture2DDestinationTarget(context, target))
617 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500618 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500619 return false;
620 }
621
622 return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
623 isSubImage, xoffset, yoffset, zoffset, width, height,
Geoff Langff5b2d52016-09-07 11:32:23 -0400624 depth, border, format, type, imageSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500625}
626
627bool ValidateES3TexImage3DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800628 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500629 GLint level,
630 GLenum internalformat,
631 bool isCompressed,
632 bool isSubImage,
633 GLint xoffset,
634 GLint yoffset,
635 GLint zoffset,
636 GLsizei width,
637 GLsizei height,
638 GLsizei depth,
639 GLint border,
640 GLenum format,
641 GLenum type,
Geoff Langc52f6f12016-10-14 10:18:00 -0400642 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -0400643 const void *pixels)
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500644{
645 if (!ValidTexture3DDestinationTarget(context, target))
646 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500647 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500648 return false;
649 }
650
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800651 if (IsETC2EACFormat(format) && target != TextureType::_2DArray)
Luc Ferron9dbaeba2018-02-01 07:26:59 -0500652 {
653 // ES 3.1, Section 8.7, page 169.
654 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InternalFormatRequiresTexture2DArray);
655 return false;
656 }
657
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800658 return ValidateES3TexImageParametersBase(context, NonCubeTextureTypeToTarget(target), level,
659 internalformat, isCompressed, isSubImage, xoffset,
660 yoffset, zoffset, width, height, depth, border, format,
661 type, bufSize, pixels);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500662}
663
Geoff Lang5d601382014-07-22 15:14:06 -0400664struct EffectiveInternalFormatInfo
665{
Jamie Madill76648fe2016-10-05 17:01:41 -0400666 GLenum effectiveFormat;
667 GLenum destFormat;
668 GLuint minRedBits;
669 GLuint maxRedBits;
670 GLuint minGreenBits;
671 GLuint maxGreenBits;
672 GLuint minBlueBits;
673 GLuint maxBlueBits;
674 GLuint minAlphaBits;
675 GLuint maxAlphaBits;
Geoff Lang5d601382014-07-22 15:14:06 -0400676};
677
Jamie Madill76648fe2016-10-05 17:01:41 -0400678static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
679 GLenum targetFormat,
680 const EffectiveInternalFormatInfo *list,
681 size_t size,
682 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400683{
Jamie Madill76648fe2016-10-05 17:01:41 -0400684 for (size_t curFormat = 0; curFormat < size; ++curFormat)
685 {
686 const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
687 if ((formatInfo.destFormat == targetFormat) &&
688 (formatInfo.minRedBits <= srcFormat.redBits &&
689 formatInfo.maxRedBits >= srcFormat.redBits) &&
690 (formatInfo.minGreenBits <= srcFormat.greenBits &&
691 formatInfo.maxGreenBits >= srcFormat.greenBits) &&
692 (formatInfo.minBlueBits <= srcFormat.blueBits &&
693 formatInfo.maxBlueBits >= srcFormat.blueBits) &&
694 (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
695 formatInfo.maxAlphaBits >= srcFormat.alphaBits))
696 {
697 *outEffectiveFormat = formatInfo.effectiveFormat;
698 return true;
699 }
700 }
Geoff Lang5d601382014-07-22 15:14:06 -0400701
Jamie Madill76648fe2016-10-05 17:01:41 -0400702 *outEffectiveFormat = GL_NONE;
703 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400704}
705
Jamie Madill76648fe2016-10-05 17:01:41 -0400706bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
707 GLenum *outEffectiveFormat)
Geoff Lang5d601382014-07-22 15:14:06 -0400708{
Jamie Madill76648fe2016-10-05 17:01:41 -0400709 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
710 // Effective internal format coresponding to destination internal format and linear source
711 // buffer component sizes.
712 // | Source channel min/max sizes |
713 // Effective Internal Format | N/A | R | G | B | A |
714 // clang-format off
715 constexpr EffectiveInternalFormatInfo list[] = {
716 { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
717 { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
718 { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
719 { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
720 { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
721 { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
722 { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
723 { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
724 { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
725 };
726 // clang-format on
Geoff Lang5d601382014-07-22 15:14:06 -0400727
Jamie Madill76648fe2016-10-05 17:01:41 -0400728 return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
729}
Geoff Lang5d601382014-07-22 15:14:06 -0400730
Jamie Madill76648fe2016-10-05 17:01:41 -0400731bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
732 const InternalFormat &destFormat,
733 GLenum *outEffectiveFormat)
734{
735 constexpr GLuint umax = UINT_MAX;
736
737 // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
738 // Effective internal format coresponding to destination internal format andlinear source buffer
739 // component sizes.
740 // | Source channel min/max sizes |
741 // Effective Internal Format | Dest Format | R | G | B | A |
742 // clang-format off
743 constexpr EffectiveInternalFormatInfo list[] = {
744 { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
745 { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
746 { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
747 { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
748 { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
749 { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
750 { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
751 { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
752 };
753 // clang-format on
754
755 return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
756 outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400757}
758
He Yunchaoced53ae2016-11-29 15:00:51 +0800759static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
760 const InternalFormat &destFormat,
Geoff Lang5d601382014-07-22 15:14:06 -0400761 GLenum *outEffectiveFormat)
762{
Geoff Langca271392017-04-05 12:30:00 -0400763 if (destFormat.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400764 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400765 return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400766 }
767 else
768 {
Jamie Madill76648fe2016-10-05 17:01:41 -0400769 return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400770 }
Geoff Lang5d601382014-07-22 15:14:06 -0400771}
772
Corentin Wallez76287682016-04-25 09:23:38 -0400773static bool EqualOrFirstZero(GLuint first, GLuint second)
774{
775 return first == 0 || first == second;
776}
777
Geoff Langca271392017-04-05 12:30:00 -0400778static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
779 const InternalFormat &framebufferFormatInfo,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400780 GLuint readBufferHandle)
Geoff Lang5d601382014-07-22 15:14:06 -0400781{
Jamie Madill21b786b2016-11-01 17:41:31 -0400782 if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
Geoff Lang5d601382014-07-22 15:14:06 -0400783 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400784 return false;
785 }
Geoff Lang5d601382014-07-22 15:14:06 -0400786
Jamie Madill21b786b2016-11-01 17:41:31 -0400787 // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
788 // must both be signed, unsigned, or fixed point and both source and destinations
789 // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
790 // conversion between fixed and floating point.
791
792 if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
793 (framebufferFormatInfo.colorEncoding == GL_SRGB))
794 {
795 return false;
796 }
797
798 if (((textureFormatInfo.componentType == GL_INT) !=
799 (framebufferFormatInfo.componentType == GL_INT)) ||
800 ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
801 (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
802 {
803 return false;
804 }
805
806 if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
807 textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
808 textureFormatInfo.componentType == GL_FLOAT) &&
809 !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
810 framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
811 framebufferFormatInfo.componentType == GL_FLOAT))
812 {
813 return false;
814 }
815
816 // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
817 // The effective internal format of the source buffer is determined with the following rules
818 // applied in order:
819 // * If the source buffer is a texture or renderbuffer that was created with a sized internal
820 // format then the effective internal format is the source buffer's sized internal format.
821 // * If the source buffer is a texture that was created with an unsized base internal format,
822 // then the effective internal format is the source image array's effective internal
823 // format, as specified by table 3.12, which is determined from the <format> and <type>
824 // that were used when the source image array was specified by TexImage*.
825 // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
826 // where Destination Internal Format matches internalformat and where the [source channel
827 // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
828 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
829 // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
Yunchao Hed7297bf2017-04-19 15:27:10 +0800830 const InternalFormat *sourceEffectiveFormat = nullptr;
Jamie Madill21b786b2016-11-01 17:41:31 -0400831 if (readBufferHandle != 0)
832 {
833 // Not the default framebuffer, therefore the read buffer must be a user-created texture or
834 // renderbuffer
Geoff Langca271392017-04-05 12:30:00 -0400835 if (framebufferFormatInfo.sized)
Geoff Lang5d601382014-07-22 15:14:06 -0400836 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400837 sourceEffectiveFormat = &framebufferFormatInfo;
Geoff Lang5d601382014-07-22 15:14:06 -0400838 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400839 else
Geoff Lang5d601382014-07-22 15:14:06 -0400840 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400841 // Renderbuffers cannot be created with an unsized internal format, so this must be an
842 // unsized-format texture. We can use the same table we use when creating textures to
843 // get its effective sized format.
Geoff Langca271392017-04-05 12:30:00 -0400844 sourceEffectiveFormat =
845 &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400846 }
Jamie Madill21b786b2016-11-01 17:41:31 -0400847 }
848 else
849 {
850 // The effective internal format must be derived from the source framebuffer's channel
851 // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
852 if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
Geoff Lang5d601382014-07-22 15:14:06 -0400853 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400854 GLenum effectiveFormat;
855 if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
856 &effectiveFormat))
Geoff Lang5d601382014-07-22 15:14:06 -0400857 {
Geoff Langca271392017-04-05 12:30:00 -0400858 sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
Geoff Lang5d601382014-07-22 15:14:06 -0400859 }
860 else
861 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400862 return false;
863 }
864 }
865 else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
866 {
867 // SRGB buffers can only be copied to sized format destinations according to table 3.18
Geoff Langca271392017-04-05 12:30:00 -0400868 if (textureFormatInfo.sized &&
Jamie Madill21b786b2016-11-01 17:41:31 -0400869 (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
870 (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
871 (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
872 (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
873 {
Geoff Langca271392017-04-05 12:30:00 -0400874 sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
Jamie Madill21b786b2016-11-01 17:41:31 -0400875 }
876 else
877 {
878 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400879 }
880 }
881 else
882 {
Jamie Madill21b786b2016-11-01 17:41:31 -0400883 UNREACHABLE();
884 return false;
Geoff Lang5d601382014-07-22 15:14:06 -0400885 }
Geoff Lang5d601382014-07-22 15:14:06 -0400886 }
887
Geoff Langca271392017-04-05 12:30:00 -0400888 if (textureFormatInfo.sized)
Jamie Madill21b786b2016-11-01 17:41:31 -0400889 {
890 // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
891 // sized, component sizes of the source and destination formats must exactly match if the
892 // destination format exists.
893 if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
894 !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
895 !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
896 !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
897 {
898 return false;
899 }
900 }
901
902 return true; // A conversion function exists, and no rule in the specification has precluded
903 // conversion between these formats.
Geoff Lang5d601382014-07-22 15:14:06 -0400904}
905
Jamie Madill5b772312018-03-08 20:28:32 -0500906bool ValidateES3CopyTexImageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800907 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500908 GLint level,
909 GLenum internalformat,
910 bool isSubImage,
911 GLint xoffset,
912 GLint yoffset,
913 GLint zoffset,
914 GLint x,
915 GLint y,
916 GLsizei width,
917 GLsizei height,
918 GLint border)
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400919{
Jamie Madill0c8abca2016-07-22 20:21:26 -0400920 Format textureFormat = Format::Invalid();
Jamie Madill560a8d82014-05-21 13:06:20 -0400921 if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
Jamie Madill0c8abca2016-07-22 20:21:26 -0400922 xoffset, yoffset, zoffset, x, y, width, height, border,
923 &textureFormat))
Shannon Woods4dfed832014-03-17 20:03:39 -0400924 {
Jamie Madill560a8d82014-05-21 13:06:20 -0400925 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400926 }
Jamie Madill0c8abca2016-07-22 20:21:26 -0400927 ASSERT(textureFormat.valid() || !isSubImage);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400928
Jamie Madill51f40ec2016-06-15 14:06:00 -0400929 const auto &state = context->getGLState();
930 gl::Framebuffer *framebuffer = state.getReadFramebuffer();
931 GLuint readFramebufferID = framebuffer->id();
Jamie Madill3c7fa222014-06-05 13:08:51 -0400932
Jamie Madill427064d2018-04-13 16:20:34 -0400933 if (!ValidateFramebufferComplete(context, framebuffer))
Jamie Madill3c7fa222014-06-05 13:08:51 -0400934 {
Geoff Langb1196682014-07-23 13:47:29 -0400935 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400936 }
937
Jamie Madille98b1b52018-03-08 09:47:23 -0500938 if (readFramebufferID != 0 && !ValidateFramebufferNotMultisampled(context, framebuffer))
Jamie Madill3c7fa222014-06-05 13:08:51 -0400939 {
Geoff Langb1196682014-07-23 13:47:29 -0400940 return false;
Jamie Madill3c7fa222014-06-05 13:08:51 -0400941 }
942
Jamie Madill0c8abca2016-07-22 20:21:26 -0400943 const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400944
Yunchao He096a6c82018-02-27 23:48:21 +0800945 // According to ES 3.x spec, if the internalformat of the texture
946 // is RGB9_E5 and copy to such a texture, generate INVALID_OPERATION.
947 if (textureFormat.info->internalFormat == GL_RGB9_E5)
948 {
949 context->handleError(InvalidOperation());
950 return false;
951 }
952
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400953 if (isSubImage)
954 {
Geoff Langca271392017-04-05 12:30:00 -0400955 if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
Jamie Madillc29968b2016-01-20 11:17:23 -0500956 readFramebufferID))
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400957 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500958 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400959 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400960 }
961 }
Shannon Woods4d161ba2014-03-17 18:13:30 -0400962 else
963 {
Jamie Madill0c8abca2016-07-22 20:21:26 -0400964 // Use format/type from the source FBO. (Might not be perfect for all cases?)
Geoff Langca271392017-04-05 12:30:00 -0400965 const InternalFormat &framebufferFormat = *source->getFormat().info;
966 const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
Jamie Madill0c8abca2016-07-22 20:21:26 -0400967 if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
Shannon Woods4d161ba2014-03-17 18:13:30 -0400968 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500969 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -0400970 return false;
Shannon Woods4d161ba2014-03-17 18:13:30 -0400971 }
972 }
973
Geoff Lang784a8fd2013-09-24 12:33:16 -0400974 // If width or height is zero, it is a no-op. Return false without setting an error.
975 return (width > 0 && height > 0);
Geoff Lange8ebe7f2013-08-05 15:03:13 -0400976}
977
Jamie Madill5b772312018-03-08 20:28:32 -0500978bool ValidateES3CopyTexImage2DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -0800979 TextureTarget target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500980 GLint level,
981 GLenum internalformat,
982 bool isSubImage,
983 GLint xoffset,
984 GLint yoffset,
985 GLint zoffset,
986 GLint x,
987 GLint y,
988 GLsizei width,
989 GLsizei height,
990 GLint border)
991{
992 if (!ValidTexture2DDestinationTarget(context, target))
993 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500994 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -0500995 return false;
996 }
997
998 return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
999 xoffset, yoffset, zoffset, x, y, width, height,
1000 border);
1001}
1002
Jamie Madill5b772312018-03-08 20:28:32 -05001003bool ValidateES3CopyTexImage3DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001004 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001005 GLint level,
1006 GLenum internalformat,
1007 bool isSubImage,
1008 GLint xoffset,
1009 GLint yoffset,
1010 GLint zoffset,
1011 GLint x,
1012 GLint y,
1013 GLsizei width,
1014 GLsizei height,
1015 GLint border)
1016{
1017 if (!ValidTexture3DDestinationTarget(context, target))
1018 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001019 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001020 return false;
1021 }
1022
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001023 return ValidateES3CopyTexImageParametersBase(context, NonCubeTextureTypeToTarget(target), level,
1024 internalformat, isSubImage, xoffset, yoffset,
1025 zoffset, x, y, width, height, border);
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001026}
1027
1028bool ValidateES3TexStorageParametersBase(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001029 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001030 GLsizei levels,
1031 GLenum internalformat,
1032 GLsizei width,
1033 GLsizei height,
1034 GLsizei depth)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001035{
1036 if (width < 1 || height < 1 || depth < 1 || levels < 1)
1037 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001038 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001039 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001040 }
1041
Geoff Langb92c1332015-09-04 12:54:55 -04001042 GLsizei maxDim = std::max(width, height);
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001043 if (target != TextureType::_2DArray)
Geoff Langb92c1332015-09-04 12:54:55 -04001044 {
1045 maxDim = std::max(maxDim, depth);
1046 }
1047
1048 if (levels > gl::log2(maxDim) + 1)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001049 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001050 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001051 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001052 }
1053
Geoff Langaae65a42014-05-26 12:43:44 -04001054 const gl::Caps &caps = context->getCaps();
1055
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001056 switch (target)
1057 {
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001058 case TextureType::_2D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001059 {
Geoff Langaae65a42014-05-26 12:43:44 -04001060 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1061 static_cast<GLuint>(height) > caps.max2DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001062 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001063 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001064 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001065 }
1066 }
1067 break;
1068
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001069 case TextureType::Rectangle:
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001070 {
1071 if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
1072 static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
1073 {
1074 context->handleError(InvalidValue());
1075 return false;
1076 }
1077 }
1078 break;
1079
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001080 case TextureType::CubeMap:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001081 {
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001082 if (width != height)
1083 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001084 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001085 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001086 }
1087
Geoff Langaae65a42014-05-26 12:43:44 -04001088 if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001089 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001090 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001091 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001092 }
1093 }
1094 break;
1095
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001096 case TextureType::_3D:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001097 {
Geoff Langaae65a42014-05-26 12:43:44 -04001098 if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
1099 static_cast<GLuint>(height) > caps.max3DTextureSize ||
1100 static_cast<GLuint>(depth) > caps.max3DTextureSize)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001101 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001102 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001103 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001104 }
1105 }
1106 break;
1107
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001108 case TextureType::_2DArray:
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001109 {
Geoff Langaae65a42014-05-26 12:43:44 -04001110 if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
1111 static_cast<GLuint>(height) > caps.max2DTextureSize ||
1112 static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001113 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001114 context->handleError(InvalidValue());
Geoff Langb1196682014-07-23 13:47:29 -04001115 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001116 }
1117 }
1118 break;
1119
He Yunchaoced53ae2016-11-29 15:00:51 +08001120 default:
1121 UNREACHABLE();
1122 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001123 }
1124
Geoff Lang691e58c2014-12-19 17:03:25 -05001125 gl::Texture *texture = context->getTargetTexture(target);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001126 if (!texture || texture->id() == 0)
1127 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001128 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001129 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001130 }
1131
Geoff Lang69cce582015-09-17 13:20:36 -04001132 if (texture->getImmutableFormat())
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001133 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001134 context->handleError(InvalidOperation());
Geoff Langb1196682014-07-23 13:47:29 -04001135 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001136 }
1137
Geoff Langca271392017-04-05 12:30:00 -04001138 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Geoff Langeb66a6e2016-10-31 13:06:12 -04001139 if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001140 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001141 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001142 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001143 }
1144
Geoff Langca271392017-04-05 12:30:00 -04001145 if (!formatInfo.sized)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001146 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001147 context->handleError(InvalidEnum());
Geoff Langb1196682014-07-23 13:47:29 -04001148 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001149 }
1150
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001151 if (formatInfo.compressed && target == TextureType::Rectangle)
Corentin Wallez13c0dd42017-07-04 18:27:01 -04001152 {
1153 context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
1154 return false;
1155 }
1156
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001157 return true;
1158}
1159
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001160bool ValidateES3TexStorage2DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001161 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001162 GLsizei levels,
1163 GLenum internalformat,
1164 GLsizei width,
1165 GLsizei height,
1166 GLsizei depth)
1167{
1168 if (!ValidTexture2DTarget(context, target))
1169 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001170 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001171 return false;
1172 }
1173
1174 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1175 height, depth);
1176}
1177
1178bool ValidateES3TexStorage3DParameters(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001179 TextureType target,
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001180 GLsizei levels,
1181 GLenum internalformat,
1182 GLsizei width,
1183 GLsizei height,
1184 GLsizei depth)
1185{
1186 if (!ValidTexture3DTarget(context, target))
1187 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001188 context->handleError(InvalidEnum());
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001189 return false;
1190 }
1191
1192 return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width,
1193 height, depth);
1194}
1195
Corentin Wallezad3ae902018-03-09 13:40:42 -05001196bool ValidateBeginQuery(gl::Context *context, QueryType target, GLuint id)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001197{
Martin Radev1be913c2016-07-11 17:59:16 +03001198 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001199 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001200 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001201 return false;
1202 }
1203
1204 return ValidateBeginQueryBase(context, target, id);
1205}
1206
Corentin Wallezad3ae902018-03-09 13:40:42 -05001207bool ValidateEndQuery(gl::Context *context, QueryType target)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001208{
Martin Radev1be913c2016-07-11 17:59:16 +03001209 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001210 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001211 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001212 return false;
1213 }
1214
1215 return ValidateEndQueryBase(context, target);
1216}
1217
Corentin Wallezad3ae902018-03-09 13:40:42 -05001218bool ValidateGetQueryiv(Context *context, QueryType target, GLenum pname, GLint *params)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001219{
Martin Radev1be913c2016-07-11 17:59:16 +03001220 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001221 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001222 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001223 return false;
1224 }
1225
Geoff Lang2186c382016-10-14 10:54:54 -04001226 return ValidateGetQueryivBase(context, target, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001227}
1228
1229bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params)
1230{
Martin Radev1be913c2016-07-11 17:59:16 +03001231 if (context->getClientMajorVersion() < 3)
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001232 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001233 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001234 return false;
1235 }
1236
Geoff Lang2186c382016-10-14 10:54:54 -04001237 return ValidateGetQueryObjectValueBase(context, id, pname, nullptr);
Ian Ewell3ffd78b2016-01-22 16:09:42 -05001238}
1239
He Yunchaoced53ae2016-11-29 15:00:51 +08001240bool ValidateFramebufferTextureLayer(Context *context,
1241 GLenum target,
1242 GLenum attachment,
1243 GLuint texture,
1244 GLint level,
1245 GLint layer)
Jamie Madill570f7c82014-07-03 10:38:54 -04001246{
Martin Radev1be913c2016-07-11 17:59:16 +03001247 if (context->getClientMajorVersion() < 3)
Jamie Madill570f7c82014-07-03 10:38:54 -04001248 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001249 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001250 return false;
Jamie Madill570f7c82014-07-03 10:38:54 -04001251 }
1252
Jamie Madill55ec3b12014-07-03 10:38:57 -04001253 if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
1254 {
1255 return false;
1256 }
1257
1258 const gl::Caps &caps = context->getCaps();
1259 if (texture != 0)
1260 {
Geoff Lang23e02842017-10-17 13:24:09 -04001261 if (layer < 0)
1262 {
1263 context->handleError(InvalidValue());
1264 return false;
1265 }
1266
Jamie Madill55ec3b12014-07-03 10:38:57 -04001267 gl::Texture *tex = context->getTexture(texture);
1268 ASSERT(tex);
1269
Corentin Wallez99d492c2018-02-27 15:17:10 -05001270 switch (tex->getType())
Jamie Madill55ec3b12014-07-03 10:38:57 -04001271 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05001272 case TextureType::_2DArray:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001273 {
1274 if (level > gl::log2(caps.max2DTextureSize))
1275 {
Olli Etuahofd162102018-08-27 16:14:57 +03001276 ANGLE_VALIDATION_ERR(context, InvalidValue(),
1277 FramebufferTextureInvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04001278 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001279 }
1280
1281 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1282 {
Olli Etuahofd162102018-08-27 16:14:57 +03001283 ANGLE_VALIDATION_ERR(context, InvalidValue(), FramebufferTextureInvalidLayer);
Geoff Langb1196682014-07-23 13:47:29 -04001284 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001285 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001286 }
1287 break;
1288
Corentin Wallez99d492c2018-02-27 15:17:10 -05001289 case TextureType::_3D:
Jamie Madill55ec3b12014-07-03 10:38:57 -04001290 {
1291 if (level > gl::log2(caps.max3DTextureSize))
1292 {
Olli Etuahofd162102018-08-27 16:14:57 +03001293 ANGLE_VALIDATION_ERR(context, InvalidValue(),
1294 FramebufferTextureInvalidMipLevel);
Geoff Langb1196682014-07-23 13:47:29 -04001295 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001296 }
1297
1298 if (static_cast<GLuint>(layer) >= caps.max3DTextureSize)
1299 {
Olli Etuahofd162102018-08-27 16:14:57 +03001300 ANGLE_VALIDATION_ERR(context, InvalidValue(), FramebufferTextureInvalidLayer);
1301 return false;
1302 }
1303 }
1304 break;
1305
1306 case TextureType::_2DMultisampleArray:
1307 {
1308 if (level != 0)
1309 {
1310 ANGLE_VALIDATION_ERR(context, InvalidValue(),
1311 FramebufferTextureInvalidMipLevel);
1312 return false;
1313 }
1314
1315 if (static_cast<GLuint>(layer) >= caps.maxArrayTextureLayers)
1316 {
1317 ANGLE_VALIDATION_ERR(context, InvalidValue(), FramebufferTextureInvalidLayer);
Geoff Langb1196682014-07-23 13:47:29 -04001318 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001319 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001320 }
1321 break;
1322
He Yunchaoced53ae2016-11-29 15:00:51 +08001323 default:
Olli Etuahofd162102018-08-27 16:14:57 +03001324 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
1325 FramebufferTextureLayerIncorrectTextureType);
He Yunchaoced53ae2016-11-29 15:00:51 +08001326 return false;
Jamie Madill55ec3b12014-07-03 10:38:57 -04001327 }
Geoff Langa9be0dc2014-12-17 12:34:40 -05001328
Corentin Wallez99d492c2018-02-27 15:17:10 -05001329 const auto &format = tex->getFormat(NonCubeTextureTypeToTarget(tex->getType()), level);
Jamie Madilla3944d42016-07-22 22:13:26 -04001330 if (format.info->compressed)
Geoff Langa9be0dc2014-12-17 12:34:40 -05001331 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001332 context->handleError(InvalidOperation());
Geoff Langa9be0dc2014-12-17 12:34:40 -05001333 return false;
1334 }
Jamie Madill55ec3b12014-07-03 10:38:57 -04001335 }
1336
1337 return true;
Jamie Madill570f7c82014-07-03 10:38:54 -04001338}
1339
He Yunchaoced53ae2016-11-29 15:00:51 +08001340bool ValidateInvalidateFramebuffer(Context *context,
1341 GLenum target,
1342 GLsizei numAttachments,
Austin Kinross08332632015-05-05 13:35:47 -07001343 const GLenum *attachments)
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001344{
Martin Radev1be913c2016-07-11 17:59:16 +03001345 if (context->getClientMajorVersion() < 3)
Austin Kinross08332632015-05-05 13:35:47 -07001346 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001347 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinross08332632015-05-05 13:35:47 -07001348 return false;
1349 }
1350
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001351 bool defaultFramebuffer = false;
1352
1353 switch (target)
1354 {
He Yunchaoced53ae2016-11-29 15:00:51 +08001355 case GL_DRAW_FRAMEBUFFER:
1356 case GL_FRAMEBUFFER:
1357 defaultFramebuffer = context->getGLState().getDrawFramebuffer()->id() == 0;
1358 break;
1359 case GL_READ_FRAMEBUFFER:
1360 defaultFramebuffer = context->getGLState().getReadFramebuffer()->id() == 0;
1361 break;
1362 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07001363 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
He Yunchaoced53ae2016-11-29 15:00:51 +08001364 return false;
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001365 }
1366
He Yunchaoced53ae2016-11-29 15:00:51 +08001367 return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
1368 defaultFramebuffer);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001369}
1370
Jamie Madill3ef140a2017-08-26 23:11:21 -04001371bool ValidateInvalidateSubFramebuffer(Context *context,
1372 GLenum target,
1373 GLsizei numAttachments,
1374 const GLenum *attachments,
1375 GLint x,
1376 GLint y,
1377 GLsizei width,
1378 GLsizei height)
1379{
Yunchao He2f3a0dc2018-02-27 22:39:44 +08001380 if (width < 0 || height < 0)
1381 {
1382 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
1383 return false;
1384 }
1385
Jamie Madill3ef140a2017-08-26 23:11:21 -04001386 return ValidateInvalidateFramebuffer(context, target, numAttachments, attachments);
1387}
1388
Jamie Madill5b772312018-03-08 20:28:32 -05001389bool ValidateClearBuffer(Context *context)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001390{
Martin Radev1be913c2016-07-11 17:59:16 +03001391 if (context->getClientMajorVersion() < 3)
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001392 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001393 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001394 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001395 }
1396
Jamie Madill427064d2018-04-13 16:20:34 -04001397 if (!ValidateFramebufferComplete(context, context->getGLState().getDrawFramebuffer()))
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001398 {
Geoff Langb1196682014-07-23 13:47:29 -04001399 return false;
Jamie Madill13f7d7d2014-06-20 13:21:27 -04001400 }
1401
1402 return true;
1403}
1404
Olli Etuaho71dfb362016-03-10 14:04:27 +02001405bool ValidateDrawRangeElements(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04001406 PrimitiveMode mode,
Olli Etuaho71dfb362016-03-10 14:04:27 +02001407 GLuint start,
1408 GLuint end,
1409 GLsizei count,
1410 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001411 const void *indices)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001412{
Martin Radev1be913c2016-07-11 17:59:16 +03001413 if (context->getClientMajorVersion() < 3)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001414 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001415 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho71dfb362016-03-10 14:04:27 +02001416 return false;
1417 }
1418
1419 if (end < start)
1420 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001421 context->handleError(InvalidValue() << "end < start");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001422 return false;
1423 }
1424
Jamie Madill9c9b40a2017-04-26 16:31:57 -04001425 if (!ValidateDrawElementsCommon(context, mode, count, type, indices, 0))
Olli Etuaho71dfb362016-03-10 14:04:27 +02001426 {
1427 return false;
1428 }
1429
Jamie Madill9fdaa492018-02-16 10:52:11 -05001430 // Skip range checks for no-op calls.
1431 if (count <= 0)
1432 {
1433 return true;
1434 }
1435
Jamie Madillc1fd7372018-10-26 22:48:39 -04001436 // Note that resolving the index range is a bit slow. We should probably optimize this.
1437 IndexRange indexRange;
1438 ANGLE_VALIDATION_TRY(context->getGLState().getVertexArray()->getIndexRange(
1439 context, type, count, indices, &indexRange));
Jamie Madill6f5444d2018-03-14 10:08:11 -04001440
1441 if (indexRange.end > end || indexRange.start < start)
Olli Etuaho71dfb362016-03-10 14:04:27 +02001442 {
1443 // GL spec says that behavior in this case is undefined - generating an error is fine.
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001444 context->handleError(InvalidOperation() << "Indices are out of the start, end range.");
Olli Etuaho71dfb362016-03-10 14:04:27 +02001445 return false;
1446 }
1447 return true;
1448}
1449
He Yunchaoced53ae2016-11-29 15:00:51 +08001450bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint *params)
Jamie Madill0063c512014-08-25 15:47:53 -04001451{
Martin Radev1be913c2016-07-11 17:59:16 +03001452 if (context->getClientMajorVersion() < 3)
Jamie Madill0063c512014-08-25 15:47:53 -04001453 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001454 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langb1196682014-07-23 13:47:29 -04001455 return false;
Jamie Madill0063c512014-08-25 15:47:53 -04001456 }
1457
Jamie Madill78f41802014-08-25 15:47:55 -04001458 return ValidateGetUniformBase(context, program, location);
Jamie Madill0063c512014-08-25 15:47:53 -04001459}
1460
Jamie Madillb885e572015-02-03 16:16:04 -05001461bool ValidateReadBuffer(Context *context, GLenum src)
1462{
Martin Radev1be913c2016-07-11 17:59:16 +03001463 if (context->getClientMajorVersion() < 3)
Jamie Madillb885e572015-02-03 16:16:04 -05001464 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001465 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb885e572015-02-03 16:16:04 -05001466 return false;
1467 }
1468
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001469 const Framebuffer *readFBO = context->getGLState().getReadFramebuffer();
Jamie Madillb885e572015-02-03 16:16:04 -05001470
1471 if (readFBO == nullptr)
1472 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001473 context->handleError(InvalidOperation() << "No active read framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001474 return false;
1475 }
1476
1477 if (src == GL_NONE)
1478 {
1479 return true;
1480 }
1481
Olli Etuaho84c9f592016-03-09 14:37:25 +02001482 if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
Jamie Madillb885e572015-02-03 16:16:04 -05001483 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001484 context->handleError(InvalidEnum() << "Unknown enum for 'src' in ReadBuffer");
Jamie Madillb885e572015-02-03 16:16:04 -05001485 return false;
1486 }
1487
1488 if (readFBO->id() == 0)
1489 {
1490 if (src != GL_BACK)
1491 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001492 context->handleError(
1493 InvalidOperation()
1494 << "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.");
Jamie Madillb885e572015-02-03 16:16:04 -05001495 return false;
1496 }
1497 }
1498 else
1499 {
1500 GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
1501
1502 if (drawBuffer >= context->getCaps().maxDrawBuffers)
1503 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001504 context->handleError(InvalidOperation() << "'src' is greater than MAX_DRAW_BUFFERS.");
Jamie Madillb885e572015-02-03 16:16:04 -05001505 return false;
1506 }
1507 }
1508
1509 return true;
1510}
1511
Jamie Madill86af3d22015-07-21 15:14:07 -04001512bool ValidateCompressedTexImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001513 TextureType target,
Jamie Madill86af3d22015-07-21 15:14:07 -04001514 GLint level,
1515 GLenum internalformat,
1516 GLsizei width,
1517 GLsizei height,
1518 GLsizei depth,
1519 GLint border,
1520 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001521 const void *data)
Jamie Madill86af3d22015-07-21 15:14:07 -04001522{
Martin Radev1be913c2016-07-11 17:59:16 +03001523 if (context->getClientMajorVersion() < 3)
Jamie Madill86af3d22015-07-21 15:14:07 -04001524 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001525 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill86af3d22015-07-21 15:14:07 -04001526 return false;
1527 }
1528
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001529 if (!ValidTextureTarget(context, target))
1530 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001531 context->handleError(InvalidEnum());
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001532 return false;
1533 }
1534
Jamie Madille2e406c2016-06-02 13:04:10 -04001535 // Validate image size
1536 if (!ValidImageSizeParameters(context, target, level, width, height, depth, false))
1537 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001538 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001539 return false;
1540 }
1541
Geoff Langca271392017-04-05 12:30:00 -04001542 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001543 if (!formatInfo.compressed)
1544 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001545 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Jamie Madill4b4cdff2016-06-06 13:53:38 -07001546 return false;
1547 }
1548
Jamie Madillca2ff382018-07-11 09:01:17 -04001549 GLuint blockSize = 0;
1550 if (!formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth), &blockSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04001551 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001552 context->handleError(InvalidValue());
Jamie Madille2e406c2016-06-02 13:04:10 -04001553 return false;
1554 }
Jamie Madillca2ff382018-07-11 09:01:17 -04001555
1556 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
Jamie Madill86af3d22015-07-21 15:14:07 -04001557 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001558 context->handleError(InvalidValue());
Jamie Madill86af3d22015-07-21 15:14:07 -04001559 return false;
1560 }
1561
1562 // 3D texture target validation
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001563 if (target != TextureType::_3D && target != TextureType::_2DArray)
Jamie Madill86af3d22015-07-21 15:14:07 -04001564 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001565 context->handleError(InvalidEnum() << "Must specify a valid 3D texture destination target");
Jamie Madill86af3d22015-07-21 15:14:07 -04001566 return false;
1567 }
1568
1569 // validateES3TexImageFormat sets the error code if there is an error
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05001570 if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04001571 0, width, height, depth, border, GL_NONE, GL_NONE, -1,
1572 data))
Jamie Madill86af3d22015-07-21 15:14:07 -04001573 {
1574 return false;
1575 }
1576
1577 return true;
1578}
Austin Kinrossbc781f32015-10-26 09:27:38 -07001579
Corentin Wallezb2931602017-04-11 15:58:57 -04001580bool ValidateCompressedTexImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08001581 TextureType target,
Corentin Wallezb2931602017-04-11 15:58:57 -04001582 GLint level,
1583 GLenum internalformat,
1584 GLsizei width,
1585 GLsizei height,
1586 GLsizei depth,
1587 GLint border,
1588 GLsizei imageSize,
1589 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04001590 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04001591{
1592 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
1593 {
1594 return false;
1595 }
1596
1597 return ValidateCompressedTexImage3D(context, target, level, internalformat, width, height,
1598 depth, border, imageSize, data);
1599}
1600
Austin Kinrossbc781f32015-10-26 09:27:38 -07001601bool ValidateBindVertexArray(Context *context, GLuint array)
1602{
Martin Radev1be913c2016-07-11 17:59:16 +03001603 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001604 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001605 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001606 return false;
1607 }
1608
1609 return ValidateBindVertexArrayBase(context, array);
1610}
1611
Jamie Madilld7576732017-08-26 18:49:50 -04001612bool ValidateIsVertexArray(Context *context, GLuint array)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001613{
Martin Radev1be913c2016-07-11 17:59:16 +03001614 if (context->getClientMajorVersion() < 3)
Austin Kinrossbc781f32015-10-26 09:27:38 -07001615 {
Jamie Madilld7576732017-08-26 18:49:50 -04001616 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Austin Kinrossbc781f32015-10-26 09:27:38 -07001617 return false;
1618 }
1619
1620 return true;
1621}
Geoff Langc5629752015-12-07 16:29:04 -05001622
Jiajia Qin6eafb042016-12-27 17:04:07 +08001623static bool ValidateBindBufferCommon(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001624 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001625 GLuint index,
1626 GLuint buffer,
1627 GLintptr offset,
1628 GLsizeiptr size)
1629{
1630 if (context->getClientMajorVersion() < 3)
1631 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001632 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001633 return false;
1634 }
1635
1636 if (buffer != 0 && offset < 0)
1637 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001638 context->handleError(InvalidValue() << "buffer is non-zero and offset is negative.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001639 return false;
1640 }
1641
1642 if (!context->getGLState().isBindGeneratesResourceEnabled() &&
1643 !context->isBufferGenerated(buffer))
1644 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001645 context->handleError(InvalidOperation() << "Buffer was not generated.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001646 return false;
1647 }
1648
1649 const Caps &caps = context->getCaps();
1650 switch (target)
1651 {
Corentin Wallez336129f2017-10-17 15:55:40 -04001652 case BufferBinding::TransformFeedback:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001653 {
1654 if (index >= caps.maxTransformFeedbackSeparateAttributes)
1655 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001656 context->handleError(InvalidValue() << "index is greater than or equal to the "
1657 "number of TRANSFORM_FEEDBACK_BUFFER "
1658 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001659 return false;
1660 }
1661 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
1662 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001663 context->handleError(InvalidValue() << "offset and size must be multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001664 return false;
1665 }
1666
1667 TransformFeedback *curTransformFeedback =
1668 context->getGLState().getCurrentTransformFeedback();
1669 if (curTransformFeedback && curTransformFeedback->isActive())
1670 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001671 context->handleError(InvalidOperation()
1672 << "target is TRANSFORM_FEEDBACK_BUFFER and transform "
1673 "feedback is currently active.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001674 return false;
1675 }
1676 break;
1677 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001678 case BufferBinding::Uniform:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001679 {
1680 if (index >= caps.maxUniformBufferBindings)
1681 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001682 context->handleError(InvalidValue() << "index is greater than or equal to the "
1683 "number of UNIFORM_BUFFER indexed "
1684 "binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001685 return false;
1686 }
1687
Qin Jiajiaf7af13c2018-06-06 14:14:54 +08001688 ASSERT(caps.uniformBufferOffsetAlignment);
Jiajia Qin6eafb042016-12-27 17:04:07 +08001689 if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
1690 {
1691 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001692 InvalidValue()
1693 << "offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001694 return false;
1695 }
1696 break;
1697 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001698 case BufferBinding::AtomicCounter:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001699 {
1700 if (context->getClientVersion() < ES_3_1)
1701 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001702 context->handleError(InvalidEnum()
1703 << "ATOMIC_COUNTER_BUFFER is not supported before GLES 3.1");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001704 return false;
1705 }
1706 if (index >= caps.maxAtomicCounterBufferBindings)
1707 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001708 context->handleError(InvalidValue() << "index is greater than or equal to the "
1709 "number of ATOMIC_COUNTER_BUFFER "
1710 "indexed binding points.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001711 return false;
1712 }
1713 if (buffer != 0 && (offset % 4) != 0)
1714 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001715 context->handleError(InvalidValue() << "offset must be a multiple of 4.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001716 return false;
1717 }
1718 break;
1719 }
Corentin Wallez336129f2017-10-17 15:55:40 -04001720 case BufferBinding::ShaderStorage:
Jiajia Qin6eafb042016-12-27 17:04:07 +08001721 {
1722 if (context->getClientVersion() < ES_3_1)
1723 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001724 context->handleError(InvalidEnum()
1725 << "SHADER_STORAGE_BUFFER is not supported in GLES3.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001726 return false;
1727 }
1728 if (index >= caps.maxShaderStorageBufferBindings)
1729 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001730 context->handleError(InvalidValue() << "index is greater than or equal to the "
1731 "number of SHADER_STORAGE_BUFFER "
1732 "indexed binding points.");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001733 return false;
1734 }
Qin Jiajiaf7af13c2018-06-06 14:14:54 +08001735 ASSERT(caps.shaderStorageBufferOffsetAlignment);
Jiajia Qinf546e7d2017-03-27 14:12:59 +08001736 if (buffer != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
1737 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001738 context->handleError(InvalidValue() << "offset must be multiple of value of "
1739 "SHADER_STORAGE_BUFFER_OFFSET_"
1740 "ALIGNMENT.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001741 return false;
1742 }
1743 break;
1744 }
1745 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001746 context->handleError(InvalidEnum() << "the target is not supported.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001747 return false;
1748 }
1749
1750 return true;
1751}
1752
Corentin Wallez336129f2017-10-17 15:55:40 -04001753bool ValidateBindBufferBase(Context *context, BufferBinding target, GLuint index, GLuint buffer)
Jiajia Qin6eafb042016-12-27 17:04:07 +08001754{
1755 return ValidateBindBufferCommon(context, target, index, buffer, 0, 0);
1756}
1757
1758bool ValidateBindBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04001759 BufferBinding target,
Jiajia Qin6eafb042016-12-27 17:04:07 +08001760 GLuint index,
1761 GLuint buffer,
1762 GLintptr offset,
1763 GLsizeiptr size)
1764{
1765 if (buffer != 0 && size <= 0)
1766 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001767 context->handleError(InvalidValue()
1768 << "buffer is non-zero and size is less than or equal to zero.");
Jiajia Qin6eafb042016-12-27 17:04:07 +08001769 return false;
1770 }
1771 return ValidateBindBufferCommon(context, target, index, buffer, offset, size);
1772}
1773
Geoff Langc5629752015-12-07 16:29:04 -05001774bool ValidateProgramBinary(Context *context,
1775 GLuint program,
1776 GLenum binaryFormat,
1777 const void *binary,
1778 GLint length)
1779{
Martin Radev1be913c2016-07-11 17:59:16 +03001780 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001781 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001782 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001783 return false;
1784 }
1785
1786 return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
1787}
1788
1789bool ValidateGetProgramBinary(Context *context,
1790 GLuint program,
1791 GLsizei bufSize,
1792 GLsizei *length,
1793 GLenum *binaryFormat,
1794 void *binary)
1795{
Martin Radev1be913c2016-07-11 17:59:16 +03001796 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001797 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001798 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001799 return false;
1800 }
1801
1802 return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
1803}
1804
Olli Etuahof0fee072016-03-30 15:11:58 +03001805bool ValidateProgramParameteri(Context *context, GLuint program, GLenum pname, GLint value)
Geoff Langc5629752015-12-07 16:29:04 -05001806{
Martin Radev1be913c2016-07-11 17:59:16 +03001807 if (context->getClientMajorVersion() < 3)
Geoff Langc5629752015-12-07 16:29:04 -05001808 {
Brandon Jonesafa75152017-07-21 13:11:29 -07001809 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc5629752015-12-07 16:29:04 -05001810 return false;
1811 }
1812
1813 if (GetValidProgram(context, program) == nullptr)
1814 {
1815 return false;
1816 }
1817
1818 switch (pname)
1819 {
1820 case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
Olli Etuahof0fee072016-03-30 15:11:58 +03001821 if (value != GL_FALSE && value != GL_TRUE)
1822 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001823 context->handleError(InvalidValue()
1824 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Olli Etuahof0fee072016-03-30 15:11:58 +03001825 return false;
1826 }
Geoff Langc5629752015-12-07 16:29:04 -05001827 break;
1828
Yunchao He61afff12017-03-14 15:34:03 +08001829 case GL_PROGRAM_SEPARABLE:
1830 if (context->getClientVersion() < ES_3_1)
1831 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001832 context->handleError(InvalidEnum()
1833 << "PROGRAM_SEPARABLE is not supported before GLES 3.1");
Yunchao He61afff12017-03-14 15:34:03 +08001834 return false;
1835 }
1836
1837 if (value != GL_FALSE && value != GL_TRUE)
1838 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001839 context->handleError(InvalidValue()
1840 << "Invalid value, expected GL_FALSE or GL_TRUE: " << value);
Yunchao He61afff12017-03-14 15:34:03 +08001841 return false;
1842 }
1843 break;
1844
Geoff Langc5629752015-12-07 16:29:04 -05001845 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001846 context->handleError(InvalidEnum()
1847 << "Invalid pname: 0x" << std::hex << std::uppercase << pname);
Geoff Langc5629752015-12-07 16:29:04 -05001848 return false;
1849 }
1850
1851 return true;
1852}
Jamie Madillc29968b2016-01-20 11:17:23 -05001853
1854bool ValidateBlitFramebuffer(Context *context,
1855 GLint srcX0,
1856 GLint srcY0,
1857 GLint srcX1,
1858 GLint srcY1,
1859 GLint dstX0,
1860 GLint dstY0,
1861 GLint dstX1,
1862 GLint dstY1,
1863 GLbitfield mask,
1864 GLenum filter)
1865{
Martin Radev1be913c2016-07-11 17:59:16 +03001866 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05001867 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08001868 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05001869 return false;
1870 }
1871
1872 return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
1873 dstX1, dstY1, mask, filter);
Geoff Lange8ebe7f2013-08-05 15:03:13 -04001874}
Jamie Madillc29968b2016-01-20 11:17:23 -05001875
Jamie Madill5b772312018-03-08 20:28:32 -05001876bool ValidateClearBufferiv(Context *context, GLenum buffer, GLint drawbuffer, const GLint *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001877{
1878 switch (buffer)
1879 {
1880 case GL_COLOR:
1881 if (drawbuffer < 0 ||
1882 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1883 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001884 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001885 return false;
1886 }
Geoff Lang76e65652017-03-27 14:58:02 -04001887 if (context->getExtensions().webglCompatibility)
1888 {
1889 constexpr GLenum validComponentTypes[] = {GL_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001890 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001891 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1892 {
1893 return false;
1894 }
1895 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001896 break;
1897
1898 case GL_STENCIL:
1899 if (drawbuffer != 0)
1900 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001901 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001902 return false;
1903 }
1904 break;
1905
1906 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001907 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001908 return false;
1909 }
1910
1911 return ValidateClearBuffer(context);
1912}
1913
Jamie Madill5b772312018-03-08 20:28:32 -05001914bool ValidateClearBufferuiv(Context *context, GLenum buffer, GLint drawbuffer, const GLuint *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001915{
1916 switch (buffer)
1917 {
1918 case GL_COLOR:
1919 if (drawbuffer < 0 ||
1920 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1921 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001922 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001923 return false;
1924 }
Geoff Lang76e65652017-03-27 14:58:02 -04001925 if (context->getExtensions().webglCompatibility)
1926 {
1927 constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
Geoff Lang0fb08642017-07-04 15:07:23 -04001928 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001929 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1930 {
1931 return false;
1932 }
1933 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001934 break;
1935
1936 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001937 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001938 return false;
1939 }
1940
1941 return ValidateClearBuffer(context);
1942}
1943
Jamie Madill5b772312018-03-08 20:28:32 -05001944bool ValidateClearBufferfv(Context *context, GLenum buffer, GLint drawbuffer, const GLfloat *value)
Jamie Madillc29968b2016-01-20 11:17:23 -05001945{
1946 switch (buffer)
1947 {
1948 case GL_COLOR:
1949 if (drawbuffer < 0 ||
1950 static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
1951 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001952 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001953 return false;
1954 }
Geoff Lang76e65652017-03-27 14:58:02 -04001955 if (context->getExtensions().webglCompatibility)
1956 {
1957 constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
1958 GL_SIGNED_NORMALIZED};
Geoff Lang0fb08642017-07-04 15:07:23 -04001959 if (!ValidateWebGLFramebufferAttachmentClearType(
Geoff Lang76e65652017-03-27 14:58:02 -04001960 context, drawbuffer, validComponentTypes, ArraySize(validComponentTypes)))
1961 {
1962 return false;
1963 }
1964 }
Jamie Madillc29968b2016-01-20 11:17:23 -05001965 break;
1966
1967 case GL_DEPTH:
1968 if (drawbuffer != 0)
1969 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001970 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001971 return false;
1972 }
1973 break;
1974
1975 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001976 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05001977 return false;
1978 }
1979
1980 return ValidateClearBuffer(context);
1981}
1982
Jamie Madill5b772312018-03-08 20:28:32 -05001983bool ValidateClearBufferfi(Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001984 GLenum buffer,
1985 GLint drawbuffer,
1986 GLfloat depth,
1987 GLint stencil)
1988{
1989 switch (buffer)
1990 {
1991 case GL_DEPTH_STENCIL:
1992 if (drawbuffer != 0)
1993 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001994 context->handleError(InvalidValue());
Jamie Madillc29968b2016-01-20 11:17:23 -05001995 return false;
1996 }
1997 break;
1998
1999 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002000 context->handleError(InvalidEnum());
Jamie Madillc29968b2016-01-20 11:17:23 -05002001 return false;
2002 }
2003
2004 return ValidateClearBuffer(context);
2005}
2006
Jamie Madill5b772312018-03-08 20:28:32 -05002007bool ValidateDrawBuffers(Context *context, GLsizei n, const GLenum *bufs)
Jamie Madillc29968b2016-01-20 11:17:23 -05002008{
Martin Radev1be913c2016-07-11 17:59:16 +03002009 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05002010 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002011 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05002012 return false;
2013 }
2014
2015 return ValidateDrawBuffersBase(context, n, bufs);
2016}
2017
2018bool ValidateCopyTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002019 TextureType target,
Jamie Madillc29968b2016-01-20 11:17:23 -05002020 GLint level,
2021 GLint xoffset,
2022 GLint yoffset,
2023 GLint zoffset,
2024 GLint x,
2025 GLint y,
2026 GLsizei width,
2027 GLsizei height)
2028{
Martin Radev1be913c2016-07-11 17:59:16 +03002029 if (context->getClientMajorVersion() < 3)
Jamie Madillc29968b2016-01-20 11:17:23 -05002030 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002031 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillc29968b2016-01-20 11:17:23 -05002032 return false;
2033 }
2034
Ian Ewellfc7cf8e2016-01-20 15:57:46 -05002035 return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset,
2036 yoffset, zoffset, x, y, width, height, 0);
Jamie Madillc29968b2016-01-20 11:17:23 -05002037}
2038
Brandon Jones4e6f2ae2018-09-19 11:09:51 -07002039bool ValidateCopyTexture3DANGLE(Context *context,
2040 GLuint sourceId,
2041 GLint sourceLevel,
2042 TextureTarget destTarget,
2043 GLuint destId,
2044 GLint destLevel,
2045 GLint internalFormat,
2046 GLenum destType,
2047 GLboolean unpackFlipY,
2048 GLboolean unpackPremultiplyAlpha,
2049 GLboolean unpackUnmultiplyAlpha)
2050{
2051 const Texture *source = context->getTexture(sourceId);
2052 if (source == nullptr)
2053 {
2054 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSourceTexture);
2055 return false;
2056 }
2057
2058 TextureType sourceType = source->getType();
2059 ASSERT(sourceType != TextureType::CubeMap);
2060 TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
2061 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
2062
2063 const Texture *dest = context->getTexture(destId);
2064 if (dest == nullptr)
2065 {
2066 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidDestinationTexture);
2067 return false;
2068 }
2069
2070 if (!ValidateCopyTexture3DCommon(context, source, sourceLevel,
2071 sourceFormat.info->internalFormat, dest, destLevel,
2072 internalFormat, destTarget))
2073 {
2074 return false;
2075 }
2076
2077 if (!ValidMipLevel(context, source->getType(), sourceLevel))
2078 {
2079 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSourceTextureLevel);
2080 return false;
2081 }
2082
2083 GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
2084 GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
2085 if (sourceWidth == 0 || sourceHeight == 0)
2086 {
2087 ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidSourceTextureSize);
2088 return false;
2089 }
2090
2091 if (dest->getImmutableFormat())
2092 {
2093 ANGLE_VALIDATION_ERR(context, InvalidOperation(), DestinationImmutable);
2094 return false;
2095 }
2096
2097 return true;
2098}
2099
2100bool ValidateCopySubTexture3DANGLE(Context *context,
2101 GLuint sourceId,
2102 GLint sourceLevel,
2103 TextureTarget destTarget,
2104 GLuint destId,
2105 GLint destLevel,
2106 GLint xoffset,
2107 GLint yoffset,
2108 GLint zoffset,
2109 GLint x,
2110 GLint y,
2111 GLint z,
2112 GLsizei width,
2113 GLsizei height,
2114 GLsizei depth,
2115 GLboolean unpackFlipY,
2116 GLboolean unpackPremultiplyAlpha,
2117 GLboolean unpackUnmultiplyAlpha)
2118{
2119 const Texture *source = context->getTexture(sourceId);
2120 if (source == nullptr)
2121 {
2122 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSourceTexture);
2123 return false;
2124 }
2125
2126 TextureType sourceType = source->getType();
2127 ASSERT(sourceType != TextureType::CubeMap);
2128 TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
2129 const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
2130
2131 const Texture *dest = context->getTexture(destId);
2132 if (dest == nullptr)
2133 {
2134 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidDestinationTexture);
2135 return false;
2136 }
2137
2138 const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
2139
2140 if (!ValidateCopyTexture3DCommon(context, source, sourceLevel,
2141 sourceFormat.info->internalFormat, dest, destLevel,
2142 destFormat.internalFormat, destTarget))
2143 {
2144 return false;
2145 }
2146
2147 if (x < 0 || y < 0 || z < 0)
2148 {
2149 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeXYZ);
2150 return false;
2151 }
2152
2153 if (width < 0 || height < 0 || depth < 0)
2154 {
2155 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeHeightWidthDepth);
2156 return false;
2157 }
2158
2159 if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
2160 static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel) ||
2161 static_cast<size_t>(z + depth) > source->getDepth(sourceTarget, sourceLevel))
2162 {
2163 ANGLE_VALIDATION_ERR(context, InvalidValue(), SourceTextureTooSmall);
2164 return false;
2165 }
2166
2167 if (TextureTargetToType(destTarget) != dest->getType())
2168 {
2169 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidDestinationTextureType);
2170 return false;
2171 }
2172
2173 if (xoffset < 0 || yoffset < 0 || zoffset < 0)
2174 {
2175 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
2176 return false;
2177 }
2178
2179 if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
2180 static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel) ||
2181 static_cast<size_t>(zoffset + depth) > dest->getDepth(destTarget, destLevel))
2182 {
2183 ANGLE_VALIDATION_ERR(context, InvalidValue(), DestinationTextureTooSmall);
2184 return false;
2185 }
2186
2187 return true;
2188}
2189
Jamie Madill73a84962016-02-12 09:27:23 -05002190bool ValidateTexImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002191 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05002192 GLint level,
2193 GLint internalformat,
2194 GLsizei width,
2195 GLsizei height,
2196 GLsizei depth,
2197 GLint border,
2198 GLenum format,
2199 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002200 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002201{
Martin Radev1be913c2016-07-11 17:59:16 +03002202 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002203 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002204 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05002205 return false;
2206 }
2207
2208 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
Geoff Langc52f6f12016-10-14 10:18:00 -04002209 0, 0, width, height, depth, border, format, type, -1,
Jamie Madill73a84962016-02-12 09:27:23 -05002210 pixels);
2211}
2212
Geoff Langc52f6f12016-10-14 10:18:00 -04002213bool ValidateTexImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002214 TextureType target,
Geoff Langc52f6f12016-10-14 10:18:00 -04002215 GLint level,
2216 GLint internalformat,
2217 GLsizei width,
2218 GLsizei height,
2219 GLsizei depth,
2220 GLint border,
2221 GLenum format,
2222 GLenum type,
2223 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002224 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002225{
2226 if (context->getClientMajorVersion() < 3)
2227 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002228 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04002229 return false;
2230 }
2231
2232 if (!ValidateRobustEntryPoint(context, bufSize))
2233 {
2234 return false;
2235 }
2236
2237 return ValidateES3TexImage3DParameters(context, target, level, internalformat, false, false, 0,
2238 0, 0, width, height, depth, border, format, type,
2239 bufSize, pixels);
2240}
2241
Jamie Madill73a84962016-02-12 09:27:23 -05002242bool ValidateTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002243 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05002244 GLint level,
2245 GLint xoffset,
2246 GLint yoffset,
2247 GLint zoffset,
2248 GLsizei width,
2249 GLsizei height,
2250 GLsizei depth,
2251 GLenum format,
2252 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04002253 const void *pixels)
Jamie Madill73a84962016-02-12 09:27:23 -05002254{
Martin Radev1be913c2016-07-11 17:59:16 +03002255 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002256 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002257 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05002258 return false;
2259 }
2260
2261 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
2262 yoffset, zoffset, width, height, depth, 0, format, type,
Geoff Langc52f6f12016-10-14 10:18:00 -04002263 -1, pixels);
2264}
2265
2266bool ValidateTexSubImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002267 TextureType target,
Geoff Langc52f6f12016-10-14 10:18:00 -04002268 GLint level,
2269 GLint xoffset,
2270 GLint yoffset,
2271 GLint zoffset,
2272 GLsizei width,
2273 GLsizei height,
2274 GLsizei depth,
2275 GLenum format,
2276 GLenum type,
2277 GLsizei bufSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002278 const void *pixels)
Geoff Langc52f6f12016-10-14 10:18:00 -04002279{
2280 if (context->getClientMajorVersion() < 3)
2281 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002282 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc52f6f12016-10-14 10:18:00 -04002283 return false;
2284 }
2285
2286 if (!ValidateRobustEntryPoint(context, bufSize))
2287 {
2288 return false;
2289 }
2290
2291 return ValidateES3TexImage3DParameters(context, target, level, GL_NONE, false, true, xoffset,
2292 yoffset, zoffset, width, height, depth, 0, format, type,
2293 bufSize, pixels);
Jamie Madill73a84962016-02-12 09:27:23 -05002294}
2295
2296bool ValidateCompressedTexSubImage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002297 TextureType target,
Jamie Madill73a84962016-02-12 09:27:23 -05002298 GLint level,
2299 GLint xoffset,
2300 GLint yoffset,
2301 GLint zoffset,
2302 GLsizei width,
2303 GLsizei height,
2304 GLsizei depth,
2305 GLenum format,
2306 GLsizei imageSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002307 const void *data)
Jamie Madill73a84962016-02-12 09:27:23 -05002308{
Martin Radev1be913c2016-07-11 17:59:16 +03002309 if (context->getClientMajorVersion() < 3)
Jamie Madill73a84962016-02-12 09:27:23 -05002310 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002311 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill73a84962016-02-12 09:27:23 -05002312 return false;
2313 }
2314
Geoff Langca271392017-04-05 12:30:00 -04002315 const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
Geoff Langc5508d62017-02-10 14:58:38 -05002316 if (!formatInfo.compressed)
2317 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002318 context->handleError(InvalidEnum() << "Not a valid compressed texture format");
Geoff Langc5508d62017-02-10 14:58:38 -05002319 return false;
2320 }
2321
Jamie Madillca2ff382018-07-11 09:01:17 -04002322 GLuint blockSize = 0;
2323 if (!formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth), &blockSize))
Jamie Madille2e406c2016-06-02 13:04:10 -04002324 {
Jamie Madillca2ff382018-07-11 09:01:17 -04002325 ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
Jamie Madille2e406c2016-06-02 13:04:10 -04002326 return false;
2327 }
Jamie Madillca2ff382018-07-11 09:01:17 -04002328
2329 if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
Jamie Madill73a84962016-02-12 09:27:23 -05002330 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002331 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002332 return false;
2333 }
2334
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002335 if (!ValidateES3TexImage3DParameters(context, target, level, GL_NONE, true, true, xoffset,
2336 yoffset, zoffset, width, height, depth, 0, format, GL_NONE,
2337 -1, data))
2338 {
2339 return false;
2340 }
2341
Jamie Madill73a84962016-02-12 09:27:23 -05002342 if (!data)
2343 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002344 context->handleError(InvalidValue());
Jamie Madill73a84962016-02-12 09:27:23 -05002345 return false;
2346 }
2347
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002348 return true;
Jamie Madill73a84962016-02-12 09:27:23 -05002349}
Luc Ferron9dbaeba2018-02-01 07:26:59 -05002350
Corentin Wallezb2931602017-04-11 15:58:57 -04002351bool ValidateCompressedTexSubImage3DRobustANGLE(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08002352 TextureType target,
Corentin Wallezb2931602017-04-11 15:58:57 -04002353 GLint level,
2354 GLint xoffset,
2355 GLint yoffset,
2356 GLint zoffset,
2357 GLsizei width,
2358 GLsizei height,
2359 GLsizei depth,
2360 GLenum format,
2361 GLsizei imageSize,
2362 GLsizei dataSize,
Jamie Madill876429b2017-04-20 15:46:24 -04002363 const void *data)
Corentin Wallezb2931602017-04-11 15:58:57 -04002364{
2365 if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
2366 {
2367 return false;
2368 }
2369
2370 return ValidateCompressedTexSubImage3D(context, target, level, xoffset, yoffset, zoffset, width,
2371 height, depth, format, imageSize, data);
2372}
Jamie Madill73a84962016-02-12 09:27:23 -05002373
Olli Etuaho41997e72016-03-10 13:38:39 +02002374bool ValidateGenQueries(Context *context, GLint n, GLuint *)
2375{
2376 return ValidateGenOrDeleteES3(context, n);
2377}
2378
2379bool ValidateDeleteQueries(Context *context, GLint n, const GLuint *)
2380{
2381 return ValidateGenOrDeleteES3(context, n);
2382}
2383
2384bool ValidateGenSamplers(Context *context, GLint count, GLuint *)
2385{
2386 return ValidateGenOrDeleteCountES3(context, count);
2387}
2388
2389bool ValidateDeleteSamplers(Context *context, GLint count, const GLuint *)
2390{
2391 return ValidateGenOrDeleteCountES3(context, count);
2392}
2393
2394bool ValidateGenTransformFeedbacks(Context *context, GLint n, GLuint *)
2395{
2396 return ValidateGenOrDeleteES3(context, n);
2397}
2398
2399bool ValidateDeleteTransformFeedbacks(Context *context, GLint n, const GLuint *ids)
2400{
2401 if (!ValidateGenOrDeleteES3(context, n))
2402 {
2403 return false;
2404 }
2405 for (GLint i = 0; i < n; ++i)
2406 {
2407 auto *transformFeedback = context->getTransformFeedback(ids[i]);
2408 if (transformFeedback != nullptr && transformFeedback->isActive())
2409 {
2410 // ES 3.0.4 section 2.15.1 page 86
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002411 context->handleError(InvalidOperation()
2412 << "Attempt to delete active transform feedback.");
Olli Etuaho41997e72016-03-10 13:38:39 +02002413 return false;
2414 }
2415 }
2416 return true;
2417}
2418
2419bool ValidateGenVertexArrays(Context *context, GLint n, GLuint *)
2420{
2421 return ValidateGenOrDeleteES3(context, n);
2422}
2423
2424bool ValidateDeleteVertexArrays(Context *context, GLint n, const GLuint *)
2425{
2426 return ValidateGenOrDeleteES3(context, n);
2427}
2428
Jamie Madill493f9572018-05-24 19:52:15 -04002429bool ValidateBeginTransformFeedback(Context *context, PrimitiveMode primitiveMode)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002430{
Martin Radev1be913c2016-07-11 17:59:16 +03002431 if (context->getClientMajorVersion() < 3)
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002432 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002433 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002434 return false;
2435 }
2436 switch (primitiveMode)
2437 {
Jamie Madill493f9572018-05-24 19:52:15 -04002438 case PrimitiveMode::Triangles:
2439 case PrimitiveMode::Lines:
2440 case PrimitiveMode::Points:
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002441 break;
2442
2443 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002444 context->handleError(InvalidEnum() << "Invalid primitive mode.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002445 return false;
2446 }
2447
Jamie Madilldfde6ab2016-06-09 07:07:18 -07002448 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002449 ASSERT(transformFeedback != nullptr);
2450
2451 if (transformFeedback->isActive())
2452 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002453 context->handleError(InvalidOperation() << "Transform feedback is already active.");
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002454 return false;
2455 }
Geoff Lang79f71042017-08-14 16:43:43 -04002456
2457 for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
2458 {
2459 const auto &buffer = transformFeedback->getIndexedBuffer(i);
2460 if (buffer.get() && buffer->isMapped())
2461 {
2462 context->handleError(InvalidOperation() << "Transform feedback has a mapped buffer.");
2463 return false;
2464 }
2465 }
2466
Jamie Madill785e8a02018-10-04 17:42:00 -04002467 Program *program = context->getGLState().getLinkedProgram(context);
Olli Etuaho02032bd2017-10-13 18:10:17 +03002468
2469 if (!program)
2470 {
2471 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
2472 return false;
2473 }
2474
2475 if (program->getTransformFeedbackVaryingCount() == 0)
2476 {
2477 ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoTransformFeedbackOutputVariables);
2478 return false;
2479 }
2480
Olli Etuahoc3e55a42016-03-09 16:29:18 +02002481 return true;
2482}
2483
Corentin Wallez336129f2017-10-17 15:55:40 -04002484bool ValidateGetBufferPointerv(Context *context, BufferBinding target, GLenum pname, void **params)
Olli Etuaho4f667482016-03-30 15:56:35 +03002485{
Geoff Lang496c02d2016-10-20 11:38:11 -07002486 return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
2487}
2488
2489bool ValidateGetBufferPointervRobustANGLE(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002490 BufferBinding target,
Geoff Lang496c02d2016-10-20 11:38:11 -07002491 GLenum pname,
2492 GLsizei bufSize,
2493 GLsizei *length,
Jamie Madill876429b2017-04-20 15:46:24 -04002494 void **params)
Geoff Lang496c02d2016-10-20 11:38:11 -07002495{
2496 if (!ValidateRobustEntryPoint(context, bufSize))
Olli Etuaho4f667482016-03-30 15:56:35 +03002497 {
Olli Etuaho4f667482016-03-30 15:56:35 +03002498 return false;
2499 }
2500
Brandon Jonesd1049182018-03-28 10:02:20 -07002501 GLsizei numParams = 0;
2502
2503 if (!ValidateGetBufferPointervBase(context, target, pname, &numParams, params))
Geoff Lang496c02d2016-10-20 11:38:11 -07002504 {
2505 return false;
2506 }
2507
Brandon Jonesd1049182018-03-28 10:02:20 -07002508 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang496c02d2016-10-20 11:38:11 -07002509 {
2510 return false;
2511 }
2512
Brandon Jonesd1049182018-03-28 10:02:20 -07002513 SetRobustLengthParam(length, numParams);
2514
Geoff Lang496c02d2016-10-20 11:38:11 -07002515 return true;
Olli Etuaho4f667482016-03-30 15:56:35 +03002516}
2517
Corentin Wallez336129f2017-10-17 15:55:40 -04002518bool ValidateUnmapBuffer(Context *context, BufferBinding target)
Olli Etuaho4f667482016-03-30 15:56:35 +03002519{
Martin Radev1be913c2016-07-11 17:59:16 +03002520 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002521 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002522 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002523 return false;
2524 }
2525
2526 return ValidateUnmapBufferBase(context, target);
2527}
2528
2529bool ValidateMapBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002530 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002531 GLintptr offset,
2532 GLsizeiptr length,
2533 GLbitfield access)
2534{
Martin Radev1be913c2016-07-11 17:59:16 +03002535 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002536 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002537 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002538 return false;
2539 }
2540
2541 return ValidateMapBufferRangeBase(context, target, offset, length, access);
2542}
2543
2544bool ValidateFlushMappedBufferRange(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002545 BufferBinding target,
Olli Etuaho4f667482016-03-30 15:56:35 +03002546 GLintptr offset,
2547 GLsizeiptr length)
2548{
Martin Radev1be913c2016-07-11 17:59:16 +03002549 if (context->getClientMajorVersion() < 3)
Olli Etuaho4f667482016-03-30 15:56:35 +03002550 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002551 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Olli Etuaho4f667482016-03-30 15:56:35 +03002552 return false;
2553 }
2554
2555 return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
2556}
2557
Jamie Madill5b772312018-03-08 20:28:32 -05002558bool ValidateIndexedStateQuery(Context *context, GLenum pname, GLuint index, GLsizei *length)
Martin Radev66fb8202016-07-28 11:45:20 +03002559{
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002560 if (length)
2561 {
2562 *length = 0;
2563 }
2564
Martin Radev66fb8202016-07-28 11:45:20 +03002565 GLenum nativeType;
2566 unsigned int numParams;
2567 if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
2568 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002569 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002570 return false;
2571 }
2572
2573 const Caps &caps = context->getCaps();
2574 switch (pname)
2575 {
2576 case GL_TRANSFORM_FEEDBACK_BUFFER_START:
2577 case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
2578 case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
2579 if (index >= caps.maxTransformFeedbackSeparateAttributes)
2580 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002581 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002582 return false;
2583 }
2584 break;
2585
2586 case GL_UNIFORM_BUFFER_START:
2587 case GL_UNIFORM_BUFFER_SIZE:
2588 case GL_UNIFORM_BUFFER_BINDING:
2589 if (index >= caps.maxUniformBufferBindings)
2590 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002591 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002592 return false;
2593 }
2594 break;
Shao80957d92017-02-20 21:25:59 +08002595
Martin Radev66fb8202016-07-28 11:45:20 +03002596 case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
2597 case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
2598 if (index >= 3u)
2599 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002600 context->handleError(InvalidValue());
Martin Radev66fb8202016-07-28 11:45:20 +03002601 return false;
2602 }
2603 break;
Shao80957d92017-02-20 21:25:59 +08002604
Jiajia Qin6eafb042016-12-27 17:04:07 +08002605 case GL_ATOMIC_COUNTER_BUFFER_START:
2606 case GL_ATOMIC_COUNTER_BUFFER_SIZE:
2607 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
2608 if (context->getClientVersion() < ES_3_1)
2609 {
2610 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002611 InvalidEnum()
2612 << "Atomic Counter buffers are not supported in this version of GL");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002613 return false;
2614 }
2615 if (index >= caps.maxAtomicCounterBufferBindings)
2616 {
2617 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002618 InvalidValue()
2619 << "index is outside the valid range for GL_ATOMIC_COUNTER_BUFFER_BINDING");
Jiajia Qin6eafb042016-12-27 17:04:07 +08002620 return false;
2621 }
2622 break;
Shao80957d92017-02-20 21:25:59 +08002623
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002624 case GL_SHADER_STORAGE_BUFFER_START:
2625 case GL_SHADER_STORAGE_BUFFER_SIZE:
2626 case GL_SHADER_STORAGE_BUFFER_BINDING:
2627 if (context->getClientVersion() < ES_3_1)
2628 {
2629 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002630 InvalidEnum()
2631 << "Shader storage buffers are not supported in this version of GL");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002632 return false;
2633 }
2634 if (index >= caps.maxShaderStorageBufferBindings)
2635 {
2636 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002637 InvalidValue()
2638 << "index is outside the valid range for GL_SHADER_STORAGE_BUFFER_BINDING");
Jiajia Qinf546e7d2017-03-27 14:12:59 +08002639 return false;
2640 }
2641 break;
2642
Shao80957d92017-02-20 21:25:59 +08002643 case GL_VERTEX_BINDING_BUFFER:
2644 case GL_VERTEX_BINDING_DIVISOR:
2645 case GL_VERTEX_BINDING_OFFSET:
2646 case GL_VERTEX_BINDING_STRIDE:
2647 if (context->getClientVersion() < ES_3_1)
2648 {
2649 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002650 InvalidEnum()
2651 << "Vertex Attrib Bindings are not supported in this version of GL");
Shao80957d92017-02-20 21:25:59 +08002652 return false;
2653 }
2654 if (index >= caps.maxVertexAttribBindings)
2655 {
2656 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002657 InvalidValue()
2658 << "bindingindex must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08002659 return false;
2660 }
2661 break;
Jiawei Shaodb342272017-09-27 10:21:45 +08002662 case GL_SAMPLE_MASK_VALUE:
2663 if (context->getClientVersion() < ES_3_1)
2664 {
2665 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2666 return false;
2667 }
2668 if (index >= caps.maxSampleMaskWords)
2669 {
2670 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidSampleMaskNumber);
2671 return false;
2672 }
2673 break;
Xinghua Cao9c8e1a32017-12-06 17:59:58 +08002674 case GL_IMAGE_BINDING_NAME:
2675 case GL_IMAGE_BINDING_LEVEL:
2676 case GL_IMAGE_BINDING_LAYERED:
2677 case GL_IMAGE_BINDING_LAYER:
2678 case GL_IMAGE_BINDING_ACCESS:
2679 case GL_IMAGE_BINDING_FORMAT:
2680 if (context->getClientVersion() < ES_3_1)
2681 {
2682 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumRequiresGLES31);
2683 return false;
2684 }
2685 if (index >= caps.maxImageUnits)
2686 {
2687 ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidImageUnit);
2688 return false;
2689 }
2690 break;
Martin Radev66fb8202016-07-28 11:45:20 +03002691 default:
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002692 context->handleError(InvalidEnum());
Martin Radev66fb8202016-07-28 11:45:20 +03002693 return false;
2694 }
2695
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002696 if (length)
Martin Radev66fb8202016-07-28 11:45:20 +03002697 {
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002698 *length = 1;
Martin Radev66fb8202016-07-28 11:45:20 +03002699 }
2700
2701 return true;
2702}
2703
Jamie Madill5b772312018-03-08 20:28:32 -05002704bool ValidateGetIntegeri_v(Context *context, GLenum target, GLuint index, GLint *data)
Martin Radev66fb8202016-07-28 11:45:20 +03002705{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002706 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002707 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002708 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002709 return false;
2710 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002711 return ValidateIndexedStateQuery(context, target, index, nullptr);
Martin Radev66fb8202016-07-28 11:45:20 +03002712}
2713
Jamie Madill5b772312018-03-08 20:28:32 -05002714bool ValidateGetIntegeri_vRobustANGLE(Context *context,
Geoff Langcf255ea2016-10-20 11:39:09 -07002715 GLenum target,
2716 GLuint index,
2717 GLsizei bufSize,
2718 GLsizei *length,
2719 GLint *data)
2720{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002721 if (context->getClientVersion() < ES_3_0)
Geoff Langcf255ea2016-10-20 11:39:09 -07002722 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002723 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langcf255ea2016-10-20 11:39:09 -07002724 return false;
2725 }
2726
2727 if (!ValidateRobustEntryPoint(context, bufSize))
2728 {
2729 return false;
2730 }
2731
Brandon Jonesd1049182018-03-28 10:02:20 -07002732 GLsizei numParams = 0;
2733
2734 if (!ValidateIndexedStateQuery(context, target, index, &numParams))
Geoff Langcf255ea2016-10-20 11:39:09 -07002735 {
2736 return false;
2737 }
2738
Brandon Jonesd1049182018-03-28 10:02:20 -07002739 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Langcf255ea2016-10-20 11:39:09 -07002740 {
2741 return false;
2742 }
2743
Brandon Jonesd1049182018-03-28 10:02:20 -07002744 SetRobustLengthParam(length, numParams);
2745
Geoff Langcf255ea2016-10-20 11:39:09 -07002746 return true;
2747}
2748
Jamie Madill5b772312018-03-08 20:28:32 -05002749bool ValidateGetInteger64i_v(Context *context, GLenum target, GLuint index, GLint64 *data)
Martin Radev66fb8202016-07-28 11:45:20 +03002750{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002751 if (context->getClientVersion() < ES_3_0)
Martin Radev66fb8202016-07-28 11:45:20 +03002752 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002753 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Martin Radev66fb8202016-07-28 11:45:20 +03002754 return false;
2755 }
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002756 return ValidateIndexedStateQuery(context, target, index, nullptr);
2757}
2758
Jamie Madill5b772312018-03-08 20:28:32 -05002759bool ValidateGetInteger64i_vRobustANGLE(Context *context,
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002760 GLenum target,
2761 GLuint index,
2762 GLsizei bufSize,
2763 GLsizei *length,
2764 GLint64 *data)
2765{
Geoff Langeb66a6e2016-10-31 13:06:12 -04002766 if (context->getClientVersion() < ES_3_0)
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002767 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002768 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002769 return false;
2770 }
2771
2772 if (!ValidateRobustEntryPoint(context, bufSize))
2773 {
2774 return false;
2775 }
2776
Brandon Jonesd1049182018-03-28 10:02:20 -07002777 GLsizei numParams = 0;
2778
2779 if (!ValidateIndexedStateQuery(context, target, index, &numParams))
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002780 {
2781 return false;
2782 }
2783
Brandon Jonesd1049182018-03-28 10:02:20 -07002784 if (!ValidateRobustBufferSize(context, bufSize, numParams))
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002785 {
2786 return false;
2787 }
2788
Brandon Jonesd1049182018-03-28 10:02:20 -07002789 SetRobustLengthParam(length, numParams);
2790
Geoff Lang2e43dbb2016-10-14 12:27:35 -04002791 return true;
Martin Radev66fb8202016-07-28 11:45:20 +03002792}
2793
Jamie Madill5b772312018-03-08 20:28:32 -05002794bool ValidateCopyBufferSubData(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04002795 BufferBinding readTarget,
2796 BufferBinding writeTarget,
Jamie Madillb0817d12016-11-01 15:48:31 -04002797 GLintptr readOffset,
2798 GLintptr writeOffset,
2799 GLsizeiptr size)
2800{
2801 if (context->getClientMajorVersion() < 3)
2802 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002803 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madillb0817d12016-11-01 15:48:31 -04002804 return false;
2805 }
2806
Corentin Walleze4477002017-12-01 14:39:58 -05002807 if (!context->isValidBufferBinding(readTarget) || !context->isValidBufferBinding(writeTarget))
Jamie Madillb0817d12016-11-01 15:48:31 -04002808 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002809 context->handleError(InvalidEnum() << "Invalid buffer target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002810 return false;
2811 }
2812
2813 Buffer *readBuffer = context->getGLState().getTargetBuffer(readTarget);
2814 Buffer *writeBuffer = context->getGLState().getTargetBuffer(writeTarget);
2815
2816 if (!readBuffer || !writeBuffer)
2817 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002818 context->handleError(InvalidOperation() << "No buffer bound to target");
Jamie Madillb0817d12016-11-01 15:48:31 -04002819 return false;
2820 }
2821
2822 // Verify that readBuffer and writeBuffer are not currently mapped
2823 if (readBuffer->isMapped() || writeBuffer->isMapped())
2824 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002825 context->handleError(InvalidOperation()
2826 << "Cannot call CopyBufferSubData on a mapped buffer");
Jamie Madillb0817d12016-11-01 15:48:31 -04002827 return false;
2828 }
2829
James Darpiniane8a93c62018-01-04 18:02:24 -08002830 if (context->getExtensions().webglCompatibility &&
2831 (readBuffer->isBoundForTransformFeedbackAndOtherUse() ||
2832 writeBuffer->isBoundForTransformFeedbackAndOtherUse()))
2833 {
2834 ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferBoundForTransformFeedback);
2835 return false;
2836 }
2837
Jamie Madilld2f0c742016-11-02 10:34:41 -04002838 CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
2839 CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
2840 CheckedNumeric<GLintptr> checkedSize(size);
2841
2842 auto checkedReadSum = checkedReadOffset + checkedSize;
2843 auto checkedWriteSum = checkedWriteOffset + checkedSize;
2844
2845 if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
2846 !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
2847 !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
Jamie Madillb0817d12016-11-01 15:48:31 -04002848 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002849 context->handleError(InvalidValue() << "Integer overflow when validating copy offsets.");
Jamie Madillb0817d12016-11-01 15:48:31 -04002850 return false;
2851 }
2852
Jamie Madilld2f0c742016-11-02 10:34:41 -04002853 if (readOffset < 0 || writeOffset < 0 || size < 0)
Jamie Madillb0817d12016-11-01 15:48:31 -04002854 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002855 context->handleError(InvalidValue()
2856 << "readOffset, writeOffset and size must all be non-negative");
Jamie Madillb0817d12016-11-01 15:48:31 -04002857 return false;
2858 }
2859
Jamie Madilld2f0c742016-11-02 10:34:41 -04002860 if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
2861 checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
2862 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002863 context->handleError(InvalidValue() << "Buffer offset overflow in CopyBufferSubData");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002864 return false;
2865 }
2866
2867 if (readBuffer == writeBuffer)
2868 {
2869 auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
2870 if (!checkedOffsetDiff.IsValid())
2871 {
2872 // This shold not be possible.
2873 UNREACHABLE();
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002874 context->handleError(InvalidValue()
2875 << "Integer overflow when validating same buffer copy.");
Jamie Madilld2f0c742016-11-02 10:34:41 -04002876 return false;
2877 }
2878
2879 if (checkedOffsetDiff.ValueOrDie() < size)
2880 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002881 context->handleError(InvalidValue());
Jamie Madilld2f0c742016-11-02 10:34:41 -04002882 return false;
2883 }
2884 }
2885
Jamie Madillb0817d12016-11-01 15:48:31 -04002886 return true;
2887}
2888
Geoff Langc339c4e2016-11-29 10:37:36 -05002889bool ValidateGetStringi(Context *context, GLenum name, GLuint index)
2890{
2891 if (context->getClientMajorVersion() < 3)
2892 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002893 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langc339c4e2016-11-29 10:37:36 -05002894 return false;
2895 }
2896
2897 switch (name)
2898 {
2899 case GL_EXTENSIONS:
2900 if (index >= context->getExtensionStringCount())
2901 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002902 context->handleError(InvalidValue()
2903 << "index must be less than the number of extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002904 return false;
2905 }
2906 break;
2907
2908 case GL_REQUESTABLE_EXTENSIONS_ANGLE:
2909 if (!context->getExtensions().requestExtension)
2910 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002911 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002912 return false;
2913 }
2914 if (index >= context->getRequestableExtensionStringCount())
2915 {
2916 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002917 InvalidValue()
2918 << "index must be less than the number of requestable extension strings.");
Geoff Langc339c4e2016-11-29 10:37:36 -05002919 return false;
2920 }
2921 break;
2922
2923 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07002924 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
Geoff Langc339c4e2016-11-29 10:37:36 -05002925 return false;
2926 }
2927
2928 return true;
2929}
2930
Jamie Madill5b772312018-03-08 20:28:32 -05002931bool ValidateRenderbufferStorageMultisample(Context *context,
Jamie Madille8fb6402017-02-14 17:56:40 -05002932 GLenum target,
2933 GLsizei samples,
2934 GLenum internalformat,
2935 GLsizei width,
2936 GLsizei height)
2937{
2938 if (context->getClientMajorVersion() < 3)
2939 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08002940 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madille8fb6402017-02-14 17:56:40 -05002941 return false;
2942 }
2943
2944 if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width,
2945 height))
2946 {
2947 return false;
2948 }
2949
2950 // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
Yunchao Hec0810202018-01-22 09:48:48 +08002951 // format if samples is greater than zero. In ES3.1(section 9.2.5), it can support integer
2952 // multisample renderbuffer, but the samples should not be greater than MAX_INTEGER_SAMPLES.
Geoff Langca271392017-04-05 12:30:00 -04002953 const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
Yunchao Hec0810202018-01-22 09:48:48 +08002954 if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT))
Jamie Madille8fb6402017-02-14 17:56:40 -05002955 {
Yunchao Hec0810202018-01-22 09:48:48 +08002956 if ((samples > 0 && context->getClientVersion() == ES_3_0) ||
2957 static_cast<GLuint>(samples) > context->getCaps().maxIntegerSamples)
2958 {
2959 context->handleError(InvalidOperation());
2960 return false;
2961 }
Jamie Madille8fb6402017-02-14 17:56:40 -05002962 }
2963
2964 // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
2965 const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
2966 if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
2967 {
2968 context->handleError(
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05002969 InvalidOperation()
2970 << "Samples must not be greater than maximum supported value for the format.");
Jamie Madille8fb6402017-02-14 17:56:40 -05002971 return false;
2972 }
2973
2974 return true;
2975}
2976
Jamie Madill5b772312018-03-08 20:28:32 -05002977bool ValidateVertexAttribIPointer(Context *context,
Geoff Langaa086d62017-03-23 16:47:21 -04002978 GLuint index,
2979 GLint size,
2980 GLenum type,
2981 GLsizei stride,
Jamie Madill876429b2017-04-20 15:46:24 -04002982 const void *pointer)
Geoff Langaa086d62017-03-23 16:47:21 -04002983{
2984 if (context->getClientMajorVersion() < 3)
2985 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002986 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Langaa086d62017-03-23 16:47:21 -04002987 return false;
2988 }
2989
Shao80957d92017-02-20 21:25:59 +08002990 if (!ValidateVertexFormatBase(context, index, size, type, true))
Geoff Langaa086d62017-03-23 16:47:21 -04002991 {
Geoff Langaa086d62017-03-23 16:47:21 -04002992 return false;
2993 }
2994
Geoff Langaa086d62017-03-23 16:47:21 -04002995 if (stride < 0)
2996 {
Brandon Jonesafa75152017-07-21 13:11:29 -07002997 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
Geoff Langaa086d62017-03-23 16:47:21 -04002998 return false;
2999 }
3000
Shao80957d92017-02-20 21:25:59 +08003001 const Caps &caps = context->getCaps();
3002 if (context->getClientVersion() >= ES_3_1)
3003 {
3004 if (stride > caps.maxVertexAttribStride)
3005 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003006 context->handleError(InvalidValue()
3007 << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
Shao80957d92017-02-20 21:25:59 +08003008 return false;
3009 }
3010
3011 // [OpenGL ES 3.1] Section 10.3.1 page 245:
3012 // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
3013 // validation should be inherited.
3014 if (index >= caps.maxVertexAttribBindings)
3015 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003016 context->handleError(InvalidValue()
3017 << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
Shao80957d92017-02-20 21:25:59 +08003018 return false;
3019 }
3020 }
3021
Geoff Langaa086d62017-03-23 16:47:21 -04003022 // [OpenGL ES 3.0.2] Section 2.8 page 24:
3023 // An INVALID_OPERATION error is generated when a non-zero vertex array object
3024 // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
3025 // and the pointer argument is not NULL.
3026 if (context->getGLState().getVertexArrayId() != 0 &&
Corentin Wallez336129f2017-10-17 15:55:40 -04003027 context->getGLState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
Geoff Langaa086d62017-03-23 16:47:21 -04003028 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003029 context
3030 ->handleError(InvalidOperation()
3031 << "Client data cannot be used with a non-default vertex array object.");
Geoff Langaa086d62017-03-23 16:47:21 -04003032 return false;
3033 }
3034
Geoff Lang2d62ab72017-03-23 16:54:40 -04003035 if (context->getExtensions().webglCompatibility)
3036 {
3037 if (!ValidateWebGLVertexAttribPointer(context, type, false, stride, pointer, true))
3038 {
3039 return false;
3040 }
3041 }
3042
Geoff Langaa086d62017-03-23 16:47:21 -04003043 return true;
3044}
3045
Geoff Lang38f2cfb2017-04-11 15:23:08 -04003046bool ValidateGetSynciv(Context *context,
3047 GLsync sync,
3048 GLenum pname,
3049 GLsizei bufSize,
3050 GLsizei *length,
3051 GLint *values)
3052{
3053 if (context->getClientMajorVersion() < 3)
3054 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003055 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04003056 return false;
3057 }
3058
3059 if (bufSize < 0)
3060 {
Brandon Jonesafa75152017-07-21 13:11:29 -07003061 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04003062 return false;
3063 }
3064
Jamie Madill70b5bb02017-08-28 13:32:37 -04003065 Sync *syncObject = context->getSync(sync);
3066 if (!syncObject)
Geoff Lang38f2cfb2017-04-11 15:23:08 -04003067 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05003068 context->handleError(InvalidValue() << "Invalid sync object.");
Geoff Lang38f2cfb2017-04-11 15:23:08 -04003069 return false;
3070 }
3071
3072 switch (pname)
3073 {
3074 case GL_OBJECT_TYPE:
3075 case GL_SYNC_CONDITION:
3076 case GL_SYNC_FLAGS:
3077 case GL_SYNC_STATUS:
3078 break;
3079
3080 default:
Brandon Jonesafa75152017-07-21 13:11:29 -07003081 ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPname);
Geoff Lang38f2cfb2017-04-11 15:23:08 -04003082 return false;
3083 }
3084
3085 return true;
3086}
3087
Jamie Madill5b772312018-03-08 20:28:32 -05003088bool ValidateDrawElementsInstanced(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003089 PrimitiveMode mode,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003090 GLsizei count,
3091 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04003092 const void *indices,
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003093 GLsizei instanceCount)
3094{
3095 if (context->getClientMajorVersion() < 3)
3096 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003097 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill9c9b40a2017-04-26 16:31:57 -04003098 return false;
3099 }
3100
3101 return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
3102}
3103
Austin Eng1bf18ce2018-10-19 15:34:02 -07003104bool ValidateMultiDrawArraysInstancedANGLE(Context *context,
3105 PrimitiveMode mode,
3106 const GLint *firsts,
3107 const GLsizei *counts,
3108 const GLsizei *instanceCounts,
3109 GLsizei drawcount)
3110{
3111 if (!context->getExtensions().multiDraw)
3112 {
3113 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3114 return false;
3115 }
3116 if (context->getClientMajorVersion() < 3)
3117 {
3118 if (!context->getExtensions().instancedArrays)
3119 {
3120 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3121 return false;
3122 }
3123 if (!ValidateDrawInstancedANGLE(context))
3124 {
3125 return false;
3126 }
3127 }
3128 for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
3129 {
3130 if (!ValidateDrawArraysInstancedBase(context, mode, firsts[drawID], counts[drawID],
3131 instanceCounts[drawID]))
3132 {
3133 return false;
3134 }
3135 }
3136 return true;
3137}
3138
3139bool ValidateMultiDrawElementsInstancedANGLE(Context *context,
3140 PrimitiveMode mode,
3141 const GLsizei *counts,
3142 GLenum type,
3143 const GLsizei *offsets,
3144 const GLsizei *instanceCounts,
3145 GLsizei drawcount)
3146{
3147 if (!context->getExtensions().multiDraw)
3148 {
3149 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3150 return false;
3151 }
3152 if (context->getClientMajorVersion() < 3)
3153 {
3154 if (!context->getExtensions().instancedArrays)
3155 {
3156 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
3157 return false;
3158 }
3159 if (!ValidateDrawInstancedANGLE(context))
3160 {
3161 return false;
3162 }
3163 }
3164 for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
3165 {
3166 const void *indices = reinterpret_cast<void *>(static_cast<long>(offsets[drawID]));
3167 if (!ValidateDrawElementsInstancedCommon(context, mode, counts[drawID], type, indices,
3168 instanceCounts[drawID]))
3169 {
3170 return false;
3171 }
3172 }
3173 return true;
3174}
3175
Martin Radev137032d2017-07-13 10:11:12 +03003176bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
3177 GLenum target,
3178 GLenum attachment,
3179 GLuint texture,
3180 GLint level,
3181 GLint baseViewIndex,
3182 GLsizei numViews)
3183{
Martin Radev137032d2017-07-13 10:11:12 +03003184 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
3185 numViews))
3186 {
3187 return false;
3188 }
3189
Martin Radev137032d2017-07-13 10:11:12 +03003190 if (texture != 0)
3191 {
Martin Radev14b21262017-08-25 13:54:37 +03003192 if (baseViewIndex < 0)
3193 {
3194 context->handleError(InvalidValue() << "baseViewIndex cannot be less than 0.");
3195 return false;
3196 }
3197
Martin Radev137032d2017-07-13 10:11:12 +03003198 Texture *tex = context->getTexture(texture);
3199 ASSERT(tex);
3200
Corentin Wallez99d492c2018-02-27 15:17:10 -05003201 switch (tex->getType())
Martin Radev137032d2017-07-13 10:11:12 +03003202 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05003203 case TextureType::_2DArray:
Olli Etuaho2c8f0842018-09-12 14:44:55 +03003204 case TextureType::_2DMultisampleArray:
Martin Radev137032d2017-07-13 10:11:12 +03003205 {
Olli Etuaho2c8f0842018-09-12 14:44:55 +03003206 if (tex->getType() == TextureType::_2DMultisampleArray)
3207 {
3208 if (!context->getExtensions().multiviewMultisample)
3209 {
3210 context->handleError(InvalidOperation()
3211 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
3212 return false;
3213 }
3214 }
3215
Martin Radev137032d2017-07-13 10:11:12 +03003216 const Caps &caps = context->getCaps();
3217 if (static_cast<GLuint>(baseViewIndex + numViews) > caps.maxArrayTextureLayers)
3218 {
3219 context->handleError(InvalidValue() << "baseViewIndex+numViews cannot be "
3220 "greater than "
3221 "GL_MAX_ARRAY_TEXTURE_LAYERS.");
3222 return false;
3223 }
Olli Etuaho2c8f0842018-09-12 14:44:55 +03003224
3225 break;
Martin Radev137032d2017-07-13 10:11:12 +03003226 }
Martin Radev137032d2017-07-13 10:11:12 +03003227 default:
3228 context->handleError(InvalidOperation()
3229 << "Texture's target must be GL_TEXTURE_2D_ARRAY.");
3230 return false;
3231 }
3232
3233 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
3234 {
3235 return false;
3236 }
3237 }
3238
3239 return true;
3240}
3241
3242bool ValidateFramebufferTextureMultiviewSideBySideANGLE(Context *context,
3243 GLenum target,
3244 GLenum attachment,
3245 GLuint texture,
3246 GLint level,
3247 GLsizei numViews,
3248 const GLint *viewportOffsets)
3249{
3250 if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, target, attachment, texture, level,
3251 numViews))
3252 {
3253 return false;
3254 }
3255
Martin Radev137032d2017-07-13 10:11:12 +03003256 if (texture != 0)
3257 {
Martin Radev14b21262017-08-25 13:54:37 +03003258 const GLsizei numViewportOffsetValues = numViews * 2;
3259 for (GLsizei i = 0; i < numViewportOffsetValues; ++i)
3260 {
3261 if (viewportOffsets[i] < 0)
3262 {
3263 context->handleError(InvalidValue()
3264 << "viewportOffsets cannot contain negative values.");
3265 return false;
3266 }
3267 }
3268
Martin Radev137032d2017-07-13 10:11:12 +03003269 Texture *tex = context->getTexture(texture);
3270 ASSERT(tex);
3271
Corentin Wallez99d492c2018-02-27 15:17:10 -05003272 switch (tex->getType())
Martin Radev137032d2017-07-13 10:11:12 +03003273 {
Corentin Wallez99d492c2018-02-27 15:17:10 -05003274 case TextureType::_2D:
Martin Radev137032d2017-07-13 10:11:12 +03003275 break;
3276 default:
3277 context->handleError(InvalidOperation()
3278 << "Texture's target must be GL_TEXTURE_2D.");
3279 return false;
3280 }
3281
3282 if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, tex, level))
3283 {
3284 return false;
3285 }
3286 }
3287
3288 return true;
3289}
3290
Jamie Madillff325f12017-08-26 15:06:05 -04003291bool ValidateUniform1ui(Context *context, GLint location, GLuint v0)
3292{
3293 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, 1);
3294}
3295
3296bool ValidateUniform2ui(Context *context, GLint location, GLuint v0, GLuint v1)
3297{
3298 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, 1);
3299}
3300
3301bool ValidateUniform3ui(Context *context, GLint location, GLuint v0, GLuint v1, GLuint v2)
3302{
3303 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, 1);
3304}
3305
3306bool ValidateUniform4ui(Context *context,
3307 GLint location,
3308 GLuint v0,
3309 GLuint v1,
3310 GLuint v2,
3311 GLuint v3)
3312{
3313 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, 1);
3314}
3315
3316bool ValidateUniform1uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
3317{
3318 return ValidateUniformES3(context, GL_UNSIGNED_INT, location, count);
3319}
3320
3321bool ValidateUniform2uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
3322{
3323 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC2, location, count);
3324}
3325
3326bool ValidateUniform3uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
3327{
3328 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC3, location, count);
3329}
3330
3331bool ValidateUniform4uiv(Context *context, GLint location, GLsizei count, const GLuint *value)
3332{
3333 return ValidateUniformES3(context, GL_UNSIGNED_INT_VEC4, location, count);
3334}
3335
Jamie Madillf0e04492017-08-26 15:28:42 -04003336bool ValidateIsQuery(Context *context, GLuint id)
3337{
3338 if (context->getClientMajorVersion() < 3)
3339 {
3340 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3341 return false;
3342 }
3343
3344 return true;
3345}
3346
Jamie Madillc8c95812017-08-26 18:40:09 -04003347bool ValidateUniformMatrix2x3fv(Context *context,
3348 GLint location,
3349 GLsizei count,
3350 GLboolean transpose,
3351 const GLfloat *value)
3352{
3353 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x3, location, count, transpose);
3354}
3355
3356bool ValidateUniformMatrix3x2fv(Context *context,
3357 GLint location,
3358 GLsizei count,
3359 GLboolean transpose,
3360 const GLfloat *value)
3361{
3362 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x2, location, count, transpose);
3363}
3364
3365bool ValidateUniformMatrix2x4fv(Context *context,
3366 GLint location,
3367 GLsizei count,
3368 GLboolean transpose,
3369 const GLfloat *value)
3370{
3371 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT2x4, location, count, transpose);
3372}
3373
3374bool ValidateUniformMatrix4x2fv(Context *context,
3375 GLint location,
3376 GLsizei count,
3377 GLboolean transpose,
3378 const GLfloat *value)
3379{
3380 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x2, location, count, transpose);
3381}
3382
3383bool ValidateUniformMatrix3x4fv(Context *context,
3384 GLint location,
3385 GLsizei count,
3386 GLboolean transpose,
3387 const GLfloat *value)
3388{
3389 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT3x4, location, count, transpose);
3390}
3391
3392bool ValidateUniformMatrix4x3fv(Context *context,
3393 GLint location,
3394 GLsizei count,
3395 GLboolean transpose,
3396 const GLfloat *value)
3397{
3398 return ValidateUniformMatrixES3(context, GL_FLOAT_MAT4x3, location, count, transpose);
3399}
3400
Jamie Madillf0dcb8b2017-08-26 19:05:13 -04003401bool ValidateEndTransformFeedback(Context *context)
3402{
3403 if (context->getClientMajorVersion() < 3)
3404 {
3405 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3406 return false;
3407 }
3408
3409 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3410 ASSERT(transformFeedback != nullptr);
3411
3412 if (!transformFeedback->isActive())
3413 {
3414 context->handleError(InvalidOperation());
3415 return false;
3416 }
3417
3418 return true;
3419}
3420
3421bool ValidateTransformFeedbackVaryings(Context *context,
3422 GLuint program,
3423 GLsizei count,
3424 const GLchar *const *varyings,
3425 GLenum bufferMode)
3426{
3427 if (context->getClientMajorVersion() < 3)
3428 {
3429 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3430 return false;
3431 }
3432
3433 if (count < 0)
3434 {
3435 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
3436 return false;
3437 }
3438
3439 switch (bufferMode)
3440 {
3441 case GL_INTERLEAVED_ATTRIBS:
3442 break;
3443 case GL_SEPARATE_ATTRIBS:
3444 {
3445 const Caps &caps = context->getCaps();
3446 if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
3447 {
3448 context->handleError(InvalidValue());
3449 return false;
3450 }
3451 break;
3452 }
3453 default:
3454 context->handleError(InvalidEnum());
3455 return false;
3456 }
3457
3458 Program *programObject = GetValidProgram(context, program);
3459 if (!programObject)
3460 {
3461 return false;
3462 }
3463
3464 return true;
3465}
3466
3467bool ValidateGetTransformFeedbackVarying(Context *context,
3468 GLuint program,
3469 GLuint index,
3470 GLsizei bufSize,
3471 GLsizei *length,
3472 GLsizei *size,
3473 GLenum *type,
3474 GLchar *name)
3475{
3476 if (context->getClientMajorVersion() < 3)
3477 {
3478 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3479 return false;
3480 }
3481
3482 if (bufSize < 0)
3483 {
3484 ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
3485 return false;
3486 }
3487
3488 Program *programObject = GetValidProgram(context, program);
3489 if (!programObject)
3490 {
3491 return false;
3492 }
3493
3494 if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
3495 {
3496 context->handleError(InvalidValue());
3497 return false;
3498 }
3499
3500 return true;
3501}
3502
3503bool ValidateBindTransformFeedback(Context *context, GLenum target, GLuint id)
3504{
3505 if (context->getClientMajorVersion() < 3)
3506 {
3507 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3508 return false;
3509 }
3510
3511 switch (target)
3512 {
3513 case GL_TRANSFORM_FEEDBACK:
3514 {
3515 // Cannot bind a transform feedback object if the current one is started and not
3516 // paused (3.0.2 pg 85 section 2.14.1)
3517 TransformFeedback *curTransformFeedback =
3518 context->getGLState().getCurrentTransformFeedback();
3519 if (curTransformFeedback && curTransformFeedback->isActive() &&
3520 !curTransformFeedback->isPaused())
3521 {
3522 context->handleError(InvalidOperation());
3523 return false;
3524 }
3525
3526 // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
3527 // 2.14.1)
3528 if (!context->isTransformFeedbackGenerated(id))
3529 {
3530 ANGLE_VALIDATION_ERR(context, InvalidOperation(), TransformFeedbackDoesNotExist);
3531 return false;
3532 }
3533 }
3534 break;
3535
3536 default:
3537 context->handleError(InvalidEnum());
3538 return false;
3539 }
3540
3541 return true;
3542}
3543
3544bool ValidateIsTransformFeedback(Context *context, GLuint id)
3545{
3546 if (context->getClientMajorVersion() < 3)
3547 {
3548 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3549 return false;
3550 }
3551
3552 return true;
3553}
3554
3555bool ValidatePauseTransformFeedback(Context *context)
3556{
3557 if (context->getClientMajorVersion() < 3)
3558 {
3559 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3560 return false;
3561 }
3562
3563 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3564 ASSERT(transformFeedback != nullptr);
3565
3566 // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
3567 if (!transformFeedback->isActive() || transformFeedback->isPaused())
3568 {
3569 context->handleError(InvalidOperation());
3570 return false;
3571 }
3572
3573 return true;
3574}
3575
3576bool ValidateResumeTransformFeedback(Context *context)
3577{
3578 if (context->getClientMajorVersion() < 3)
3579 {
3580 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3581 return false;
3582 }
3583
3584 TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
3585 ASSERT(transformFeedback != nullptr);
3586
3587 // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
3588 if (!transformFeedback->isActive() || !transformFeedback->isPaused())
3589 {
3590 context->handleError(InvalidOperation());
3591 return false;
3592 }
3593
3594 return true;
3595}
3596
Jamie Madill12e957f2017-08-26 21:42:26 -04003597bool ValidateVertexAttribI4i(Context *context, GLuint index, GLint x, GLint y, GLint z, GLint w)
3598{
3599 if (context->getClientMajorVersion() < 3)
3600 {
3601 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3602 return false;
3603 }
3604
3605 return ValidateVertexAttribIndex(context, index);
3606}
3607
3608bool ValidateVertexAttribI4ui(Context *context,
3609 GLuint index,
3610 GLuint x,
3611 GLuint y,
3612 GLuint z,
3613 GLuint w)
3614{
3615 if (context->getClientMajorVersion() < 3)
3616 {
3617 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3618 return false;
3619 }
3620
3621 return ValidateVertexAttribIndex(context, index);
3622}
3623
3624bool ValidateVertexAttribI4iv(Context *context, GLuint index, const GLint *v)
3625{
3626 if (context->getClientMajorVersion() < 3)
3627 {
3628 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3629 return false;
3630 }
3631
3632 return ValidateVertexAttribIndex(context, index);
3633}
3634
3635bool ValidateVertexAttribI4uiv(Context *context, GLuint index, const GLuint *v)
3636{
3637 if (context->getClientMajorVersion() < 3)
3638 {
3639 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3640 return false;
3641 }
3642
3643 return ValidateVertexAttribIndex(context, index);
3644}
3645
3646bool ValidateGetFragDataLocation(Context *context, GLuint program, const GLchar *name)
3647{
3648 if (context->getClientMajorVersion() < 3)
3649 {
3650 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3651 return false;
3652 }
3653
3654 Program *programObject = GetValidProgram(context, program);
3655 if (!programObject)
3656 {
3657 return false;
3658 }
3659
3660 if (!programObject->isLinked())
3661 {
3662 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
3663 return false;
3664 }
3665
3666 return true;
3667}
3668
3669bool ValidateGetUniformIndices(Context *context,
3670 GLuint program,
3671 GLsizei uniformCount,
3672 const GLchar *const *uniformNames,
3673 GLuint *uniformIndices)
3674{
3675 if (context->getClientMajorVersion() < 3)
3676 {
3677 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3678 return false;
3679 }
3680
3681 if (uniformCount < 0)
3682 {
3683 context->handleError(InvalidValue());
3684 return false;
3685 }
3686
3687 Program *programObject = GetValidProgram(context, program);
3688 if (!programObject)
3689 {
3690 return false;
3691 }
3692
3693 return true;
3694}
3695
3696bool ValidateGetActiveUniformsiv(Context *context,
3697 GLuint program,
3698 GLsizei uniformCount,
3699 const GLuint *uniformIndices,
3700 GLenum pname,
3701 GLint *params)
3702{
3703 if (context->getClientMajorVersion() < 3)
3704 {
3705 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3706 return false;
3707 }
3708
3709 if (uniformCount < 0)
3710 {
3711 context->handleError(InvalidValue());
3712 return false;
3713 }
3714
3715 Program *programObject = GetValidProgram(context, program);
3716 if (!programObject)
3717 {
3718 return false;
3719 }
3720
3721 switch (pname)
3722 {
3723 case GL_UNIFORM_TYPE:
3724 case GL_UNIFORM_SIZE:
Bryan Bernhart22f7aaf2018-08-23 14:13:51 -07003725 break;
Jamie Madill12e957f2017-08-26 21:42:26 -04003726 case GL_UNIFORM_NAME_LENGTH:
Bryan Bernhart22f7aaf2018-08-23 14:13:51 -07003727 if (context->getExtensions().webglCompatibility)
3728 {
3729 ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
3730 return false;
3731 }
3732 break;
Jamie Madill12e957f2017-08-26 21:42:26 -04003733 case GL_UNIFORM_BLOCK_INDEX:
3734 case GL_UNIFORM_OFFSET:
3735 case GL_UNIFORM_ARRAY_STRIDE:
3736 case GL_UNIFORM_MATRIX_STRIDE:
3737 case GL_UNIFORM_IS_ROW_MAJOR:
3738 break;
3739
3740 default:
3741 context->handleError(InvalidEnum());
3742 return false;
3743 }
3744
3745 if (uniformCount > programObject->getActiveUniformCount())
3746 {
3747 context->handleError(InvalidValue());
3748 return false;
3749 }
3750
3751 for (int uniformId = 0; uniformId < uniformCount; uniformId++)
3752 {
3753 const GLuint index = uniformIndices[uniformId];
3754
3755 if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
3756 {
3757 context->handleError(InvalidValue());
3758 return false;
3759 }
3760 }
3761
3762 return true;
3763}
3764
3765bool ValidateGetUniformBlockIndex(Context *context, GLuint program, const GLchar *uniformBlockName)
3766{
3767 if (context->getClientMajorVersion() < 3)
3768 {
3769 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3770 return false;
3771 }
3772
3773 Program *programObject = GetValidProgram(context, program);
3774 if (!programObject)
3775 {
3776 return false;
3777 }
3778
3779 return true;
3780}
3781
3782bool ValidateGetActiveUniformBlockiv(Context *context,
3783 GLuint program,
3784 GLuint uniformBlockIndex,
3785 GLenum pname,
3786 GLint *params)
3787{
3788 return ValidateGetActiveUniformBlockivBase(context, program, uniformBlockIndex, pname, nullptr);
3789}
3790
3791bool ValidateGetActiveUniformBlockName(Context *context,
3792 GLuint program,
3793 GLuint uniformBlockIndex,
3794 GLsizei bufSize,
3795 GLsizei *length,
3796 GLchar *uniformBlockName)
3797{
3798 if (context->getClientMajorVersion() < 3)
3799 {
3800 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3801 return false;
3802 }
3803
3804 Program *programObject = GetValidProgram(context, program);
3805 if (!programObject)
3806 {
3807 return false;
3808 }
3809
3810 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3811 {
3812 context->handleError(InvalidValue());
3813 return false;
3814 }
3815
3816 return true;
3817}
3818
3819bool ValidateUniformBlockBinding(Context *context,
3820 GLuint program,
3821 GLuint uniformBlockIndex,
3822 GLuint uniformBlockBinding)
3823{
3824 if (context->getClientMajorVersion() < 3)
3825 {
3826 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3827 return false;
3828 }
3829
3830 if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
3831 {
3832 context->handleError(InvalidValue());
3833 return false;
3834 }
3835
3836 Program *programObject = GetValidProgram(context, program);
3837 if (!programObject)
3838 {
3839 return false;
3840 }
3841
3842 // if never linked, there won't be any uniform blocks
3843 if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
3844 {
3845 context->handleError(InvalidValue());
3846 return false;
3847 }
3848
3849 return true;
3850}
3851
3852bool ValidateDrawArraysInstanced(Context *context,
Jamie Madill493f9572018-05-24 19:52:15 -04003853 PrimitiveMode mode,
Jamie Madill12e957f2017-08-26 21:42:26 -04003854 GLint first,
3855 GLsizei count,
3856 GLsizei primcount)
3857{
3858 if (context->getClientMajorVersion() < 3)
3859 {
3860 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3861 return false;
3862 }
3863
3864 return ValidateDrawArraysInstancedBase(context, mode, first, count, primcount);
3865}
3866
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003867bool ValidateFenceSync(Context *context, GLenum condition, GLbitfield flags)
3868{
3869 if (context->getClientMajorVersion() < 3)
3870 {
3871 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3872 return false;
3873 }
3874
3875 if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
3876 {
3877 context->handleError(InvalidEnum());
3878 return false;
3879 }
3880
3881 if (flags != 0)
3882 {
3883 context->handleError(InvalidValue());
3884 return false;
3885 }
3886
3887 return true;
3888}
3889
3890bool ValidateIsSync(Context *context, GLsync sync)
3891{
3892 if (context->getClientMajorVersion() < 3)
3893 {
3894 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3895 return false;
3896 }
3897
3898 return true;
3899}
3900
3901bool ValidateDeleteSync(Context *context, GLsync sync)
3902{
3903 if (context->getClientMajorVersion() < 3)
3904 {
3905 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3906 return false;
3907 }
3908
Jamie Madill70b5bb02017-08-28 13:32:37 -04003909 if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003910 {
3911 context->handleError(InvalidValue());
3912 return false;
3913 }
3914
3915 return true;
3916}
3917
3918bool ValidateClientWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3919{
3920 if (context->getClientMajorVersion() < 3)
3921 {
3922 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3923 return false;
3924 }
3925
3926 if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
3927 {
3928 context->handleError(InvalidValue());
3929 return false;
3930 }
3931
Jamie Madill70b5bb02017-08-28 13:32:37 -04003932 Sync *clientWaitSync = context->getSync(sync);
3933 if (!clientWaitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003934 {
3935 context->handleError(InvalidValue());
3936 return false;
3937 }
3938
3939 return true;
3940}
3941
3942bool ValidateWaitSync(Context *context, GLsync sync, GLbitfield flags, GLuint64 timeout)
3943{
3944 if (context->getClientMajorVersion() < 3)
3945 {
3946 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3947 return false;
3948 }
3949
3950 if (flags != 0)
3951 {
3952 context->handleError(InvalidValue());
3953 return false;
3954 }
3955
3956 if (timeout != GL_TIMEOUT_IGNORED)
3957 {
3958 context->handleError(InvalidValue());
3959 return false;
3960 }
3961
Jamie Madill70b5bb02017-08-28 13:32:37 -04003962 Sync *waitSync = context->getSync(sync);
3963 if (!waitSync)
Jamie Madill7f0c5a42017-08-26 22:43:26 -04003964 {
3965 context->handleError(InvalidValue());
3966 return false;
3967 }
3968
3969 return true;
3970}
3971
3972bool ValidateGetInteger64v(Context *context, GLenum pname, GLint64 *params)
3973{
3974 if (context->getClientMajorVersion() < 3)
3975 {
3976 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
3977 return false;
3978 }
3979
3980 GLenum nativeType = GL_NONE;
3981 unsigned int numParams = 0;
3982 if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
3983 {
3984 return false;
3985 }
3986
3987 return true;
3988}
3989
Jamie Madill3ef140a2017-08-26 23:11:21 -04003990bool ValidateIsSampler(Context *context, GLuint sampler)
3991{
3992 if (context->getClientMajorVersion() < 3)
3993 {
Yunchao Hef0fd87d2017-09-12 04:55:05 +08003994 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
Jamie Madill3ef140a2017-08-26 23:11:21 -04003995 return false;
3996 }
3997
3998 return true;
3999}
4000
4001bool ValidateBindSampler(Context *context, GLuint unit, GLuint sampler)
4002{
4003 if (context->getClientMajorVersion() < 3)
4004 {
4005 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
4006 return false;
4007 }
4008
4009 if (sampler != 0 && !context->isSampler(sampler))
4010 {
4011 context->handleError(InvalidOperation());
4012 return false;
4013 }
4014
4015 if (unit >= context->getCaps().maxCombinedTextureImageUnits)
4016 {
4017 context->handleError(InvalidValue());
4018 return false;
4019 }
4020
4021 return true;
4022}
4023
4024bool ValidateVertexAttribDivisor(Context *context, GLuint index, GLuint divisor)
4025{
4026 if (context->getClientMajorVersion() < 3)
4027 {
4028 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
4029 return false;
4030 }
4031
4032 return ValidateVertexAttribIndex(context, index);
4033}
4034
4035bool ValidateTexStorage2D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004036 TextureType target,
Jamie Madill3ef140a2017-08-26 23:11:21 -04004037 GLsizei levels,
4038 GLenum internalformat,
4039 GLsizei width,
4040 GLsizei height)
4041{
4042 if (context->getClientMajorVersion() < 3)
4043 {
4044 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
4045 return false;
4046 }
4047
4048 if (!ValidateES3TexStorage2DParameters(context, target, levels, internalformat, width, height,
4049 1))
4050 {
4051 return false;
4052 }
4053
4054 return true;
4055}
4056
4057bool ValidateTexStorage3D(Context *context,
Corentin Wallezf0e89be2017-11-08 14:00:32 -08004058 TextureType target,
Jamie Madill3ef140a2017-08-26 23:11:21 -04004059 GLsizei levels,
4060 GLenum internalformat,
4061 GLsizei width,
4062 GLsizei height,
4063 GLsizei depth)
4064{
4065 if (context->getClientMajorVersion() < 3)
4066 {
4067 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
4068 return false;
4069 }
4070
4071 if (!ValidateES3TexStorage3DParameters(context, target, levels, internalformat, width, height,
4072 depth))
4073 {
4074 return false;
4075 }
4076
4077 return true;
4078}
4079
Jamie Madill5b772312018-03-08 20:28:32 -05004080bool ValidateGetBufferParameteri64v(Context *context,
Corentin Wallez336129f2017-10-17 15:55:40 -04004081 BufferBinding target,
Jamie Madill9696d072017-08-26 23:19:57 -04004082 GLenum pname,
4083 GLint64 *params)
4084{
4085 return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
4086}
4087
4088bool ValidateGetSamplerParameterfv(Context *context, GLuint sampler, GLenum pname, GLfloat *params)
4089{
4090 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4091}
4092
4093bool ValidateGetSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, GLint *params)
4094{
4095 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4096}
4097
Till Rathmannb8543632018-10-02 19:46:14 +02004098bool ValidateGetSamplerParameterIivOES(Context *context,
4099 GLuint sampler,
4100 GLenum pname,
4101 const GLint *params)
4102{
4103 if (context->getClientMajorVersion() < 3)
4104 {
4105 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
4106 return false;
4107 }
4108 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4109}
4110
4111bool ValidateGetSamplerParameterIuivOES(Context *context,
4112 GLuint sampler,
4113 GLenum pname,
4114 const GLuint *params)
4115{
4116 if (context->getClientMajorVersion() < 3)
4117 {
4118 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
4119 return false;
4120 }
4121 return ValidateGetSamplerParameterBase(context, sampler, pname, nullptr);
4122}
4123
Jamie Madill9696d072017-08-26 23:19:57 -04004124bool ValidateSamplerParameterf(Context *context, GLuint sampler, GLenum pname, GLfloat param)
4125{
Till Rathmannb8543632018-10-02 19:46:14 +02004126 return ValidateSamplerParameterBase(context, sampler, pname, -1, false, &param);
Jamie Madill9696d072017-08-26 23:19:57 -04004127}
4128
4129bool ValidateSamplerParameterfv(Context *context,
4130 GLuint sampler,
4131 GLenum pname,
4132 const GLfloat *params)
4133{
Till Rathmannb8543632018-10-02 19:46:14 +02004134 return ValidateSamplerParameterBase(context, sampler, pname, -1, true, params);
Jamie Madill9696d072017-08-26 23:19:57 -04004135}
4136
4137bool ValidateSamplerParameteri(Context *context, GLuint sampler, GLenum pname, GLint param)
4138{
Till Rathmannb8543632018-10-02 19:46:14 +02004139 return ValidateSamplerParameterBase(context, sampler, pname, -1, false, &param);
Jamie Madill9696d072017-08-26 23:19:57 -04004140}
4141
4142bool ValidateSamplerParameteriv(Context *context, GLuint sampler, GLenum pname, const GLint *params)
4143{
Till Rathmannb8543632018-10-02 19:46:14 +02004144 return ValidateSamplerParameterBase(context, sampler, pname, -1, true, params);
4145}
4146
4147bool ValidateSamplerParameterIivOES(Context *context,
4148 GLuint sampler,
4149 GLenum pname,
4150 const GLint *params)
4151{
4152 if (context->getClientMajorVersion() < 3)
4153 {
4154 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
4155 return false;
4156 }
4157 return ValidateSamplerParameterBase(context, sampler, pname, -1, true, params);
4158}
4159
4160bool ValidateSamplerParameterIuivOES(Context *context,
4161 GLuint sampler,
4162 GLenum pname,
4163 const GLuint *params)
4164{
4165 if (context->getClientMajorVersion() < 3)
4166 {
4167 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
4168 return false;
4169 }
4170 return ValidateSamplerParameterBase(context, sampler, pname, -1, true, params);
Jamie Madill9696d072017-08-26 23:19:57 -04004171}
4172
4173bool ValidateGetVertexAttribIiv(Context *context, GLuint index, GLenum pname, GLint *params)
4174{
4175 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4176}
4177
4178bool ValidateGetVertexAttribIuiv(Context *context, GLuint index, GLenum pname, GLuint *params)
4179{
4180 return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, true);
4181}
4182
4183bool ValidateGetInternalformativ(Context *context,
4184 GLenum target,
4185 GLenum internalformat,
4186 GLenum pname,
4187 GLsizei bufSize,
4188 GLint *params)
4189{
4190 return ValidateGetInternalFormativBase(context, target, internalformat, pname, bufSize,
4191 nullptr);
4192}
4193
Olli Etuaho0ca09752018-09-24 11:00:50 +03004194bool ValidateBindFragDataLocationIndexedEXT(Context *context,
4195 GLuint program,
4196 GLuint colorNumber,
4197 GLuint index,
4198 const char *name)
4199{
4200 if (!context->getExtensions().blendFuncExtended)
4201 {
4202 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
4203 return false;
4204 }
4205 if (context->getClientMajorVersion() < 3)
4206 {
4207 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
4208 return false;
4209 }
4210 if (index < 0 || index > 1)
4211 {
4212 // This error is not explicitly specified but the spec does say that "<index> may be zero or
4213 // one to specify that the color be used as either the first or second color input to the
4214 // blend equation, respectively"
4215 ANGLE_VALIDATION_ERR(context, InvalidValue(), FragDataBindingIndexOutOfRange);
4216 return false;
4217 }
4218 if (index == 1)
4219 {
4220 if (colorNumber >= context->getExtensions().maxDualSourceDrawBuffers)
4221 {
4222 ANGLE_VALIDATION_ERR(context, InvalidValue(),
4223 ColorNumberGreaterThanMaxDualSourceDrawBuffers);
4224 return false;
4225 }
4226 }
4227 else
4228 {
4229 if (colorNumber >= context->getCaps().maxDrawBuffers)
4230 {
4231 ANGLE_VALIDATION_ERR(context, InvalidValue(), ColorNumberGreaterThanMaxDrawBuffers);
4232 return false;
4233 }
4234 }
4235 Program *programObject = GetValidProgram(context, program);
4236 if (!programObject)
4237 {
4238 return false;
4239 }
4240 return true;
4241}
4242
4243bool ValidateBindFragDataLocationEXT(Context *context,
4244 GLuint program,
4245 GLuint colorNumber,
4246 const char *name)
4247{
4248 return ValidateBindFragDataLocationIndexedEXT(context, program, colorNumber, 0u, name);
4249}
4250
4251bool ValidateGetFragDataIndexEXT(Context *context, GLuint program, const char *name)
4252{
4253 if (!context->getExtensions().blendFuncExtended)
4254 {
4255 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
4256 return false;
4257 }
4258 if (context->getClientMajorVersion() < 3)
4259 {
4260 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES3Required);
4261 return false;
4262 }
4263 Program *programObject = GetValidProgram(context, program);
4264 if (!programObject)
4265 {
4266 return false;
4267 }
4268 if (!programObject->isLinked())
4269 {
4270 ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
4271 return false;
4272 }
4273 return true;
4274}
4275
Yizhou Jiang7818a852018-09-06 15:02:04 +08004276bool ValidateTexStorage2DMultisampleANGLE(Context *context,
4277 TextureType target,
4278 GLsizei samples,
4279 GLint internalFormat,
4280 GLsizei width,
4281 GLsizei height,
4282 GLboolean fixedSampleLocations)
4283{
4284 if (!context->getExtensions().textureMultisample)
4285 {
4286 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
4287 MultisampleTextureExtensionOrES31Required);
4288 return false;
4289 }
4290
4291 return ValidateTexStorage2DMultisampleBase(context, target, samples, internalFormat, width,
4292 height);
4293}
4294
Yizhou Jiangc0b6c632018-09-06 15:02:04 +08004295bool ValidateGetTexLevelParameterfvANGLE(Context *context,
4296 TextureTarget target,
4297 GLint level,
4298 GLenum pname,
4299 GLfloat *params)
4300{
4301 if (!context->getExtensions().textureMultisample)
4302 {
4303 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
4304 MultisampleTextureExtensionOrES31Required);
4305 return false;
4306 }
4307
4308 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
4309}
4310
4311bool ValidateGetTexLevelParameterivANGLE(Context *context,
4312 TextureTarget target,
4313 GLint level,
4314 GLenum pname,
4315 GLint *params)
4316{
4317 if (!context->getExtensions().textureMultisample)
4318 {
4319 ANGLE_VALIDATION_ERR(context, InvalidOperation(),
4320 MultisampleTextureExtensionOrES31Required);
4321 return false;
4322 }
4323
4324 return ValidateGetTexLevelParameterBase(context, target, level, pname, nullptr);
4325}
4326
Jamie Madillc29968b2016-01-20 11:17:23 -05004327} // namespace gl